@prefix bsdo:  <https://w3id.org/bsdo#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix skos:  <http://www.w3.org/2004/02/skos/core#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix bat:   <https://w3id.org/emmo/domain/battery#> .
@prefix echem: <https://w3id.org/emmo/domain/electrochemistry#> .
@prefix chem:  <https://w3id.org/emmo/domain/chemical-substance#> .
@prefix gpo:   <https://gpo.ontology.link/> .
@prefix sosa:  <http://www.w3.org/ns/sosa/> .
@prefix prov:  <http://www.w3.org/ns/prov#> .
@prefix vann:  <http://purl.org/vocab/vann/> .

#################################################################
#  BSDO — Battery Swap Domain Ontology
#  Terminology (TBox)
#
#  A domain ontology for battery swap ecosystems for electric two-wheelers.
#  Class definitions are grounded in Formal Concept Analysis over artefacts
#  observed in two independently operated ecosystems. Where a class comes
#  from a formal concept, only concepts robust across both readings of the
#  incomplete observational data were promoted.
#
#  Not every class is a formal concept, and the difference is recorded
#  rather than glossed. Each class carries two independent annotations,
#  because where a concept came from and whether it is tied to an external
#  vocabulary are different questions and a single value cannot record both.
#
#  bsdo:derivationPath - where the concept came from:
#
#    lattice    - a formal concept robust under both readings, with its
#                 context, extent and intent named
#    composed   - a concept from one context combined with an observation
#                 not present in that context
#    reuse      - taken from an aligned external vocabulary
#    structural - scaffolding: value partitions, n-ary reifications,
#                 genus nodes, and role classes
#
#  bsdo:reuseStatus - how the class stands to external vocabularies:
#
#    reused     - the concept itself was taken from an external vocabulary
#    aligned    - defined here, and tied to an external term by subsumption
#                 or by reference
#    native     - defined here, with no external counterpart found
#
#  Together with rdfs:comment, this lets a reader reconstruct the path from
#  an observed fact to a class without access to the authors.
#
#  Aligned to the EMMO domain-battery, domain-electrochemistry and
#  chemical-substance modules, to the General Process Ontology (GPO), and to
#  the W3C SOSA and PROV-O vocabularies.
#  Licence: CC-BY 4.0
#################################################################

<https://w3id.org/bsdo> rdf:type owl:Ontology ;
    owl:versionIRI <https://w3id.org/bsdo/0.4.1> ;
    owl:versionInfo "0.4.1" ;
    owl:priorVersion <https://w3id.org/bsdo/0.4.0> ;
    dcterms:title "BSDO — Battery Swap Domain Ontology"@en ;
    dcterms:creator "Sido Dea Auvia" ;
    dcterms:license <https://creativecommons.org/licenses/by/4.0/> ;
    vann:preferredNamespacePrefix "bsdo" ;
    vann:preferredNamespaceUri "https://w3id.org/bsdo#" ;
    dcterms:created "2026-07-26"^^xsd:date ;
    dcterms:issued "2026-08-15"^^xsd:date ;
    dcterms:publisher "Zenodo" ;
    dcterms:identifier <https://doi.org/10.5281/zenodo.21683493> ;
    dcterms:bibliographicCitation "Dea Auvia, S. (2026). BSDO: Battery Swap Domain Ontology. Zenodo. https://doi.org/10.5281/zenodo.21683493" ;
    rdfs:comment """Domain ontology for battery swap ecosystems for electric two-wheelers.
TBox derived from Formal Concept Analysis over four artefact-family contexts (batteries,
station devices, service flows, vehicles), following METHONTOLOGY with FCA substituting the
informal conceptualisation activity. Where a class comes from a formal concept, only concepts
robust across pessimistic and optimistic readings of unarticulated data were promoted. Classes
that are not formal concepts are marked as such: every class carries bsdo:derivationPath, whose
value begins with one of lattice, composed, reuse or structural. Every class additionally carries
bsdo:reuseStatus, recording separately whether it is reused, aligned or native, since a class may
be derived from a formal concept and still borrow an external superclass.
Aligned to EMMO domain-battery, domain-electrochemistry and chemical-substance (the vocabulary
layer profiled by BattINFO), to the General Process Ontology, and to W3C SOSA and PROV-O."""@en .

#################################################################
#  0. PROVENANCE ANNOTATION
#################################################################

bsdo:derivationPath rdf:type owl:AnnotationProperty ;
    rdfs:label "derivation path"@en ;
    rdfs:comment """How the annotated class was obtained. The value opens with one of four
provenance kinds: 'lattice' (a formal concept robust under both readings of the unarticulated
cells, with context, extent and intent named), 'composed' (a concept from one context combined
with an observation not carried by that context), 'reuse' (taken from an aligned external
vocabulary), or 'structural' (scaffolding: value partitions, n-ary reifications, genus nodes and
role classes). Extents are given as object identifiers of the published formal contexts, so that
each claim can be checked against context_K*.csv and recomputed with lattice.py."""@en .

bsdo:reuseStatus rdf:type owl:AnnotationProperty ;
    rdfs:label "reuse status"@en ;
    rdfs:comment """How the annotated class stands in relation to external vocabularies, recorded
separately from bsdo:derivationPath because the two answer different questions. The value is one
of 'reused' (the concept itself was taken from an external vocabulary), 'aligned' (defined here
and tied to an external term, whether by rdfs:subClassOf or by rdfs:seeAlso), or 'native'
(defined here, with no external counterpart found). A class may be derived from a formal concept
and still be aligned: the lithium-ion battery class is one such case. Reporting the two axes in a
single value would force a choice between them and would understate the alignment actually
present in the artefact."""@en .

#################################################################
#  1. SERVICE EVENTS
#     Top-level split: object transfer versus energy transfer
#################################################################

bsdo:ServiceEvent rdf:type owl:Class ;
    bsdo:derivationPath "structural: Genus for the K3 artefact family; the node under which the transfer split is drawn. Not itself a closed concept."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Service Event"@en ;
    rdfs:comment "A bounded event in which energy is supplied to a vehicle, either by exchanging the physical carrier or by transferring energy into a carrier that remains in place."@en .

