Lire et agir
Lire le matériel, la composition et les voyageurs
Comparer les profils configuré et actuel et calculer une occupation uniquement avec des données disponibles.
Choisir le profil correspondant à la question
Ce parcours suppose une requête de trains par lot. includeCharacteristics demande les caractéristiques, includeComposition la composition et includePassengers les occupants. Activez uniquement ce que votre écran utilise ; ces options répondent à des besoins indépendants.
| Profil | Usage |
|---|---|
| configured | Matériel configuré pour le train. Utile à la fiche prévue ou achetée. |
| current | Matériel actuellement observé. Utile aux capacités et à la capacité voyageurs actuelles. |
| purchasedDynamics / currentDynamics | Profils de conduite de la lecture JVM ciblée, indépendants l’un de l’autre. |
Conserver les unités du SDK
| Propriété | Unité | Interprétation |
|---|---|---|
| maximumSpeedMps / maximumSpeedKmh | m/s / km/h | Vitesse maximale du matériel ; la conversion en km/h est déjà exposée. |
| maximumAccelerationMps2 | m/s² | Accélération maximale du profil, pas une accélération mesurée. |
| tractiveForceN | N | Force de traction ; diviser par 1 000 pour les kN. |
| powerW | W | Puissance ; diviser par 1 000 pour les kW. |
| emptyMassKg | kg | Masse à vide, sans la confondre avec une masse chargée. |
| lengthM | m | Longueur du profil de train. |
| passengerCapacity | personnes | Capacité déclarée, distincte du nombre présent. |
Conservez les unités natives dans vos modèles et convertissez à l’affichage. Dans une fiche Native, la vitesse observée est en m/s ; la ligne Train JVM du lot utilise speedKmh. La lecture JVM ciblée revient à speedMps. Son TrainDynamics utilise maxSpeedMps, maxAccelerationMps2 et tractiveEffortN, et expose aussi serviceBrakingMps2 et emergencyBrakingMps2 en m/s². Ces noms appartiennent à ce type ciblé, pas à TrainCharacteristics.
Conserver l’ordre et l’identité des véhicules
TrainCharacteristics.composition est une liste nullable de TrainVehicle. Son ordre et les répétitions de modelId décrivent la composition : ne transformez pas cette liste en ensemble. Chaque véhicule porte son model et son modelId. Le lot expose aussi vehicleModels pour présenter les modèles référencés ; les libellés inconnus n’effacent pas l’identité du modèle.
VehicleModel expose les informations de modèle disponibles, dont son libellé source. Ce libellé n’est pas une traduction fournie par le SDK. Distinguez le nombre d’éléments de composition du nombre de voitures : ils décrivent des niveaux différents et ne se remplacent pas automatiquement.
Calculer un taux sans fabriquer de zéro
Un taux d’occupation nécessite un nombre d’occupants connu et la capacité actuelle connue, strictement positive. Une capacité nulle rend le ratio indéfini ; une donnée absente ne devient pas zéro. Le résultat peut être supérieur à 100 % si les valeurs observées l’impliquent : ne le tronquez pas silencieusement.
Produire des fiches matériel testables
package wiki.trainmaterial
import nimby.*
data class MaterialCard(
val id: TrainId,
val configured: TrainCharacteristics?,
val current: TrainCharacteristics?,
val passengers: Int?,
val occupancyPercent: Double?,
)
fun readMaterial(context: ToolContext): List<MaterialCard> {
val snapshot = context.trains(TrainQuery(
includeService = false,
includeLocations = false,
includeCharacteristics = true,
includeComposition = true,
includePassengers = true,
))
return snapshot.trains.map { train ->
MaterialCard(
train.trainId, train.configured, train.current, train.passengers,
occupancyPercent(train.passengers, train.current),
)
}
}
// Aucune capacité de remplacement quand le matériel actuel est inconnu.
fun occupancyPercent(passengers: Int?, current: TrainCharacteristics?): Double? {
val capacity = current?.passengerCapacity ?: return null
if (passengers == null || capacity <= 0) return null
return passengers.toDouble() * 100.0 / capacity
}
// L'ordre et les répétitions de modèles décrivent la composition.
fun orderedModelIds(profile: TrainCharacteristics?): List<VehicleModelId>? =
profile?.composition?.map { it.modelId }
package wiki.jvmtrainmaterial
import fr.nimby.sdk.*
data class MaterialCard(
val id: TrainId,
val configured: TrainCharacteristics?,
val current: TrainCharacteristics?,
val passengers: Int?,
val occupancyPercent: Double?,
)
fun readMaterial(game: Game): List<MaterialCard> {
val snapshot = game.trains.snapshot(query = TrainQuery(
includeService = false,
includeLocations = false,
includeCharacteristics = true,
includeComposition = true,
includePassengers = true,
))
return snapshot.trains.mapNotNull { train ->
val record = snapshot.train(train.trainId) ?: return@mapNotNull null
val current = record.metadata?.current
val passengers = record.details?.passengers
MaterialCard(
train.trainId, record.metadata?.configured, current, passengers,
occupancyPercent(passengers, current),
)
}
}
// Un nombre d'occupants inconnu ne devient jamais zéro.
fun occupancyPercent(passengers: Int?, current: TrainCharacteristics?): Double? {
val capacity = current?.passengerCapacity ?: return null
if (passengers == null || capacity <= 0) return null
return passengers.toDouble() * 100.0 / capacity
}
fun orderedModelIds(profile: TrainCharacteristics?): List<VehicleModelId>? =
profile?.composition?.map { it.modelId }
Les fonctions renvoient une fiche par train avec les deux profils conservés. occupancyPercent est une fonction pure : testez occupants absents, profil absent, capacité zéro et capacité positive. orderedModelIds conserve les doublons et l’ordre ; un résultat null signifie que la composition n’est pas connue.