NRF SDK 0.9

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.

ProfilUsage
configuredMatériel configuré pour le train. Utile à la fiche prévue ou achetée.
currentMatériel actuellement observé. Utile aux capacités et à la capacité voyageurs actuelles.
purchasedDynamics / currentDynamicsProfils 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 / maximumSpeedKmhm/s / km/hVitesse maximale du matériel ; la conversion en km/h est déjà exposée.
maximumAccelerationMps2m/s²Accélération maximale du profil, pas une accélération mesurée.
tractiveForceNNForce de traction ; diviser par 1 000 pour les kN.
powerWWPuissance ; diviser par 1 000 pour les kW.
emptyMassKgkgMasse à vide, sans la confondre avec une masse chargée.
lengthMmLongueur du profil de train.
passengerCapacitypersonnesCapacité 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

Native : profils, capacité et ordre des modèles
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 }
JVM : mêmes questions, jointures explicites du lot
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.