bsdo:ObjectTransferEvent rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K3 concept, extent {f1,f2,f3,f4,f5,f6}, intent {object transfer}. Robust under both readings; extent spans both ecosystems."@en ;
    bsdo:reuseStatus "aligned" ;
    rdfs:subClassOf bsdo:ServiceEvent ,
                    gpo:GPO_890abbc3_d75b_4f3f_a5b7_e1b0e898655b ;   # gpo:MatterTransportProcess
    rdfs:label "Object Transfer Event"@en ;
    rdfs:comment "Events in which the physical carrier is exchanged. Derived from a formal concept spanning six service flows drawn from both ecosystems, so the distinction is not an artefact of one operator's product line. The matter-versus-energy transfer distinction is not introduced here: it is a standing division of the General Process Ontology, and this class specialises the matter side of it to the swap domain."@en .

bsdo:EnergyTransferEvent rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K3 concept, extent {f7}, intent includes {energy transfer}. Robust under both readings."@en ;
    bsdo:reuseStatus "aligned" ;
    rdfs:subClassOf bsdo:ServiceEvent ,
                    gpo:GPO_04b6cbaf_a63a_4130_974a_8cc9c2a612f1 ;   # gpo:EnergyTransportProcess
    rdfs:label "Energy Transfer Event"@en ;
    rdfs:comment "Events in which energy is transferred without exchanging the physical carrier. Specialises the energy side of the General Process Ontology transport division, the counterpart of the matter side taken by Object Transfer Event."@en .

[] rdf:type owl:AllDisjointClasses ;
   owl:members ( bsdo:ObjectTransferEvent bsdo:EnergyTransferEvent ) .

bsdo:SwapEvent rdf:type owl:Class ;
    bsdo:derivationPath "composed: K3: the object-transfer flows lacking {same pack returned}. A complement within a robust concept, not itself a closed extent."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:ObjectTransferEvent ;
    rdfs:label "Swap Event"@en ;
    rdfs:comment "An exchange in which the outgoing pack does not return to the customer."@en .

bsdo:LoanEvent rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K3 concept, extent {f6}, intent includes {borrowed pack, ownership retained, same pack returned}. Robust under both readings."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:ObjectTransferEvent ;
    rdfs:label "Loan Event"@en ;
    skos:altLabel "Tukar Titip"@id ;
    rdfs:comment "An exchange in which the customer receives a borrowed pack and later returns it, within a stated deadline, in exchange for their own."@en .

bsdo:DepositChargingEvent rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K3 concept, extent {f7}, intent includes {energy transfer, ownership retained, same pack returned}. Robust under both readings."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:EnergyTransferEvent ;
    rdfs:label "Deposit Charging Event"@en ;
    skos:altLabel "SCB"@id , "Sistem Charge Battery"@id ;
    rdfs:comment "The customer's own pack is deposited in a cabinet for charging and later retrieved."@en .

bsdo:EnrolmentGatedObjectTransfer rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K3 concept, extent {f4,f5,f6}, intent {object transfer, available only to packs holding network status, paid membership required, cabinet scan required}. Robust under both readings. Extent lies within one ecosystem: unlike the transfer split above, this concept does not span both."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:ObjectTransferEvent ;
    rdfs:label "Enrolment-Gated Object Transfer"@en ;
    rdfs:comment "Exchanges that a customer may perform only while the pack holds network status and the customer holds a paid membership. Stated as a primitive class: enrolment status is a property of the pack rather than of the event, so the intent cannot be expressed as a restriction on the event without inventing a relation that was not observed. The class is retained because it records where the right to obtain a swap is conditioned on standing rather than on the state of the pack, which is the service-side counterpart of the ownership question."@en .

#  --- Defined class, crossing the split above ---
#  One member is an object transfer and the other an energy transfer, yet both
#  share the same custody structure. The class is therefore not placed under
#  either branch; membership is inferred.

bsdo:CustodyPreservingEvent rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K3 concept, extent {f6,f7}, intent includes {6-hour limit, ownership retained, same pack returned}. Robust under both readings. Extent straddles the disjoint transfer split, so the class is defined rather than subsumed; membership is computed by the reasoner."@en ;
    bsdo:reuseStatus "native" ;
    owl:equivalentClass [ rdf:type owl:Class ;
        owl:intersectionOf ( bsdo:ServiceEvent
                             [ rdf:type owl:Restriction ;
                               owl:onProperty bsdo:hasCustodyDeadlineHours ;
                               owl:minCardinality "1"^^xsd:nonNegativeInteger ]
                             [ rdf:type owl:Restriction ;
                               owl:onProperty bsdo:returnsPackTo ;
                               owl:minCardinality "1"^^xsd:nonNegativeInteger ] ) ] ;
    rdfs:label "Custody-Preserving Event"@en ;
    rdfs:comment "Events in which custody transfers temporarily while ownership does not. Membership is inferred rather than asserted, and deliberately crosses the object-transfer / energy-transfer partition: in a loan event the customer holds an operator's pack, whereas in a deposit-charging event the operator holds the customer's pack."@en .

#################################################################
#  2. DEVICES
#################################################################

bsdo:BatteryHandlingDevice rdf:type owl:Class ;
    bsdo:derivationPath "structural: Genus for the K2 artefact family. Not itself a closed concept."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Battery Handling Device"@en .

bsdo:SwapDevice rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K2 concept, extent {s1,s2,s4}, intent {exchange, booking, host partner}. Robust under both readings; extent spans both ecosystems."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:BatteryHandlingDevice ;
    rdfs:label "Swap Device"@en ;
    skos:altLabel "BSS"@id , "Swap Poin"@id , "SGB"@id , "kabinet"@id ;
    rdfs:comment "A device that exchanges battery packs."@en .

bsdo:ChargingDevice rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K2 concept, extent {s3,s4}, intent {charging}. Robust under both readings; extent spans both ecosystems, which is why this class is not disjoint from Swap Device."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:BatteryHandlingDevice ;
    rdfs:label "Charging Device"@en ;
    rdfs:comment "A device that transfers energy into a battery pack in place."@en .

#  SwapDevice and ChargingDevice are deliberately NOT disjoint.
#  One ecosystem separates exchange and charging across distinct appliances;
#  the other performs both at a single cabinet. Declaring disjointness would
#  render that cabinet unsatisfiable.

bsdo:DualFunctionDevice rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K2 concept, extent {s4}, intent includes both {exchange} and {charging}. Robust under both readings; defined class, membership computed by the reasoner."@en ;
    bsdo:reuseStatus "native" ;
    owl:equivalentClass [ rdf:type owl:Class ;
        owl:intersectionOf ( bsdo:SwapDevice bsdo:ChargingDevice ) ] ;
    rdfs:label "Dual-Function Device"@en ;
    rdfs:comment "A device performing both object exchange and energy transfer. One ecosystem separates these functions across distinct appliances; the other combines them in a single cabinet. The distinction becomes visible only because the two functions are modelled as separate attributes."@en .

