"""Rank planets by extraction factor for a resource. Also holds environment_extras(): FIO's own BuildRequirements field is an unreliable superset across hazard types (confirmed wrong in-game, see docs/mechanics.md) - the real per-building material is computed from the planet's own pressure/gravity/temperature/surface against the Prosperous Universe Handbook's threshold table, which PRUNplanner's own calculations don't model either.""" from . import fio # (condition check, ticker, qty per unit area, flat qty) - handbook building-costs table ENV_RULES = [ (lambda p: (p.get("pressure") or 0) < 0.25, "SEA", 1.0, 0.0), (lambda p: (p.get("pressure") or 0) > 2.0, "HSE", 0.0, 1.0), (lambda p: 0 < (p.get("gravity") or 1) < 0.25, "MGC", 0.0, 1.0), (lambda p: (p.get("gravity") or 0) > 2.5, "BL", 0.0, 1.0), (lambda p: (p.get("temperature") if p.get("temperature") is not None else 20) < -25, "INS", 10.0, 0.0), (lambda p: (p.get("temperature") or 0) > 75, "TSH", 0.0, 1.0), ] def environment_extras(planet: dict, area: float) -> dict[str, float]: """Extra construction/repair materials a building needs beyond its normal BuildingCosts and the universal MCG area cost (already handled elsewhere, e.g. simulate()'s mcg_per_area) - one row per hazard the planet actually has (pressure/gravity/temperature; rocky-vs-gaseous MCG/AEF swap not covered here). planet needs lowercase pressure/gravity/temperature keys, e.g. from prunplanner._g('/data/planet/{id}/') or fio.planets_full() remapped to lowercase.""" out: dict[str, float] = {} for cond, tk, per_area, flat in ENV_RULES: if cond(planet): out[tk] = out.get(tk, 0.0) + per_area * area + flat return out def candidates(resource_ticker: str, min_factor: float = 0.0): """All planets with this resource, sorted by factor descending. Each: PlanetNaturalId, PlanetName, factor, resource_type, plus the raw planet record (temperature/pressure/ gravity/fertility/faction/BuildRequirements/SystemId etc).""" mats = {m["Ticker"]: m["MaterialId"] for m in fio.materials()} mid = mats.get(resource_ticker.upper()) if not mid: raise ValueError(f"unknown material ticker {resource_ticker!r}") out = [] for p in fio.planets_full(): for r in p.get("Resources", []): if r["MaterialId"] == mid and r["Factor"] >= min_factor: out.append({ "natural_id": p["PlanetNaturalId"], "name": p["PlanetName"], "factor": r["Factor"], "resource_type": r["ResourceType"], "temperature": p["Temperature"], "pressure": p["Pressure"], "gravity": p["Gravity"], "fertility": p["Fertility"], "faction": p.get("FactionCode"), "system_id": p["SystemId"], "build_requirements": p.get("BuildRequirements", []), }) out.sort(key=lambda x: -x["factor"]) return out