"""q_cd_route_1 -- the club route family.

HYPOTHESIS
  The 125-row action table at 0x1802caa20 binds each client-originated request to a
  URL base out of the 48-row base table at 0x18021df80 (16-byte rows: char* template,
  char* symbolic name).  Exactly four rows carry base index 3 = "ut/%s/club":
  ClubSearch (fn 0x180123a60), ClubStats (0x180123a70), StaffStats (0x1801247e0),
  ConsumablesSearch (0x180123a80).  If that is right, those four factories are the
  COMPLETE set of club-route request builders and everything the client can emit on
  /club is one of them.

CONTROL
  Decompile a NON-club factory from the same table in the same pass (PurchasedItems
  0x180124260, base 26 = ut/%s/purchased) and confirm it resolves to a different
  request class with a different suffix builder.  If the four club factories and the
  control all decompile to the same shape, the shape is real; if the control comes
  back empty while the targets do too, the method is broken, not the answer.

  Second control: the /stats/%s, /stats/staff and /consumables/%s literals were found
  by RIP-relative displacement scan of .text on the ON-DISK PE, at 0x18012f5b5,
  0x18012b086 and 0x18013090e.  Those three functions must turn out to be the URL
  builders of three of the four classes.  If they are not, the base-index reading of
  column 1 is wrong.
"""
import traceback

try:
    TARGETS = [
        ("ClubSearch.factory",        0x180123a60),
        ("ClubStats.factory",         0x180123a70),
        ("StaffStats.factory",        0x1801247e0),
        ("ConsumablesSearch.factory", 0x180123a80),
        ("CONTROL PurchasedItems.factory", 0x180124260),
        ("uses /stats/%s",            0x18012f5b5),
        ("uses /stats/staff",         0x18012b086),
        ("uses /consumables/%s",      0x18013090e),
        ("uses both enum tables",     0x180166306),
    ]
    for label, ea in TARGETS:
        f = func(ea)
        print("=" * 78)
        print("### %s  @ %s  -> %s" % (label, hex(ea), f.getName() if f else "NO FUNC"))
        if f is None:
            continue
        print("    entry %s" % f.getEntryPoint())
        src = dec(f)
        print("    len(src) = %d" % len(src))
        print(src)
except Exception:
    traceback.print_exc()