bsdo:SlotLevelStatusExposingDevice rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K2 concept, extent {s2,s4}, intent {exchange, capacity 3-8 packs, per-slot status exposed, per-slot state of charge exposed, reservation supported, sited at a partner location}. Robust under both readings; extent spans both ecosystems."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:BatteryHandlingDevice ;
    rdfs:label "Slot-Level Status Exposing Device"@en ;
    rdfs:comment "Exchange devices of mid-range capacity that publish the state of each slot individually rather than only in aggregate. Stated as a primitive class: the ontology has no property for what a device exposes, so the intent cannot be turned into a restriction without asserting an interface model that was not observed. The class matters because per-slot disclosure is what makes a pack's location legible over time, and it is the largest cross-ecosystem concept the station context yields."@en .

bsdo:BatterySlot rdf:type owl:Class ;
    bsdo:derivationPath "structural: Introduced to carry the per-slot status observed on K2 objects s2 and s4. Native operator terms are retained as alternative labels rather than normalised away."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Battery Slot"@en ;
    skos:altLabel "Slot"@id , "Pintu"@id ;
    rdfs:comment "The two ecosystems use different native terms for this concept. Both are retained as alternative labels rather than normalised to a single term."@en .

#################################################################
#  3. BATTERIES
#################################################################

bsdo:SwappableBattery rdf:type owl:Class ;
    bsdo:derivationPath "reuse: Reuse: subclass of the Battery class of the EMMO domain-battery module. Corresponds to the K1 top concept, whose intent is empty and therefore carries no discriminating attribute of its own."@en ;
    bsdo:reuseStatus "reused" ;
    rdfs:subClassOf bat:battery_74ed2670_657d_4f0b_b0a6_3f13bc2e9c17 ;   # emmo:Battery
    rdfs:label "Swappable Battery"@en ;
    rdfs:comment "Aligned to the Battery class of the EMMO domain-battery module, which is the vocabulary layer that the BattINFO application ontology profiles."@en .

#  --- Voltage class: an attribute that does NOT determine interchange ---
bsdo:VoltageClass rdf:type owl:Class ;
    bsdo:derivationPath "structural: Value partition over the voltage attributes of K1. Not functional, since one battery model carries two declared classes."@en ;
    bsdo:reuseStatus "aligned" ;
    rdfs:seeAlso echem:electrochemistry_639b844a_e801_436b_985d_28926129ead6 ;
    rdfs:label "Nominal Voltage Class"@en ;
    rdfs:comment "Referenced to NominalVoltage in the EMMO domain-electrochemistry module. The reference is by rdfs:seeAlso rather than subsumption: the EMMO term is a quantity, whereas the members of this partition are the voltage classes operators declare, which is a coarser thing than a measured value."@en .

bsdo:VC_60V rdf:type owl:NamedIndividual , bsdo:VoltageClass ; rdfs:label "60 V"@en ;
    rdfs:comment "Source: Value-partition member; no observational source of its own."@en .
bsdo:VC_64V rdf:type owl:NamedIndividual , bsdo:VoltageClass ; rdfs:label "64 V"@en ;
    rdfs:comment "Source: Value-partition member; no observational source of its own."@en .
bsdo:VC_72V rdf:type owl:NamedIndividual , bsdo:VoltageClass ; rdfs:label "72 V"@en ;
    rdfs:comment "Source: Value-partition member; no observational source of its own."@en .

#  --- Cell chemistry: the dimension that actually separates the ecosystems ---
bsdo:CellChemistry rdf:type owl:Class ;
    bsdo:derivationPath "structural: Value partition (Rector 2005) over the chemistry attributes of K1."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Cell Chemistry"@en .

bsdo:LithiumIon rdf:type owl:NamedIndividual , bsdo:CellChemistry ;
    rdfs:label "Lithium-Ion (generic)"@en ;
    rdfs:comment "Source: Value-partition member; no observational source of its own. Not aligned at substance level: the EMMO chemical-substance module enumerates specific electrode and electrolyte materials, and the operator declares only a generic cell family without naming a cathode material, so no substance-level target corresponds. The lithium-ion side is instead aligned at battery level, on Lithium-Ion Swappable Battery."@en .
bsdo:LithiumIronPhosphate rdf:type owl:NamedIndividual , bsdo:CellChemistry ;
    rdfs:label "LiFePO4"@en ;
    rdfs:seeAlso chem:substance_aa8e9cc4_5f66_4307_b1c8_26fac7653a90 ;
    rdfs:comment "Source: Value-partition member; no observational source of its own. Aligned to LithiumIronPhosphate (altLabel LFP) in the EMMO chemical-substance module, by reference rather than import, following the pattern used for the electrochemistry quantities. The target was verified against the module's published file."@en .
[] rdf:type owl:AllDifferent ;
   owl:distinctMembers ( bsdo:LithiumIon bsdo:LithiumIronPhosphate ) .

bsdo:LithiumIonSwappableBattery rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K1 concept, extent {b1,b2}, intent includes {Li-ion, capacity in kWh}. Robust under both readings."@en ;
    bsdo:reuseStatus "aligned" ;
    owl:equivalentClass [ rdf:type owl:Class ;
        owl:intersectionOf ( bsdo:SwappableBattery
                             [ rdf:type owl:Restriction ;
                               owl:onProperty bsdo:hasCellChemistry ;
                               owl:hasValue bsdo:LithiumIon ] ) ] ;
    rdfs:subClassOf bsdo:SwappableBattery ,
                    bat:battery_96addc62_ea04_449a_8237_4cd541dd8e5f ;   # emmo:LithiumIonBattery
    rdfs:label "Lithium-Ion Swappable Battery"@en ;
    rdfs:comment "The subclass axiom is stated explicitly although it is entailed by the equivalent-class definition, so that SPARQL queries over the raw graph work without a reasoner."@en .

