From 0a7c4e129c35ca54f44632c537a407723082c918 Mon Sep 17 00:00:00 2001 From: funman300 Date: Fri, 21 Aug 2026 23:59:35 +0000 Subject: [PATCH] docs(fifa17): record discard economy validation evidence and impact Adds scripts/fifa17-discard-impact.py (owned-instance economic impact, computed from the shipped implementation's matrix -- informational, never a reason to alter a value) and records the measured results. Owned club, 1993 instances: legacy 1,820,700 -> recovered 19,128,031 = 10.51x. Players 10.53x, manager 1.88x, consumables 0.19x (the ladder overpaid them ~5x), staff 0.24x, club items 900 -> 0. --- scripts/fifa17-discard-impact.py | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 scripts/fifa17-discard-impact.py diff --git a/scripts/fifa17-discard-impact.py b/scripts/fifa17-discard-impact.py new file mode 100755 index 0000000..7d12643 --- /dev/null +++ b/scripts/fifa17-discard-impact.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +"""Economic impact of the recovered discard table, over OWNED instances. + +Informational only: it exists to make the promotion decision explicit, never to +justify altering a value. Values come from the matrix emitted by +`cargo run -p openfut-adapter-fifa17 --example discard_matrix`, i.e. the shipped +implementation. + +Usage: + python3 scripts/fifa17-discard-impact.py --matrix /tmp/discard-matrix.csv +""" +import argparse +import collections +import csv +import sqlite3 + +DB = "/home/alex/openfut-sold-staging/staging-core.db" + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--matrix", required=True) + ap.add_argument("--db", default=DB) + a = ap.parse_args() + + matrix = {} + with open(a.matrix) as fh: + for row in csv.DictReader(fh): + matrix[row["definition"]] = row + + con = sqlite3.connect("file:%s?mode=ro" % a.db, uri=True) + owned = con.execute("SELECT card_id, content_kind FROM owned_cards").fetchall() + con.close() + + by_kind = collections.defaultdict(lambda: [0, 0, 0]) # n, legacy, recovered + deltas = [] + missing = 0 + for card_id, kind in owned: + row = matrix.get(card_id) + if row is None: + missing += 1 + continue + legacy = int(row["legacy"]) + rec = int(row["recovered"]) if row["recovered"] != "-" else legacy + b = by_kind[kind] + b[0] += 1 + b[1] += legacy + b[2] += rec + deltas.append((rec - legacy, kind, card_id, legacy, rec)) + + print("OWNED-INSTANCE DISCARD IMPACT (informational)") + print("%-12s %6s %14s %14s %8s" % ("kind", "n", "legacy", "recovered", "ratio")) + tl = tr = tn = 0 + for kind in sorted(by_kind): + n, legacy, rec = by_kind[kind] + ratio = (rec / legacy) if legacy else 0 + print("%-12s %6d %14s %14s %7.2fx" % (kind, n, f"{legacy:,}", f"{rec:,}", ratio)) + tl += legacy + tr += rec + tn += n + print("%-12s %6d %14s %14s %7.2fx" + % ("TOTAL", tn, f"{tl:,}", f"{tr:,}", (tr / tl) if tl else 0)) + if missing: + print("\ndefinitions absent from the matrix: %d" % missing) + + deltas.sort() + print("\nlargest DECREASES") + for d, kind, cid, legacy, rec in deltas[:5]: + print(" %-10s %-18s %6d -> %-7d (%+d)" % (kind, cid, legacy, rec, d)) + print("largest INCREASES") + for d, kind, cid, legacy, rec in deltas[-5:][::-1]: + print(" %-10s %-18s %6d -> %-7d (%+d)" % (kind, cid, legacy, rec, d)) + + +if __name__ == "__main__": + main()