diff --git a/openfut-adapter-fifa17/src/fut/club_stats.rs b/openfut-adapter-fifa17/src/fut/club_stats.rs index 2141882..672985d 100644 --- a/openfut-adapter-fifa17/src/fut/club_stats.rs +++ b/openfut-adapter-fifa17/src/fut/club_stats.rs @@ -66,12 +66,20 @@ const S_KITS_HOME: i64 = 0x29; const S_KITS_AWAY: i64 = 0x2A; const S_BADGES: i64 = 0x2D; -/// `fcc_kitcards.assetid` splits the kit table into the home and away families. -/// Verified across all 1482 rows of the FIFA 17 kit table: assetid 14 covers -/// exactly the `63xxxxx` carddbids (828 rows) and assetid 15 exactly the -/// `64xxxxx` ones (654 rows), with no exceptions in either direction. -const KIT_ASSET_HOME: i64 = 14; -const KIT_ASSET_AWAY: i64 = 15; +/// First `carddbid` of the AWAY kit family. `fcc_kitcards` is split into a +/// `63xxxxx` home family and a `64xxxxx` away family, and the table's own +/// `assetid` column agrees exactly: across all 1482 rows, assetid 14 covers +/// precisely the 828 `63xxxxx` ids and assetid 15 precisely the 654 `64xxxxx` +/// ids, with no exceptions either way. A kit's catalog `asset_id` IS its +/// carddbid, so the id itself is the family key -- the `assetid` column is not +/// carried on the wire and would be a second source of truth for the same fact. +const KIT_AWAY_FLOOR: i64 = 6_400_000; + +/// Which kit family an owned kit belongs to. Only meaningful for +/// [`ContentKind::Kit`]; the caller filters first. +fn is_home_kit(kit: &ClubStatInput) -> bool { + kit.asset_id < KIT_AWAY_FLOOR +} /// cardsubtypeid (staff family) -> stat id (STAFF_SUBTYPE_STAT). fn staff_stat(subtype: i64) -> Option { @@ -240,11 +248,10 @@ pub fn club_stats_body(items: &[ClubStatInput], ctx: ContextField) -> Value { .iter() .filter(|item| matches!(item.kind, ContentKind::Kit)) .collect(); - let kits_with_asset = - |asset: i64| kits.iter().filter(|item| item.asset_id == asset).count() as i64; + let home = kits.iter().filter(|kit| is_home_kit(kit)).count() as i64; g.insert(S_KITS, kits.len() as i64); - g.insert(S_KITS_HOME, kits_with_asset(KIT_ASSET_HOME)); - g.insert(S_KITS_AWAY, kits_with_asset(KIT_ASSET_AWAY)); + g.insert(S_KITS_HOME, home); + g.insert(S_KITS_AWAY, kits.len() as i64 - home); let mut stat: Vec = g.iter().map(|(sid, v)| row(1, 0, *sid, *v)).collect(); @@ -344,22 +351,27 @@ mod tests { team_id: None, } } - /// A kit of the given family (`KIT_ASSET_HOME` / `KIT_ASSET_AWAY`) worn by - /// `team`. - fn kit_of(asset_id: i64, team: i64) -> ClubStatInput { + /// A kit worn by `team`. `carddbid` is the real `fcc_kitcards` id, which is + /// also the catalog `asset_id` and therefore the home/away family key. + fn kit_of(carddbid: i64, team: i64) -> ClubStatInput { ClubStatInput { kind: ContentKind::Kit, subtype: 9, rating: 0, rare: false, - asset_id, + asset_id: carddbid, nation_id: None, league_id: None, team_id: Some(team), } } + /// Real team-21 kits from `fcc_kitcards`: 6300006 is its home kit and + /// 6400003 its away kit. + const HOME_KIT: i64 = 6_300_006; + const AWAY_KIT: i64 = 6_400_003; + fn kit() -> ClubStatInput { - kit_of(KIT_ASSET_HOME, 21) + kit_of(HOME_KIT, 21) } fn global(body: &Value) -> std::collections::HashMap { @@ -432,9 +444,9 @@ mod tests { #[test] fn kit_counts_split_by_home_and_away_family() { let items = vec![ - kit_of(KIT_ASSET_HOME, 21), - kit_of(KIT_ASSET_HOME, 38), - kit_of(KIT_ASSET_AWAY, 21), + kit_of(HOME_KIT, 21), + kit_of(6_300_010, 38), + kit_of(AWAY_KIT, 21), ]; let g = global(&club_stats_body(&items, ContextField::Nation)); assert_eq!(g["kits"], 3); @@ -450,9 +462,9 @@ mod tests { with_team.team_id = Some(21); let items = vec![ with_team, - kit_of(KIT_ASSET_HOME, 21), - kit_of(KIT_ASSET_AWAY, 21), - kit_of(KIT_ASSET_HOME, 38), + kit_of(HOME_KIT, 21), + kit_of(AWAY_KIT, 21), + kit_of(6_300_010, 38), ]; let body = club_stats_body(&items, ContextField::Team); let kits_for = |team: i64| {