bsdo:LFPSwappableBattery rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K1 concept, extent {b3,b4}, intent {LiFePO4, capacity in Ah}. Robust under both readings."@en ;
    bsdo:reuseStatus "native" ;
    owl:equivalentClass [ rdf:type owl:Class ;
        owl:intersectionOf ( bsdo:SwappableBattery
                             [ rdf:type owl:Restriction ;
                               owl:onProperty bsdo:hasCellChemistry ;
                               owl:hasValue bsdo:LithiumIronPhosphate ] ) ] ;
    rdfs:subClassOf bsdo:SwappableBattery ;
    rdfs:label "LiFePO4 Swappable Battery"@en .

#  --- The nominal voltage classes the two ecosystems share ---
#
#  Two classes, not one. The SWAP pack is declared 60 V by the manufacturer's
#  website and 64 V by the operator's own application, and hasVoltageClass is
#  deliberately non-functional so that both declarations stand. It therefore
#  falls in both classes, and each class also draws one Volta pack. The overlap
#  between the ecosystems is consequently non-empty whichever declaration is
#  eventually taken as authoritative, which is what the argument in the paper
#  requires. Minting only one of the two would have made that argument depend
#  on the disputed reading.

bsdo:Nominal60VBattery rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K1 concept, extent {b1,b3}, intent {60 V nominal voltage class, state of charge, unit identifier}. Robust under both readings; extent spans both ecosystems."@en ;
    bsdo:reuseStatus "native" ;
    owl:equivalentClass [ rdf:type owl:Class ;
        owl:intersectionOf ( bsdo:SwappableBattery
                             [ rdf:type owl:Restriction ;
                               owl:onProperty bsdo:hasVoltageClass ;
                               owl:hasValue bsdo:VC_60V ] ) ] ;
    rdfs:subClassOf bsdo:SwappableBattery ;
    rdfs:label "60 V Swappable Battery"@en ;
    rdfs:comment "Packs declaring a 60 V nominal voltage class. Its extent draws one pack from each ecosystem, and those two packs differ in cell chemistry, in the unit in which capacity is declared, and in every published physical attribute; they cannot be interchanged. The concept is richer than its 64 V counterpart, since the two packs share a persistent unit identifier and a reported state of charge as well as the voltage class, which is why the failure of exchange cannot be attributed to a lack of common attributes."@en .

bsdo:Nominal64VBattery rdf:type owl:Class ;
    bsdo:derivationPath "lattice: K1 concept, extent {b1,b4}, intent {64 V nominal voltage class}. Robust under both readings; extent spans both ecosystems."@en ;
    bsdo:reuseStatus "native" ;
    owl:equivalentClass [ rdf:type owl:Class ;
        owl:intersectionOf ( bsdo:SwappableBattery
                             [ rdf:type owl:Restriction ;
                               owl:onProperty bsdo:hasVoltageClass ;
                               owl:hasValue bsdo:VC_64V ] ) ] ;
    rdfs:subClassOf bsdo:SwappableBattery ;
    rdfs:label "64 V Swappable Battery"@en ;
    rdfs:comment "Packs declaring a 64 V nominal voltage class. Together with its 60 V counterpart this class carries the weight of the interoperability argument, and that is the reason both exist rather than being left implicit in the value partition: its extent draws one pack from each ecosystem, and the voltage class is the only attribute those two packs share. They differ in cell chemistry, in the unit in which capacity is declared, and in every published physical attribute, and they cannot be interchanged. A mandate written in terms of nominal voltage alone would treat them as the same case."@en .

[] rdf:type owl:AllDisjointClasses ;
   owl:members ( bsdo:LithiumIonSwappableBattery bsdo:LFPSwappableBattery ) .

#################################################################
#  4. OWNERSHIP AND CUSTODY
#################################################################

bsdo:Agent rdf:type owl:Class ; rdfs:subClassOf prov:Agent ; rdfs:label "Agent"@en ;
    bsdo:derivationPath "structural: Role scaffold; not ecosystem-bound and not a formal-context object."@en ;
    bsdo:reuseStatus "aligned" .
bsdo:Customer rdf:type owl:Class ; rdfs:subClassOf bsdo:Agent ; rdfs:label "Customer"@en ;
    bsdo:derivationPath "structural: Role scaffold; see Agent."@en ;
    bsdo:reuseStatus "native" ;
    skos:altLabel "Volters"@id .
bsdo:Operator rdf:type owl:Class ; rdfs:subClassOf bsdo:Agent ; rdfs:label "Operator"@en ;
    bsdo:derivationPath "structural: Role scaffold; see Agent."@en ;
    bsdo:reuseStatus "native" .

bsdo:operatedBy rdf:type owl:ObjectProperty ;
    rdfs:range bsdo:Operator ;
    rdfs:label "operated by"@en ;
    rdfs:comment "Relates an artefact to the operator whose ecosystem it belongs to. Ecosystem membership is what makes cross-ecosystem comparison expressible at all."@en .

bsdo:ownedBy rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range bsdo:Agent ;
    rdfs:label "owned by"@en ;
    rdfs:comment "Ownership, which persists across service events."@en .

bsdo:heldBy rdf:type owl:ObjectProperty , owl:FunctionalProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range bsdo:Agent ;
    rdfs:label "held by"@en ;
    rdfs:comment "Current physical custody. Functional: a pack is held by at most one party at a time. Custody can diverge from ownership, and changes at every exchange."@en .

bsdo:hasCustodyDeadlineHours rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:ServiceEvent ; rdfs:range xsd:decimal ;
    rdfs:label "custody deadline (hours)"@en ;
    rdfs:comment "The deadline for temporary custody, expressed in hours. Note that xsd:duration is deliberately not used: it is not part of the OWL 2 datatype map and would place the ontology outside OWL 2 DL."@en .

bsdo:returnsPackTo rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:ServiceEvent ; rdfs:range bsdo:Agent ;
    rdfs:label "returns pack to"@en .

#  --- Network enrolment status: the right to manage depends on it ---
bsdo:NetworkEnrolmentStatus rdf:type owl:Class ; rdfs:label "Network Enrolment Status"@en ;
    bsdo:derivationPath "structural: Value partition over the network-enrolment attribute observed in K3."@en ;
    bsdo:reuseStatus "native" .
bsdo:Online rdf:type owl:NamedIndividual , bsdo:NetworkEnrolmentStatus ; rdfs:label "online"@en ;
    rdfs:comment "Source: Value-partition member; no observational source of its own."@en .
bsdo:Offline rdf:type owl:NamedIndividual , bsdo:NetworkEnrolmentStatus ; rdfs:label "offline"@en ;
    rdfs:comment "Source: Value-partition member; no observational source of its own."@en .
