diff --git a/src/mapper.rs b/src/mapper.rs index d9cb0a1..7ea3566 100644 --- a/src/mapper.rs +++ b/src/mapper.rs @@ -381,6 +381,36 @@ const EXACT: &[ExactRoute] = &[ core_method: "GET", core_path: "/notifications", notes: "FUT active messages → Core notifications (mapped to nearest equivalent)", }, + // ── Dynamic objectives (FIFA 23 actual path) ────────────────────────────── + ExactRoute { + ea_method: "GET", ea_path: "/ut/game/fut/user/dynamicobjectives", + core_method: "GET", core_path: "/objectives", + notes: "FIFA 23 dynamic objectives list → Core objectives", + }, + // ── SBS challenges (FIFA 23 uses /sbs/ not /sbc/) ──────────────────────── + ExactRoute { + ea_method: "GET", ea_path: "/ut/game/fut/sbs/challenges", + core_method: "GET", core_path: "/sbc", + notes: "FIFA 23 SBS challenges list → Core SBC list", + }, + // ── Squad Battles result (separate from rivals/result) ─────────────────── + ExactRoute { + ea_method: "POST", ea_path: "/ut/game/fut/squadbattle/result", + core_method: "POST", core_path: "/matches/result", + notes: "Squad Battles match result → Core match result", + }, + // ── Match submission (FIFA 23 uses /game/r) ─────────────────────────────── + ExactRoute { + ea_method: "POST", ea_path: "/ut/game/fut/game/r", + core_method: "POST", core_path: "/matches/result", + notes: "FIFA 23 match result (short path /game/r) → Core match result", + }, + // ── Squad list ──────────────────────────────────────────────────────────── + ExactRoute { + ea_method: "GET", ea_path: "/ut/game/fut/squads/user", + core_method: "GET", core_path: "/squad", + notes: "FUT squad list for user → Core squad", + }, ]; // ── Prefix mappings (dynamic path segments after a known prefix) ─────────────── @@ -431,6 +461,36 @@ fn prefix_routes() -> &'static [PrefixRoute] { core_path_fn: |_| "/sbc/submit".to_string(), notes: "FUT SBC set submission → Core SBC submit", }, + // /ut/game/fut/sbs/challenges/{id} → GET /sbc/{id} + PrefixRoute { + ea_method: "GET", + ea_prefix: "/ut/game/fut/sbs/challenges/", + core_path_fn: |suffix| { + // suffix is "{id}" or "{id}/sets/{setId}" — strip extra segments + let id = suffix.split('/').next().unwrap_or(suffix); + format!("/sbc/{id}") + }, + notes: "FIFA 23 SBS challenge detail → Core SBC by ID", + }, + // /ut/game/fut/sbs/challenges/{id}/sets/{setId}/trade → POST /sbc/submit + PrefixRoute { + ea_method: "POST", + ea_prefix: "/ut/game/fut/sbs/challenges/", + core_path_fn: |_| "/sbc/submit".to_string(), + notes: "FIFA 23 SBS challenge trade → Core SBC submit", + }, + // /ut/game/fut/user/dynamicobjectives/{id}/milestones/{m}/claim + // → POST /objectives/{id}/claim + PrefixRoute { + ea_method: "POST", + ea_prefix: "/ut/game/fut/user/dynamicobjectives/", + core_path_fn: |suffix| { + // suffix is "{id}/milestones/{m}/claim" — extract just the obj id + let obj_id = suffix.split('/').next().unwrap_or(suffix); + format!("/objectives/{obj_id}/claim") + }, + notes: "FIFA 23 dynamic objective claim → Core objective claim by ID", + }, // /ut/game/fut/trade/{trade_id} (DELETE) → DELETE /market/listings/{trade_id} PrefixRoute { ea_method: "DELETE", @@ -523,7 +583,7 @@ pub fn map_to_core(method: &str, path: &str) -> Option { if !suffix.is_empty() { let core_path = (r.core_path_fn)(suffix); return Some(CoreMapping { - method: "GET", // overridden per-route below + method: r.ea_method, core_path, notes: r.notes, }); @@ -720,14 +780,39 @@ mod tests { fn test_quick_sell_maps() { let m = map_to_core("DELETE", "/ut/game/fut/item/owned-111"); assert!(m.is_some()); - assert_eq!(m.unwrap().core_path, "/collection/owned-111"); + let m = m.unwrap(); + assert_eq!(m.core_path, "/collection/owned-111"); + assert_eq!(m.method, "DELETE"); } #[test] fn test_cancel_listing_maps() { let m = map_to_core("DELETE", "/ut/game/fut/trade/trade-222"); assert!(m.is_some()); - assert_eq!(m.unwrap().core_path, "/market/listings/trade-222"); + let m = m.unwrap(); + assert_eq!(m.core_path, "/market/listings/trade-222"); + assert_eq!(m.method, "DELETE"); + } + + #[test] + fn test_prefix_routes_preserve_method() { + let cases = [ + ("POST", "/ut/game/fut/draft/abc-123/pick", "POST"), + ("POST", "/ut/game/fut/champs/sess-456/result", "POST"), + ("DELETE", "/ut/game/fut/trade/trade-222", "DELETE"), + ("DELETE", "/ut/game/fut/item/owned-111", "DELETE"), + ("PUT", "/ut/game/fut/item/owned-999", "PUT"), + ("POST", "/ut/game/fut/store/pack/pack-789/open", "POST"), + ]; + for (ea_method, path, expected_method) in cases { + let m = map_to_core(ea_method, path) + .unwrap_or_else(|| panic!("no mapping for {ea_method} {path}")); + assert_eq!( + m.method, expected_method, + "{ea_method} {path} → expected method {expected_method}, got {}", + m.method + ); + } } #[test]