feat: map objectives, SBC, squad battles, and match endpoints #5

Open
funman300 wants to merge 1 commits from feat/map-objectives-sbc into main
+88 -3
View File
@@ -381,6 +381,36 @@ const EXACT: &[ExactRoute] = &[
core_method: "GET", core_path: "/notifications", core_method: "GET", core_path: "/notifications",
notes: "FUT active messages → Core notifications (mapped to nearest equivalent)", 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) ─────────────── // ── 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(), core_path_fn: |_| "/sbc/submit".to_string(),
notes: "FUT SBC set submission → Core SBC submit", 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} // /ut/game/fut/trade/{trade_id} (DELETE) → DELETE /market/listings/{trade_id}
PrefixRoute { PrefixRoute {
ea_method: "DELETE", ea_method: "DELETE",
@@ -523,7 +583,7 @@ pub fn map_to_core(method: &str, path: &str) -> Option<CoreMapping> {
if !suffix.is_empty() { if !suffix.is_empty() {
let core_path = (r.core_path_fn)(suffix); let core_path = (r.core_path_fn)(suffix);
return Some(CoreMapping { return Some(CoreMapping {
method: "GET", // overridden per-route below method: r.ea_method,
core_path, core_path,
notes: r.notes, notes: r.notes,
}); });
@@ -720,14 +780,39 @@ mod tests {
fn test_quick_sell_maps() { fn test_quick_sell_maps() {
let m = map_to_core("DELETE", "/ut/game/fut/item/owned-111"); let m = map_to_core("DELETE", "/ut/game/fut/item/owned-111");
assert!(m.is_some()); 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] #[test]
fn test_cancel_listing_maps() { fn test_cancel_listing_maps() {
let m = map_to_core("DELETE", "/ut/game/fut/trade/trade-222"); let m = map_to_core("DELETE", "/ut/game/fut/trade/trade-222");
assert!(m.is_some()); 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] #[test]