[] rdf:type owl:AllDifferent ; owl:distinctMembers ( bsdo:Online bsdo:Offline ) .

bsdo:hasEnrolmentStatus rdf:type owl:ObjectProperty , owl:FunctionalProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range bsdo:NetworkEnrolmentStatus ;
    rdfs:label "has enrolment status"@en .

bsdo:mayBeChargedByHolder rdf:type owl:DatatypeProperty , owl:FunctionalProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range xsd:boolean ;
    rdfs:label "may be charged by holder"@en ;
    rdfs:comment "The right to charge a pack, which is separate from owning it. The same physical pack may fall under different rights regimes depending on its network enrolment status, with ownership unchanged throughout."@en .

bsdo:NetworkEnrolledBattery rdf:type owl:Class ;
    bsdo:derivationPath "composed: Composed: the {network enrolment} attribute is observed of K3 service flows, not of battery models. Applied to packs on the strength of the manufacturer documentation governing enrolled units. Defined class; membership computed by the reasoner."@en ;
    bsdo:reuseStatus "native" ;
    owl:equivalentClass [ rdf:type owl:Restriction ;
        owl:onProperty bsdo:hasEnrolmentStatus ; owl:hasValue bsdo:Online ] ;
    rdfs:subClassOf [ rdf:type owl:Restriction ;
        owl:onProperty bsdo:mayBeChargedByHolder ;
        owl:hasValue "false"^^xsd:boolean ] ;
    rdfs:label "Network-Enrolled Battery"@en ;
    rdfs:comment "A pack enrolled in an operator's network: ownership remains with the customer while the right to charge rests with the operator."@en .

#################################################################
#  5. UNIT IDENTITY
#################################################################

bsdo:hasUnitIdentifier rdf:type owl:DatatypeProperty , owl:FunctionalProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range xsd:string ;
    rdfs:label "unit identifier"@en ;
    rdfs:comment "A persistent unit identifier, independent of any vehicle. Both ecosystems maintain such identifiers, but under mutually uninterpretable schemes, and neither follows the identification standard required of battery passports by Regulation (EU) 2023/1542."@en .

bsdo:IdentifierScheme rdf:type owl:Class ; rdfs:label "Identifier Scheme"@en ;
    bsdo:derivationPath "structural: Observed per-ecosystem identifier schemes, retained as pattern only. Not a formal-context object."@en ;
    bsdo:reuseStatus "native" .
bsdo:hasIdentifierScheme rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range bsdo:IdentifierScheme .

#################################################################
#  6. STATE AT AN EVENT (bounded temporal representation)
#################################################################

bsdo:BatteryStateObservation rdf:type owl:Class ;
    bsdo:derivationPath "structural: N-ary relation pattern: reification of a pack state at one time point. A modelling construct, not a concept."@en ;
    bsdo:reuseStatus "aligned" ;
    rdfs:subClassOf sosa:Observation ;
    rdfs:label "Battery State Observation"@en ;
    rdfs:comment "Reification of a pack's state at a single point in time. Temporal representation is deliberately bounded to state at an event rather than a continuous trajectory. The reification follows the SOSA observation pattern rather than a construct invented here; the same pattern is used by the Battery Data Format of the Battery Data Alliance for battery measurement data."@en .

bsdo:observedAt rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:BatteryStateObservation ; rdfs:range xsd:dateTime .
bsdo:observationOf rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:BatteryStateObservation ; rdfs:range bsdo:SwappableBattery .
bsdo:hasStateOfCharge rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:BatteryStateObservation ; rdfs:range xsd:decimal ;
    rdfs:seeAlso echem:electrochemistry_8b2aaa50_bbe1_45da_8778_8898326246a2 ;
    rdfs:comment "Aligned to StateOfCharge in the EMMO domain-electrochemistry module. The StateOfCharge class in the domain-battery namespace is deprecated and is not used here."@en .
bsdo:hasQualitativeHealthLabel rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:BatteryStateObservation ; rdfs:range xsd:string ;
    rdfs:seeAlso echem:electrochemistry_a7a4614f_2426_46f3_8475_cda4a9fabfce ;
    rdfs:comment "Deliberately typed as a string rather than a numeric quantity. One ecosystem exposes a qualitative badge whose scale, thresholds and derivation method are undisclosed; the other exposes nothing. Typing it numerically would imply a comparability the sources do not support."@en .

#################################################################
#  7. EVENT PARTICIPANTS (n-ary reification)
#################################################################

bsdo:hasParticipantCustomer rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:ServiceEvent ; rdfs:range bsdo:Customer .
bsdo:occursAtDevice rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:ServiceEvent ; rdfs:range bsdo:BatteryHandlingDevice .
bsdo:occursAtSlot rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:ServiceEvent ; rdfs:range bsdo:BatterySlot .

#  --- Slot structure ---
#  Both ecosystems publish the state of individual slots. Neither publishes which
#  pack occupies a slot, so state of charge attaches to the slot rather than to a
#  pack; see the comment on hasSlotStateOfCharge.

bsdo:hasSlot rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:BatteryHandlingDevice ; rdfs:range bsdo:BatterySlot ;
    rdfs:label "has slot"@en ;
    rdfs:comment "Relates a device to the slots it comprises. The relation is not stated as mereological: what was observed is that a device presents a numbered set of slots, not that a slot is a part in any stronger sense."@en .

bsdo:hasSlotNumber rdf:type owl:DatatypeProperty , owl:FunctionalProperty ;
    rdfs:domain bsdo:BatterySlot ; rdfs:range xsd:integer ;
    rdfs:label "slot number"@en ;
    rdfs:comment "The number under which the operator presents the slot. Numbering is per device and carries no meaning across devices or across ecosystems."@en .

bsdo:hasSlotStateOfCharge rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:BatterySlot ; rdfs:range xsd:decimal ;
    rdfs:seeAlso echem:electrochemistry_8b2aaa50_bbe1_45da_8778_8898326246a2 ;
    rdfs:label "state of charge reported at slot"@en ;
    rdfs:comment "State of charge as published against a slot. It is deliberately attached to the slot and not to a pack, because that is the limit of what is disclosed: the operator shows the charge held in a slot but not the identity of the pack holding it. The reading therefore cannot be carried forward once the pack leaves, which is the same gap in battery identity and location that Section 8 discusses, appearing here in the shape of the data itself."@en .
