fix(fifa17): key the kit home/away split on the carddbid, not assetid
Staging served `kits=2 kitsHome=0 kitsAway=0`: the split compared the catalog `asset_id` against `fcc_kitcards.assetid` (14/15), but a kit's catalog `asset_id` IS its carddbid (6300006), not that column, so neither family ever matched. The carddbid range is the same fact in the form we actually carry: across all 1482 kit rows, assetid 14 covers precisely the 828 `63xxxxx` ids and assetid 15 precisely the 654 `64xxxxx` ids, with no exceptions either way. Keying on the id we already have avoids carrying `assetid` as a second source of truth for the same split. Tests now use the real team-21 pair (6300006 home / 6400003 away). Verified against the staging stack: `kits=2 kitsHome=1 kitsAway=1`, team-21 bucket 2, `?type=kit` still activeHomeKit/activeAwayKit, `?type=player` 12.
This commit is contained in:
@@ -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<i64> {
|
||||
@@ -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<Value> = 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<String, i64> {
|
||||
@@ -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| {
|
||||
|
||||
Reference in New Issue
Block a user