feat: add full supported API details for variants and enhance tests
This commit is contained in:
14
README.md
14
README.md
@@ -238,11 +238,15 @@ curl -OJ "http://127.0.0.1:8000/compat?format=md" # → compat.md
|
|||||||
curl -OJ "http://127.0.0.1:8000/compat?format=json" # → compat.json (grupy + warianty + diffy)
|
curl -OJ "http://127.0.0.1:8000/compat?format=json" # → compat.json (grupy + warianty + diffy)
|
||||||
```
|
```
|
||||||
|
|
||||||
W UI: przyciski **⬇ md** / **⬇ json** w panelu *Gry / wersje*. Markdown to macierz `biblioteka × gra`
|
**JSON niesie pełny baseline.** Każdy wariant ma `api` = *co jest obsługiwane*: lista typów oraz
|
||||||
(`✓` = obecna; `A`/`B*`/… gdy nazwa ma kilka wariantów powierzchni) plus sekcja *Warianty*: dla
|
`classes` (per klasa jej `methods`/`events`/`fields` z nazwami, id, typami). To punkt odniesienia,
|
||||||
każdego rozbieżnego wariantu overlap %, zbiorcze `types/methods/events/fields +N/-N/~N`, a pod tym
|
względem którego czyta się diff — masz i „co było", i „co się zmieniło". Diff rozbieżnego wariantu
|
||||||
**nazwany rozkład per klasa** — które metody/eventy/pola doszły (`+`), zniknęły (`−`) lub zmieniły
|
siedzi w `vs_reference` (overlap %, zbiorcze liczby + `detail` z nazwanym rozkładem per klasa, bez cap-a).
|
||||||
się (`~`), np. `CMC_Animo: −PAUSE ~FPS (type int→float)`. Pełne listy (bez cap-a) są w `vs_reference.detail` JSON-a.
|
|
||||||
|
W UI: przyciski **⬇ md** / **⬇ json** w panelu *Gry / wersje*. Markdown to tylko **podgląd**:
|
||||||
|
macierz `biblioteka × gra` (`✓` = obecna; `A`/`B*`/… gdy nazwa ma kilka wariantów) plus sekcja
|
||||||
|
*Warianty* — dla każdego wariantu liczba i nazwy klas, a dla rozbieżnych skrócony rozkład zmian
|
||||||
|
(`CMC_Animo: −PAUSE ~FPS (type int→float)`). Pełne listy metod bierz z JSON-a (`api` / `vs_reference.detail`).
|
||||||
|
|
||||||
## Front — Command Center
|
## Front — Command Center
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,35 @@ def _surface_counts(snap: Snapshot) -> dict[str, int]:
|
|||||||
return {axis: len(_keys(snap, axis)) for axis in _AXES}
|
return {axis: len(_keys(snap, axis)) for axis in _AXES}
|
||||||
|
|
||||||
|
|
||||||
|
def surface_api(snap: Snapshot) -> dict[str, Any]:
|
||||||
|
"""The full *supported* surface of one variant: every type, and per class the methods, events
|
||||||
|
and fields it exposes. This is the baseline — 'what is there' — so the diff against the
|
||||||
|
reference variant has a point of reference to read against."""
|
||||||
|
classes: dict[str, dict[str, list]] = {}
|
||||||
|
|
||||||
|
def cls(owner: str | None) -> dict[str, list]:
|
||||||
|
return classes.setdefault(owner or "?", {"methods": [], "events": [], "fields": []})
|
||||||
|
|
||||||
|
for m in snap.methods:
|
||||||
|
cls(m.get("owner"))["methods"].append({"name": m["name"], "id": m.get("id")})
|
||||||
|
for e in snap.events:
|
||||||
|
cls(e.get("owner"))["events"].append({"name": e["name"], "order": e.get("order")})
|
||||||
|
for f in snap.fields:
|
||||||
|
cls(f.get("owner"))["fields"].append({"name": f["name"], "type": f.get("type")})
|
||||||
|
|
||||||
|
for d in classes.values():
|
||||||
|
d["methods"].sort(key=lambda x: x["name"])
|
||||||
|
d["events"].sort(key=lambda x: (x["order"] if x["order"] is not None else 1 << 30, x["name"]))
|
||||||
|
d["fields"].sort(key=lambda x: x["name"])
|
||||||
|
|
||||||
|
types = sorted(
|
||||||
|
({"script_name": t["script_name"], "cpp_class": t.get("cpp_class"),
|
||||||
|
"object_size": t.get("object_size")} for t in snap.types),
|
||||||
|
key=lambda x: x["script_name"],
|
||||||
|
)
|
||||||
|
return {"types": types, "classes": dict(sorted(classes.items()))}
|
||||||
|
|
||||||
|
|
||||||
def _axis_counts(block: dict[str, Any]) -> dict[str, int]:
|
def _axis_counts(block: dict[str, Any]) -> dict[str, int]:
|
||||||
return {
|
return {
|
||||||
"added": len(block["added"]),
|
"added": len(block["added"]),
|
||||||
@@ -182,6 +211,7 @@ def _build_library(name: str, entries: list[Entry]) -> dict[str, Any]:
|
|||||||
"id": vid,
|
"id": vid,
|
||||||
"reference": is_ref,
|
"reference": is_ref,
|
||||||
"surface": _surface_counts(sample),
|
"surface": _surface_counts(sample),
|
||||||
|
"api": surface_api(sample),
|
||||||
"members": members,
|
"members": members,
|
||||||
"vs_reference": None if is_ref else _vs_reference(reference_snap, sample),
|
"vs_reference": None if is_ref else _vs_reference(reference_snap, sample),
|
||||||
}
|
}
|
||||||
@@ -344,10 +374,13 @@ def render_markdown(table: dict[str, Any]) -> str:
|
|||||||
m["game"], m["engine"] or "?", m["compiler"] or "?", _short(m["sha256"]))
|
m["game"], m["engine"] or "?", m["compiler"] or "?", _short(m["sha256"]))
|
||||||
for m in v["members"]
|
for m in v["members"]
|
||||||
)
|
)
|
||||||
|
class_names = list(v["api"]["classes"])
|
||||||
out.append(
|
out.append(
|
||||||
"- **{0}** ({1}) — typy {2} / metody {3} / eventy {4} / pola {5}".format(
|
"- **{0}** ({1}) — klasy {2} / typy {3} / metody {4} / eventy {5} / pola {6}".format(
|
||||||
v["id"], tag, s["types"], s["methods"], s["events"], s["fields"]))
|
v["id"], tag, len(class_names), s["types"], s["methods"], s["events"], s["fields"]))
|
||||||
out.append(" - gry: {0}".format(games_str))
|
out.append(" - gry: {0}".format(games_str))
|
||||||
|
if class_names:
|
||||||
|
out.append(" - klasy: {0}".format(_signed("", class_names, cap=30)))
|
||||||
vs = v["vs_reference"]
|
vs = v["vs_reference"]
|
||||||
if vs:
|
if vs:
|
||||||
ax = vs["axes"]
|
ax = vs["axes"]
|
||||||
|
|||||||
@@ -97,6 +97,17 @@ def test_hash_prefix_is_stripped_for_grouping():
|
|||||||
assert "333ab0c4_PIKLIB8.dll" in files
|
assert "333ab0c4_PIKLIB8.dll" in files
|
||||||
|
|
||||||
|
|
||||||
|
def test_variant_carries_full_supported_api():
|
||||||
|
# the baseline: each variant lists *what is there*, grouped by class — not just the diff
|
||||||
|
t = compatibility_table([
|
||||||
|
Entry("Game A", _snap("X.dll", ["SHOW", "HIDE"], events=["ONCLICK"])),
|
||||||
|
])
|
||||||
|
api = t["libraries"][0]["variants"][0]["api"]
|
||||||
|
assert [m["name"] for m in api["classes"]["CMC_Animo"]["methods"]] == ["HIDE", "SHOW"]
|
||||||
|
assert [e["name"] for e in api["classes"]["CMC_Animo"]["events"]] == ["ONCLICK"]
|
||||||
|
assert [t_["script_name"] for t_ in api["types"]] == ["ANIMO"]
|
||||||
|
|
||||||
|
|
||||||
def test_grouping_is_case_insensitive_keeps_common_spelling():
|
def test_grouping_is_case_insensitive_keeps_common_spelling():
|
||||||
t = compatibility_table([
|
t = compatibility_table([
|
||||||
Entry("Game A", _snap("Piklib8.dll", ["SHOW"])),
|
Entry("Game A", _snap("Piklib8.dll", ["SHOW"])),
|
||||||
|
|||||||
Reference in New Issue
Block a user