bsdo:eventTime rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:ServiceEvent ; rdfs:range xsd:dateTime .
bsdo:packRemoved rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:ObjectTransferEvent ; rdfs:range bsdo:SwappableBattery ;
    rdfs:label "pack removed from vehicle"@en .
bsdo:packInserted rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:ObjectTransferEvent ; rdfs:range bsdo:SwappableBattery ;
    rdfs:label "pack inserted into vehicle"@en .

#  --- Battery-vehicle relation: temporary, not a fixed part-whole ---
bsdo:ElectricMotorcycle rdf:type owl:Class ;
    bsdo:derivationPath "structural: K4 artefact family. K4 yields a full Boolean lattice on three objects under both readings, so no attribute implication holds; the family is reported as a specification table rather than as a lattice, and this class carries no concept-derived intent."@en ;
    bsdo:reuseStatus "aligned" ;
    rdfs:subClassOf gpo:GPO_bc07577b_1e4b_4d60_aa8d_3cfd09e7c03a ;   # gpo:RoadVehicle
    rdfs:label "Electric Motorcycle"@en .

bsdo:BatteryInstallation rdf:type owl:Class ;
    bsdo:derivationPath "structural: N-ary relation pattern (Noy and Rector 2006): reification of the pack-vehicle association so the relation can be temporary. A modelling construct, not a concept."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Battery Installation"@en ;
    rdfs:comment "Reification of the association between a pack and a vehicle. This is deliberately not modelled as a mereological part-whole relation: in a swap domain a pack moves between vehicles, so a fixed relation would be false."@en .
bsdo:installedPack rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:BatteryInstallation ; rdfs:range bsdo:SwappableBattery .
bsdo:installedIn rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:BatteryInstallation ; rdfs:range bsdo:ElectricMotorcycle .
bsdo:installationFrom rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:BatteryInstallation ; rdfs:range xsd:dateTime .

#################################################################
#  8. TARIFFS (two incommensurable quota dimensions)
#################################################################

bsdo:QuotaPlan rdf:type owl:Class ;
    bsdo:derivationPath "structural: Genus for the commercial artefacts, which were observed but not admitted to a formal context."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Prepaid Quota Plan"@en ;
    rdfs:comment "Both ecosystems sell prepaid quota with an expiry period. What differs is the dimension in which the quota is denominated."@en .

bsdo:DistanceQuotaPlan rdf:type owl:Class ;
    bsdo:derivationPath "structural: Observed commercial artefact: quota denominated in distance. Not a formal-context object; disjointness with the event-count plan records an incommensurability, not a lattice result."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:QuotaPlan ;
    rdfs:label "Distance Quota Plan"@en ;
    rdfs:comment "Quota denominated in kilometres travelled."@en .

bsdo:EventCountQuotaPlan rdf:type owl:Class ;
    bsdo:derivationPath "structural: Observed commercial artefact: quota denominated in exchange events. See Distance Quota Plan."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:QuotaPlan ;
    rdfs:label "Event-Count Quota Plan"@en ;
    rdfs:comment "Quota denominated in number of exchange events."@en .

[] rdf:type owl:AllDisjointClasses ;
   owl:members ( bsdo:DistanceQuotaPlan bsdo:EventCountQuotaPlan ) .
#  This disjointness models the incommensurability: converting between the two
#  requires a distance-per-exchange figure that depends on pack capacity and
#  riding conditions, and is therefore not a fixed factor.

bsdo:quotaAmount rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:QuotaPlan ; rdfs:range xsd:decimal .
bsdo:validityDays rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:QuotaPlan ; rdfs:range xsd:integer .

#################################################################
#  9. SWAP ELIGIBILITY
#################################################################

bsdo:SwapEligibilityRule rdf:type owl:Class ;
    bsdo:derivationPath "structural: Observed normative artefact: operator-declared readiness thresholds. Modelled as an operator-relative rule so that the two incompatible definitions can coexist; not a formal-context object."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Swap Eligibility Rule"@en ;
    rdfs:comment "A rule stating when a pack counts as ready to be exchanged. Eligibility is operator-relative: the two ecosystems declare thresholds that do not partition the same interval, so the predicate has no ontology-wide extension."@en .
bsdo:thresholdPercent rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:SwapEligibilityRule ; rdfs:range xsd:decimal .
bsdo:declaredBy rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:SwapEligibilityRule ; rdfs:range bsdo:Operator .

#################################################################
# 10. BATTERY PROPERTIES
#################################################################

bsdo:hasVoltageClass rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range bsdo:VoltageClass ;
    rdfs:comment "Deliberately not functional: a single product may carry more than one declared voltage class when different sources of the same operator label it differently. Non-functionality records that instability rather than resolving it."@en .
bsdo:hasCellChemistry rdf:type owl:ObjectProperty , owl:FunctionalProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range bsdo:CellChemistry .
bsdo:hasCapacityAh rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range xsd:decimal .
bsdo:hasCapacityKWh rdf:type owl:DatatypeProperty ;
    rdfs:domain bsdo:SwappableBattery ; rdfs:range xsd:decimal .

#################################################################
# 11. INCOMPATIBILITY AS AN INFERENCE
#     Compatibility is never asserted. A device accepts a given chemistry;
#     asserting otherwise renders the individual unsatisfiable.
#################################################################

bsdo:acceptsChemistry rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:BatteryHandlingDevice ; rdfs:range bsdo:CellChemistry .

bsdo:accepts rdf:type owl:ObjectProperty ;
    rdfs:domain bsdo:BatteryHandlingDevice ; rdfs:range bsdo:SwappableBattery ;
    rdfs:comment "The packs a device can serve. Never asserted directly; constrained by chemistry axioms so that incompatibility surfaces as a logical inconsistency rather than as an empty query result."@en .

bsdo:LithiumIonOnlyDevice rdf:type owl:Class ;
    bsdo:derivationPath "composed: Composed, not read off K2: cell chemistry is not an attribute of any station in K2, because no operator states which chemistry its devices accept. Obtained from the K1 concept with extent {b1,b2} and intent including {Li-ion}, together with the observation that each network serves only its own packs."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:BatteryHandlingDevice ,
        [ rdf:type owl:Restriction ;
          owl:onProperty bsdo:accepts ;
          owl:allValuesFrom bsdo:LithiumIonSwappableBattery ] ;
    rdfs:label "Lithium-Ion-Only Device"@en .

