"""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. Each condition's own `Party` field ("CUSTOMER" or "PROVIDER") says who performs it, checked against the contract's own top-level `Party` field (the player's role in that contract - usually "CUSTOMER"). Condition vocabulary, direction confirmed against real contract JSON (2026-10-17): PAYMENT/REPUTATION (always granted TO the player by the PROVIDER, regardless of which `Party` the condition lists), PROVISION_SHIPMENT (the player's `Party` supplies this material - a real COST, buy-fresh-priced), COMEX_PURCHASE_PICKUP (the partner already bought this via Comex - a REWARD handed to the player, sell-valued), PICKUP_SHIPMENT/DELIVERY_SHIPMENT (a logistics leg performed by whichever `Party` it lists - free to the player when that's the PROVIDER's leg, e.g. their transporter collecting what you provisioned; a real freight cost via `puga.shipping` when it's the player's own leg, not priced by this module, flagged with weight/volume/address instead), 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 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, materials the contract hands TO the player (COMEX_PURCHASE_PICKUP, sell-valued), materials the player must supply (PROVISION_SHIPMENT on the player's own Party, buy-fresh cost), freight legs the player must personally fly (PICKUP/DELIVERY_SHIPMENT on the player's own Party - weight/volume flagged, not priced), and any other unpriced/contextual conditions - all for the caller to weigh. net = payment + reward_value - cost_value (freight excluded, flagged separately).""" my_party = contract.get("Party") # the player's role in THIS contract, e.g. "CUSTOMER" payment = 0.0 reputation = False rewards, costs, freight_legs = [], [], [] flags = [] deadline_days = 0.0 for cond in contract["Conditions"]: t = cond["Type"] mine = cond.get("Party") == my_party if t == "PAYMENT" and cond.get("Amount"): payment += cond["Amount"] elif t == "REPUTATION": reputation = True elif t == "COMEX_PURCHASE_PICKUP" and cond.get("MaterialTicker"): rewards.append((cond["MaterialTicker"], cond["MaterialAmount"], cond.get("Address"))) elif t == "PROVISION_SHIPMENT" and cond.get("MaterialTicker") and mine: costs.append((cond["MaterialTicker"], cond["MaterialAmount"], cond.get("Address"))) elif t in ("PICKUP_SHIPMENT", "DELIVERY_SHIPMENT") and mine: freight_legs.append((t, cond.get("Address"), cond.get("Weight"), cond.get("Volume"))) elif t not in ("PAYMENT", "REPUTATION", "COMEX_PURCHASE_PICKUP", "PROVISION_SHIPMENT", "PICKUP_SHIPMENT", "DELIVERY_SHIPMENT"): flags.append((t, cond.get("Address"))) dl = cond.get("DeadlineDurationMs") if dl: deadline_days = max(deadline_days, dl / 86400000) def price_all(items, side): total, priced = 0.0, [] for tick, qty, addr in items: r = market.walk(tick, cx, qty, side) priced.append({"ticker": tick, "qty": qty, "address": addr, "value": r["total"], "short": r["short"]}) total += r["total"] return total, priced reward_value, priced_rewards = price_all(rewards, "sell") cost_value, priced_costs = price_all(costs, "buy") return { "id": contract["ContractLocalId"], "partner": contract.get("PartnerName"), "payment": payment, "reputation": reputation, "deadline_days": deadline_days, "rewards": priced_rewards, "reward_value": reward_value, "costs": priced_costs, "cost_value": cost_value, "freight_legs": freight_legs, "net": payment + reward_value - cost_value, "flags": flags, }