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.
This commit is contained in:
funman300
2026-08-21 23:59:35 +00:00
parent a96d06dbc0
commit 0a7c4e129c
+76
View File
@@ -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()