bsdo:LFPOnlyDevice rdf:type owl:Class ;
    bsdo:derivationPath "composed: Composed, not read off K2, for the reason given on Lithium-Ion-Only Device. Obtained from the K1 concept with extent {b3,b4} and intent {LiFePO4, capacity in Ah}, together with the closed-network observation."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:subClassOf bsdo:BatteryHandlingDevice ,
        [ rdf:type owl:Restriction ;
          owl:onProperty bsdo:accepts ;
          owl:allValuesFrom bsdo:LFPSwappableBattery ] ;
    rdfs:label "LiFePO4-Only Device"@en .

#  Asserting that a chemistry-restricted device accepts a pack of the other
#  chemistry places that pack in two disjoint classes, so a reasoner reports
#  an inconsistency. Incompatibility is thus detected as unsatisfiability
#  rather than as an empty query result.

#################################################################
# 12. EXTERNAL ALIGNMENT TARGETS, LABELS AND DEFINITIONS
#################################################################

#  --- EMMO alignment stubs, declared locally ---
#  Both IRIs serve as rdfs:subClassOf targets but the module is not imported:
#  a full import would introduce several thousand classes to obtain two
#  subsumption relations. Local declaration keeps them readable in editors.

bat:battery_74ed2670_657d_4f0b_b0a6_3f13bc2e9c17 rdf:type owl:Class ;
    rdfs:label "Battery (EMMO domain-battery)"@en ;
    rdfs:comment "Alignment stub for the Battery class of the EMMO domain-battery module. Declared locally rather than imported: importing the full module would introduce several thousand classes to obtain a single subsumption relation."@en ;
    rdfs:isDefinedBy <https://w3id.org/emmo/domain/battery> .

bat:battery_96addc62_ea04_449a_8237_4cd541dd8e5f rdf:type owl:Class ;
    rdfs:label "LithiumIonBattery (EMMO domain-battery)"@en ;
    rdfs:comment "Alignment stub for the LithiumIonBattery class of the EMMO domain-battery module."@en ;
    rdfs:isDefinedBy <https://w3id.org/emmo/domain/battery> .

#  --- General Process Ontology ---
#  The matter/energy transport division is a standing feature of GPO. It is
#  reused rather than restated, which is also why the top-level split of the
#  service events above is not claimed as a finding of this work.

gpo:GPO_c4600586_ccc8_4d4b_b7a2_123d5aa2d77d rdf:type owl:Class ;
    rdfs:label "TransportProcess (GPO)"@en ;
    rdfs:comment "Alignment stub. Elucidated in the source as a process that manipulates the location of a participant."@en ;
    rdfs:isDefinedBy <https://gpo.ontology.link> .

gpo:GPO_890abbc3_d75b_4f3f_a5b7_e1b0e898655b rdf:type owl:Class ;
    rdfs:subClassOf gpo:GPO_c4600586_ccc8_4d4b_b7a2_123d5aa2d77d ;
    rdfs:label "MatterTransportProcess (GPO)"@en ;
    rdfs:comment "Alignment stub for the matter branch of the GPO transport division."@en ;
    rdfs:isDefinedBy <https://gpo.ontology.link> .

gpo:GPO_04b6cbaf_a63a_4130_974a_8cc9c2a612f1 rdf:type owl:Class ;
    rdfs:subClassOf gpo:GPO_c4600586_ccc8_4d4b_b7a2_123d5aa2d77d ;
    rdfs:label "EnergyTransportProcess (GPO)"@en ;
    rdfs:comment "Alignment stub for the energy branch of the GPO transport division."@en ;
    rdfs:isDefinedBy <https://gpo.ontology.link> .

gpo:GPO_bc07577b_1e4b_4d60_aa8d_3cfd09e7c03a rdf:type owl:Class ;
    rdfs:label "RoadVehicle (GPO)"@en ;
    rdfs:comment "Alignment stub for the road vehicle class of GPO."@en ;
    rdfs:isDefinedBy <https://gpo.ontology.link> .

#  --- W3C vocabularies ---

sosa:Observation rdf:type owl:Class ;
    rdfs:label "Observation (SOSA)"@en ;
    rdfs:comment "Alignment stub for the SOSA observation class. The observation reification used here follows this pattern rather than a construct of its own."@en ;
    rdfs:isDefinedBy <http://www.w3.org/ns/sosa/> .

prov:Agent rdf:type owl:Class ;
    rdfs:label "Agent (PROV-O)"@en ;
    rdfs:comment "Alignment stub for the PROV-O agent class."@en ;
    rdfs:isDefinedBy <http://www.w3.org/ns/prov-o> .

#  --- Property labels and definitions ---
bsdo:hasCellChemistry     rdfs:label "has cell chemistry"@en ;
    rdfs:comment "The cell chemistry declared by the manufacturer. This is the dimension on which interchange actually fails."@en .
bsdo:hasVoltageClass      rdfs:comment "The declared nominal voltage class. Not functional, since one artefact may carry more than one declaration from different sources."@en .
bsdo:hasCapacityAh        rdfs:label "capacity (Ah)"@en ;
    rdfs:comment "Capacity in ampere-hours. The two ecosystems report capacity in different units, which are not convertible without the actual rather than nominal voltage."@en .
bsdo:hasCapacityKWh       rdfs:label "capacity (kWh)"@en ;
    rdfs:comment "Capacity in kilowatt-hours. See the note on capacity in ampere-hours."@en .
bsdo:hasIdentifierScheme  rdfs:label "has identifier scheme"@en ;
    rdfs:comment "The numbering scheme of a unit identifier. The two ecosystems use mutually uninterpretable schemes, which is the first mapping any roaming arrangement must resolve."@en .
bsdo:hasEnrolmentStatus   rdfs:comment "A pack's enrolment status in an operator's network. This determines the right to manage the pack, not its ownership."@en .
bsdo:hasStateOfCharge     rdfs:label "state of charge (%)"@en .
bsdo:hasQualitativeHealthLabel rdfs:label "qualitative health label"@en .
bsdo:accepts              rdfs:label "accepts"@en .
bsdo:acceptsChemistry     rdfs:label "accepts chemistry"@en ;
    rdfs:comment "The cell chemistry a device can serve. Together with the disjointness of the chemistry classes, this is what makes incompatibility derivable as a logical inconsistency."@en .
