"""Player-to-player CONTD contracts (FIO /contract/allcontracts/{user}) - the NPC logistics-officer offers shown in APEX's CONTD panel, not the public Local Market hauling ads in puga/contracts.py. Only OPEN contracts are real choices - exactly one of the pool of (usually 3) offers can be accepted; CANCELLED/REJECTED/FULFILLED/PARTIALLY_FULFILLED are history or already-committed work. Condition vocabulary seen in this account's full history (2026-10-16): PAYMENT, REPUTATION, PROVISION_SHIPMENT and COMEX_PURCHASE_PICKUP (a material+qty+address you must supply - these are the only ones with a real market buy-fresh cost), PICKUP_SHIPMENT/DELIVERY_SHIPMENT (logistics legs, no separate cost beyond the material), and open-ended ones this module deliberately does NOT price because their real cost depends on context this API can't see (a ship already flying that route, a planet you were about to survey anyway, a ship already damaged): EXPLORATION (Address = planet to survey), REPAIR_SHIP, HEADQUARTERS_UPGRADE, BASE_CONSTRUCTION, CONTRIBUTION, WAIT, INCREASE_SATISFACTION. Judging whether one of those is actually cheap right now is the caller's job. """ from . import fio, market MATERIAL_TYPES = {"PROVISION_SHIPMENT", "COMEX_PURCHASE_PICKUP"} def open_contracts(): me = fio.me() data = fio.own(f"/contract/allcontracts/{me}", ttl=60) return [c for c in data if c["Status"] == "OPEN"] def evaluate(contract: dict, cx: str) -> dict: """Payment, priced material requirements (buy-fresh cost at `cx` - assumes none already in free stock, check storage for materials you may already hold), and any unpriced/contextual conditions flagged separately for the caller to judge.""" payment = 0.0 reputation = False requirements = [] # (ticker, qty, address) flags = [] # (type, address) for conditions this module won't price deadline_days = 0.0 for cond in contract["Conditions"]: t = cond["Type"] if t == "PAYMENT" and cond.get("Amount"): payment += cond["Amount"] elif t == "REPUTATION": reputation = True elif t in MATERIAL_TYPES and cond.get("MaterialTicker"): requirements.append((cond["MaterialTicker"], cond["MaterialAmount"], cond.get("Address"))) elif t not in MATERIAL_TYPES | {"PAYMENT", "REPUTATION", "PICKUP_SHIPMENT", "DELIVERY_SHIPMENT"}: flags.append((t, cond.get("Address"))) dl = cond.get("DeadlineDurationMs") if dl: deadline_days = max(deadline_days, dl / 86400000) material_cost = 0.0 short = False priced = [] for tick, qty, addr in requirements: r = market.walk(tick, cx, qty, "buy") priced.append({"ticker": tick, "qty": qty, "address": addr, "cost": r["total"], "short": r["short"]}) material_cost += r["total"] short = short or r["short"] return { "id": contract["ContractLocalId"], "partner": contract.get("PartnerName"), "payment": payment, "reputation": reputation, "deadline_days": deadline_days, "requirements": priced, "material_cost": material_cost, "net": payment - material_cost, "short": short, "flags": flags, }