docs: add FLE bridge direction pivot and squad-injection test tooling
Adds the app-centric FLE bridge direction (direction.md) replacing the Blaze-backend route as primary plan, plus a corrected foundational test procedure and snapshot/diff/apply tooling for reverse-engineering FLE's Freeze Lineup write mechanism. Also picks up prior untracked research docs (status-review, fut-integration-options, fifa23-startup-flow, track-c) and existing capture/export tooling that hadn't been committed yet.
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Diff two openfut_snapshot_*.json files from snapshot_lineup_tables.lua.
|
||||
|
||||
Usage: diff_snapshots.py before.json after.json
|
||||
|
||||
Reports, per table, which rows changed and which fields differed —
|
||||
this is how the real DB write behind FLE's "Freeze Lineup" GUI feature
|
||||
gets discovered (see docs/foundational-xi-injection-test.md).
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def row_key(row):
|
||||
for candidate in ("playerid", "player_id", "id", "rowid"):
|
||||
if candidate in row:
|
||||
return row[candidate]
|
||||
return json.dumps(row, sort_keys=True)
|
||||
|
||||
|
||||
def diff_table(name, before, after):
|
||||
before_rows = {row_key(r): r for r in before.get("rows", [])}
|
||||
after_rows = {row_key(r): r for r in after.get("rows", [])}
|
||||
|
||||
changes = []
|
||||
for key, after_row in after_rows.items():
|
||||
before_row = before_rows.get(key)
|
||||
if before_row is None:
|
||||
changes.append({"row": key, "type": "added", "row_data": after_row})
|
||||
continue
|
||||
field_diffs = {}
|
||||
for field in set(before_row) | set(after_row):
|
||||
bval = before_row.get(field)
|
||||
aval = after_row.get(field)
|
||||
if bval != aval:
|
||||
field_diffs[field] = {"before": bval, "after": aval}
|
||||
if field_diffs:
|
||||
changes.append({"row": key, "type": "modified", "fields": field_diffs})
|
||||
|
||||
for key in before_rows:
|
||||
if key not in after_rows:
|
||||
changes.append({"row": key, "type": "removed"})
|
||||
|
||||
if changes:
|
||||
print(f"\n=== {name}: {len(changes)} changed row(s) ===")
|
||||
for c in changes:
|
||||
print(json.dumps(c, indent=2))
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print(__doc__)
|
||||
sys.exit(1)
|
||||
|
||||
with open(sys.argv[1]) as f:
|
||||
before = json.load(f)
|
||||
with open(sys.argv[2]) as f:
|
||||
after = json.load(f)
|
||||
|
||||
table_names = set(before.get("tables", {})) | set(after.get("tables", {}))
|
||||
any_changes = False
|
||||
for name in sorted(table_names):
|
||||
b = before.get("tables", {}).get(name, {"rows": []})
|
||||
a = after.get("tables", {}).get(name, {"rows": []})
|
||||
before_len = len(b.get("rows", []))
|
||||
after_len = len(a.get("rows", []))
|
||||
if before_len != after_len:
|
||||
print(f"{name}: row count changed {before_len} -> {after_len}")
|
||||
any_changes = True
|
||||
diff_table(name, b, a)
|
||||
|
||||
if not any_changes:
|
||||
print("(row-count-only check found no differences; per-field diffs above are authoritative)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user