bsdo:occursAtDevice       rdfs:label "occurs at device"@en .
bsdo:occursAtSlot         rdfs:label "occurs at slot"@en .
bsdo:eventTime            rdfs:label "event time"@en .
bsdo:hasParticipantCustomer rdfs:label "has participant customer"@en .
bsdo:packRemoved          rdfs:comment "The pack removed from the vehicle during an object-transfer event."@en .
bsdo:packInserted         rdfs:comment "The pack inserted into the vehicle during an object-transfer event."@en .
bsdo:returnsPackTo        rdfs:comment "The party to whom a pack is returned at the end of an event. Present only on events that preserve ownership."@en .
bsdo:installedPack        rdfs:label "installed pack"@en .
bsdo:installedIn          rdfs:label "installed in"@en .
bsdo:installationFrom     rdfs:label "installation from"@en .
bsdo:observationOf        rdfs:label "observation of"@en .
bsdo:observedAt           rdfs:label "observed at"@en .
bsdo:declaredBy           rdfs:label "declared by"@en .
bsdo:quotaAmount          rdfs:label "quota amount"@en ;
    rdfs:comment "The quota amount. Its unit depends on the subclass: kilometres for a distance plan, exchange events for an event-count plan. The two are disjoint because they are not commensurable."@en .
bsdo:validityDays         rdfs:label "validity (days)"@en .
bsdo:thresholdPercent     rdfs:label "threshold (%)"@en .

#  --- Class definitions ---
bsdo:Agent                 rdfs:comment "A party that can own or hold a battery pack. Aligned to the PROV-O agent class. Customer and Operator are kept as subclasses of this class rather than reified as roles: the two are not declared disjoint, so one party can already be typed as both, and reifying them would require the population to be restated without answering any competency question that is not already answered."@en .
bsdo:Customer              rdfs:comment "An end user of a battery swap service."@en .
bsdo:Operator              rdfs:comment "An operator of a battery swap ecosystem."@en .
bsdo:ElectricMotorcycle    rdfs:comment "An electric two-wheeler using swappable batteries. Its relation to a pack is temporary; see BatteryInstallation."@en .
bsdo:CellChemistry         rdfs:comment "Cell chemistry as an enumerated value."@en .
bsdo:VoltageClass          rdfs:comment "Declared nominal voltage class. This dimension overlaps across the ecosystems studied and therefore does not determine whether packs can be interchanged."@en .
bsdo:IdentifierScheme      rdfs:comment "A unit identifier scheme, specific to an ecosystem."@en .
bsdo:NetworkEnrolmentStatus rdfs:comment "A pack's network enrolment status: enrolled or not enrolled."@en .
bsdo:BatteryHandlingDevice rdfs:comment "A device that handles battery packs, whether by exchanging or by charging them."@en .
bsdo:LithiumIonOnlyDevice  rdfs:comment "A device that accepts only lithium-ion packs. The value restriction declared here is what makes incompatibility detectable as an inconsistency."@en .
bsdo:LFPOnlyDevice         rdfs:comment "A device that accepts only lithium iron phosphate packs."@en .
bsdo:LFPSwappableBattery   rdfs:comment "A swappable pack with lithium iron phosphate chemistry. Disjoint with the lithium-ion class."@en .

#  --- Further labels and definitions ---
bsdo:hasVoltageClass   rdfs:label "has voltage class"@en .
bsdo:declaredBy        rdfs:comment "The operator declaring this rule. Eligibility rules are operator-specific rather than a shared standard."@en .
bsdo:eventTime         rdfs:comment "The time at which an event occurred. Generally unpopulated: transaction payloads could not be observed from available sources."@en .
bsdo:hasParticipantCustomer rdfs:comment "The customer participating in a service event."@en .
bsdo:occursAtDevice    rdfs:comment "The device at which an event takes place."@en .
bsdo:occursAtSlot      rdfs:comment "The slot or door in which a pack is placed. The two ecosystems use different native terms."@en .
bsdo:installedPack     rdfs:comment "The pack installed in the vehicle during this installation episode."@en .
bsdo:installedIn       rdfs:comment "The vehicle in which the pack is installed during this episode."@en .
bsdo:installationFrom  rdfs:comment "The start of an installation episode, which makes the battery-vehicle relation temporary rather than a fixed part-whole."@en .
bsdo:observationOf     rdfs:comment "The pack whose state is observed."@en .
bsdo:observedAt        rdfs:comment "The time of observation, which bounds temporal representation to state at a point in time rather than a full trajectory."@en .
bsdo:thresholdPercent  rdfs:comment "The state-of-charge threshold a rule declares. The same numeric value can mean different things: a single eligibility threshold in one ecosystem, a band boundary in the other."@en .
bsdo:validityDays      rdfs:comment "The validity period of a quota in days. A quota is exhausted either by use or by expiry, whichever comes first."@en .

#################################################################
# 13. UMBRELLA CLASS FOR ECOSYSTEM-BOUND ARTEFACTS
#################################################################

#  `operatedBy` initially carried no rdfs:domain, since it applies across
#  artefact families.
#  An umbrella class is introduced instead of leaving the property without a
#  domain. All four artefact families used as formal contexts, together with
#  the commercial and normative artefacts, are artefacts bound to a single
#  ecosystem. That binding is what makes cross-ecosystem comparison expressible.

bsdo:EcosystemArtefact rdf:type owl:Class ;
    bsdo:derivationPath "structural: Umbrella introduced in response to pitfall P11. It names the ecosystem-binding that the formal-context design had assumed implicitly, since all four artefact families are ecosystem-bound."@en ;
    bsdo:reuseStatus "native" ;
    rdfs:label "Ecosystem Artefact"@en ;
    rdfs:comment "Any artefact bound to a particular battery swap ecosystem: battery models, station devices, service flows, vehicle models, and the commercial and normative artefacts that accompany them. This binding is what makes cross-ecosystem comparison expressible."@en .

bsdo:SwappableBattery      rdfs:subClassOf bsdo:EcosystemArtefact .
bsdo:BatteryHandlingDevice rdfs:subClassOf bsdo:EcosystemArtefact .
bsdo:ServiceEvent          rdfs:subClassOf bsdo:EcosystemArtefact .
bsdo:ElectricMotorcycle    rdfs:subClassOf bsdo:EcosystemArtefact .
bsdo:QuotaPlan             rdfs:subClassOf bsdo:EcosystemArtefact .
bsdo:SwapEligibilityRule   rdfs:subClassOf bsdo:EcosystemArtefact .
bsdo:BatterySlot           rdfs:subClassOf bsdo:EcosystemArtefact .

bsdo:operatedBy rdfs:domain bsdo:EcosystemArtefact .
