diff --git a/AGENTS.md b/AGENTS.md index 5ce9f19..09ea4d5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -67,11 +67,13 @@ history/ │ ├── region-adjacency.json # region key -> bordering region keys, 1,800 entries (the getNeighbours data, #16 P2) │ ├── region-centroids.json # region key -> {lat,lon,spread} anchor for map markers, 1,800 entries (#44) │ ├── region-geo.json # region key -> {area (km²), population}, 1,800 entries (the area×population weighting for per-region stats, #46) +│ ├── region-resources.json # region key -> synthesized {oil, iron, food, industry} (each 0–1, 2dp), 1,800 entries (the resource profiles that scale industry boosts + feed the prompt aggregate, #59) │ └── ne-admin0-pop.json # ISO_A3 -> admin-0 POP_EST, 249 codes (the committed population SOURCE for region-geo.json — a small derived table, the 13 MB Natural Earth source is NOT committed, #46) ├── scripts/ # the geo/manifest data pipeline — .mjs (turf allowed HERE only; │ │ # never imported by .ts): generate → coarsen → cleanup → smooth → │ │ # fill-gaps → split-arkhangel → split-arkhangel-band → build-region-keys │ │ # → build-region-adjacency → build-region-centroids → build-region-geo +│ │ # → build-region-resources │ │ # (build-region-geo reads the COMMITTED ne-admin0-pop.json; that small │ │ # table is distilled once from the 13 MB Natural Earth admin-0 source by │ │ # extract-admin0-pop.mjs — the raw source is never committed, #46) @@ -131,6 +133,7 @@ history/ | `npm run split:regions:band` | (re)apply the #41 Arctic-coast-band split (`RU-ARK` mainland's 28-part lat ≥ 68 band → `RU-PEO` + `RU-YAM`) — idempotent no-op once applied | | `npm run build:region-keys` / `build:region-adjacency` / `build:region-centroids` | (re)generate the `public/region-keys.json` / `region-adjacency.json` / `region-centroids.json` manifests — deterministic + idempotent (byte-identical re-run) | | `npm run build:region-geo` | (re)generate `public/region-geo.json` (region key → area km² + population) from `regions.geo.json` + `region-keys.json` + the committed `ne-admin0-pop.json` — deterministic + idempotent (byte-identical re-run; #46) | +| `npm run build:region-resources` | (re)generate `public/region-resources.json` (region key → synthesized `{ oil, iron, food, industry }` 0–1 profile) from `region-keys.json` + `region-geo.json` (area factor) — deterministic + idempotent (byte-identical re-run; #59) | | `npm run extract:admin0-pop` | one-time distillation of the 13 MB Natural Earth admin-0 source → the committed `public/ne-admin0-pop.json` (ISO_A3 → `POP_EST`, 249 codes); the raw source is never committed (#46) | | `docker compose up -d --build` | prod image on :4321, routed via Traefik at `history.dev.kkhost.pl` | @@ -407,6 +410,38 @@ history/ **stub never** declares or lifts a trade/embargo (`economy: { trade: [], embargo: [] }`), so e2e (CI, `LLM_STUB=1`) is unaffected and the path is unit-tested only (`server/engine.test.ts`). +- **Resources & Industry — per-region resource profiles + the `industry` lever (v0.36, #59).** + Since v0.36 each of the 1,800 sub-regions carries a **synthesized 4-value resource profile** + (`{ oil, iron, food, industry }`, each 0–1, 2dp) from the committed `public/region-resources.json` + — built by the deterministic, idempotent `scripts/build-region-resources.mjs` (an FNV-1a hash of + `` `${key}\u0000${resource}` `` scaled by an area factor from `region-geo.json`, clamped to 1, + byte-identical re-run) and loaded by `server/regions.ts` via the same optional-manifest pattern as + the other manifests (`hasResources()` / `resourceOf()`, probe `public/` then `dist/`; a missing or + malformed file degrades — boosts use the unscaled base value and the aggregate is omitted from the + prompt, never a crash). `TurnResult.industry = { projects: IndustryProject[] }` (required, default + `{ projects: [] }`; `IndustryProject = { regionKey, type }`, `type ∈ INDUSTRY_TYPES = + oil | iron | food | industry`) declares a project on a region. `applyTurnResult` maintains + `GameState.industry` (required, `[]` at creation; a legacy SQLite row without the field loads as + `[]` — `db.ts`, additive, never wiped) as a **per-region SET**: a region key not in the valid-keys + manifest is dropped; a region that already hosts a project is untouched (the first declared type + wins — re-declaring is a no-op, the type is never replaced). Every committed turn, + `applyIndustryEffects` (placed after the economy block, before markers; the owner is resolved from + the FINAL post-claim ownership) grants each active project's region's **SOLE owner** a small, + deterministic economy boost — `INDUSTRY_ECONOMY_BONUS = 1` plus one extra point when the region's + `industry` resource value is ≥ 0.5 (without the manifest, just the base) — clamped to 0–100, + mirrored to every region the owner holds (`regionStats`), and each affected nation's derived `stats` + re-derived afterwards (same 0-region / no-entry guards as the economy/hybrid dips). A project on a + region with 0 or 2+ owners yields no boost but is **kept** in the list (never removed, never + thrown); sole ownership is untouched (the layer moves stats, never territory). `isMeaningful` + counts non-empty `industry.projects`; the system prompt documents the field + constraints (a region + holds at most one project — never re-declare on a region that already has one; at most 1–2 per + turn, each narrated in `events`), and the user payload carries the active projects (`industry`) + plus each nation's aggregate resource profile (`resources` — `deriveNationResources` in + `shared/protocol.ts`, the area×population-weighted **average** of the owned regions' profiles; + omitted entirely when the manifest is not loaded). The **stub never** declares a project + (`industry: { projects: [] }`) — e2e (CI, `LLM_STUB=1`) is unaffected and the path is unit-tested + only (`server/engine.test.ts`, `server/protocol.test.ts`, `server/regions.test.ts`, + `server/db.test.ts`, `scripts/build-region-resources.test.ts`). - **Map click → dossier target (owner resolved from the RegionMap, by region key).** Clicking a sub-region does NOT open a popup — it switches the dossier to that sub-region's owning nation (`focusNation(ownerId, {name})` in `App.tsx`, which also records which region was diff --git a/CHANGELOG.md b/CHANGELOG.md index c445cbc..4531791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ All notable changes to **History** are listed here, newest first. +## v0.36.0 — 2026-10-15 18:17 +- **#59: Resources & Industry — per-region synthesized resource profiles + a per-region industry-project lever with a deterministic per-turn economy boost.** Every prior lever moved borders, dipped stats one-shot, or proposed a player-confirmed change; this version adds a **resource abundance layer** (every sub-region gets a synthesized 4-value profile) and a **development lever**: the model can build industry projects (oil facilities, iron mines, food operations, factories) in individual regions, and every committed turn each active project pays its region's sole owner a small, deterministic economy gain scaled by the region's `industry` resource value. The engine is **fully deterministic (no hidden randomness)**: the resource profiles are a pure function of the region key (FNV-1a) scaled by an area factor, and the per-turn effect is a fixed, clamped, mirrored, re-derived stat adjustment. + - **Manifest (`public/region-resources.json`, new).** 1,800 entries — region key → `{ oil, iron, food, industry }` (each 0–1, 2dp) — built by the new turf-free, deterministic, **idempotent** `scripts/build-region-resources.mjs` (`npm run build:region-resources`): per resource, `(fnv1a32(`${key}\u0000${resource}`) & 0x3fff) / 0x4000` → [0,1), times an area factor `1 + 0.2·min(1, log10(1+area)/8)` (max ≈1.2) from `region-geo.json` (missing geo / zero area → pure hash), clamped to 1, keys sorted, byte-identical re-run. Pinned by `scripts/build-region-resources.test.ts` (key-set equality vs `region-keys.json`, sorted order, per-entry shape, spot-checked values, determinism via a re-run). + - **Types (`shared/types.ts`).** New `RegionResources` (`{ oil; iron; food; industry }`), `IndustryType` (`'oil' | 'iron' | 'food' | 'industry'`) + `INDUSTRY_TYPES` const, `IndustryProject` (`{ regionKey; type }`), and the required `GameState.industry: IndustryProject[]` field (placed after `embargoes`). `[]` on a fresh game; rows saved before v0.36 load with it defaulted to `[]` (additive, never wiped). + - **Protocol (`shared/protocol.ts`).** New `IndustryOps` (`{ projects: IndustryProject[] }`); `TurnResult.industry` is required, placed between `economy` and `markers`. New exported `deriveNationResources(regionKeys, resourceOf?, geoOf?)` — a nation's aggregate profile as the **area×population-weighted AVERAGE** (an average, not a median, is the meaningful aggregation for an abundance profile) of the resource profiles of its owned regions, same weight formula as `deriveNationStats`, 2dp-rounded, zero profile when no owned region has a profile. + - **Engine (`server/engine.ts`).** + - `isIndustryType(t)` — exported guard over the four types (mirrors `isHybridOpType`). + - `validateIndustryOps(raw)` — new exported, defensive validator (never throws): a missing/malformed object yields `{ projects: [] }`; each op needs a non-empty `regionKey` (≤120 chars) and a known `type`. + - `industryBoost(regionKey, resourceOf?)` — internal; `INDUSTRY_ECONOMY_BONUS = 1` plus one extra point when the region's `industry` value is ≥ 0.5 (without the manifest, just the base). + - `applyIndustryOps(next, ops, validKeys?)` — internal; applies the turn's projects to `GameState.industry` as a **per-region SET** — a key not in the valid-keys manifest is dropped; a region that already hosts a project is untouched (first type wins; re-declare is a no-op, the type is never replaced). + - `applyIndustryEffects(next, resourceOf?, geoOf?)` — new exported; the per-turn effect, applied **every committed turn** to the **full** active list: each project grants its region's **SOLE owner** (owner resolved from the FINAL post-claim ownership; 0 or 2+ owners → no boost, project **kept**, never thrown) a deterministic economy boost, clamped to 0–100, mirrored to every region the owner holds (`regionStats`), and each affected nation's derived `stats` re-derived afterwards (same 0-region / no-entry guards as the economy/hybrid dips). Sole ownership is untouched (the layer moves stats, never territory). No-op when there are no active projects; never throws. + - `applyTurnResult` — new `resourceOf` param (last) and **industry block** (after the economy block, before markers): `applyIndustryOps` → `applyIndustryEffects` (ops first, so a project declared this turn is paid this turn). + - `isMeaningful` — non-empty `industry.projects` makes a turn meaningful. + - `validateTurnResult` — initializes and validates `industry` (default `{ projects: [] }`). + - `buildSystemPrompt` — documents the `industry` field and a constraint bullet (a per-resource development lever; one project per region — never re-declare on a region that already has one; at most 1–2 per turn, each narrated in `events`) in both tool and plain modes. + - `buildUserPrompt` — new optional `nationResources` (each nation's aggregate profile) and `industryProjects` (the active projects) params — emitted as `resources` / `industry` in the payload, only when provided (so the stub / no-manifest prompt stays byte-identical). + - `runTurn` — new optional `resourceOf` (last); computes `nationResources` via `deriveNationResources` **only when** the resource manifest is loaded (otherwise omitted from the prompt); passes both new payload fields; the "unclear" fallback carries `industry: { projects: [] }`; `applyTurnResult` receives `resourceOf`. + - **Regions loader (`server/regions.ts`).** The optional-manifest pattern extended: `region-resources.json` is probed after `public/` then `dist/`; malformed entries (any of the four values not a finite number in [0,1]) are filtered out, a failure logs `[regions] failed to load region-resources.json, continuing without it` and the server keeps working without it; new `hasResources()` / `resourceOf(key)` accessors (mirror `hasGeo()` / `geoOf()`). + - **Server wiring (`server/index.ts`).** The jump route passes `resourceOf: hasResources() ? (key) => resourceOf(key) : undefined` into `runTurn` (like `geoOf`); fresh preset games are created with `industry: []` (dynamic games already via `shared/scenario.ts`). + - **Persistence (`server/db.ts`).** `load()` defaults `industry` to `[]` on rows saved before v0.36 (additive migration, alongside `unowned`/`pendingNationOps`/`markers`/`wars`/`trades`/`embargoes`) — legacy games are never wiped and never gain phantom projects. + - **Stub (`server/stub.ts`).** The deterministic stub returns `industry: { projects: [] }` — it **never** declares an industry project, so the e2e (CI, `LLM_STUB=1`) assertions are unaffected and the path is covered by unit tests only. `StubPayload` gains optional `resources` / `industry` fields (ignored). + - **Unit tests.** New: `scripts/build-region-resources.test.ts` (5 tests); `server/regions.test.ts` (resources load/spot-check/unknown-key, degradation, prod `dist/` layout, incl. a new "with the manifest" case); `server/protocol.test.ts` — `deriveNationResources` (7 tests: area×population weighting, unweighted degradation, profile-skipping, zero profile, single region, weight fallback, 2dp rounding); `server/db.test.ts` — legacy-row default; `server/engine.test.ts` — `validateIndustryOps` (shape/drops), `applyTurnResult` industry ops (declare, per-region SET / re-declare no-op, invalid-key drop, persistence across turns), `applyIndustryEffects` (sole-owner boost, ≥0.5 scaling, multi-project accumulation, ownerless/2+ owner kept-but-unpaid, no-op empty), `isMeaningful`, the system-prompt contract (both modes), the user-prompt payload (carried / omitted), and the `runTurn` defensive init; all pre-existing fixtures gained the new required fields (mechanical, deliberate updates). + - **Client.** No change — the industry layer is an engine/LLM concern; its effects surface through the existing stats and event feed. + - **AGENTS.md.** New convention entry documenting the resource manifest, the per-region SET semantics, the sole-owner per-turn boost, and the stub/test coverage; the `public/` layout, the scripts pipeline line, and the Commands table all gained `region-resources` / `build:region-resources`. + ## v0.35.0 — 2026-10-15 17:22 - **#58: Trade & Embargoes — a bilateral trade + embargo economy layer with a deterministic per-turn effect and war auto-suspension.** Every prior turn lever moved borders, dipped stats one-shot, or proposed a player-confirmed change. This version adds `TurnResult.economy = { trade: EconomyTradeOp[]; embargo: EconomyEmbargoOp[] }` (required, default `{ trade: [], embargo: [] }`) so the model can declare/lift **bilateral trade agreements** and **unilateral embargoes**, which persist in `GameState` and apply a small, deterministic economic effect **every committed turn**. The engine is **fully deterministic (no hidden randomness)** and **additive** — declares add to the lists, lifts remove, and nothing else (not even a war, beyond the suspension below) mutates them. - **Types (`shared/types.ts`).** New `TradeAgreement` (`{ a; b }` — a symmetric pair, stored sorted `a < b`) and `Embargo` (`{ from; target }` — an ordered unilateral pair) interfaces, plus the required `GameState.trades` and `GameState.embargoes` fields (placed after `wars`). Both are `[]` on a fresh game; rows saved before v0.35 load with them defaulted to `[]` (additive, never wiped). diff --git a/package.json b/package.json index 6ef94ef..ef99f9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "history", - "version": "0.35.0", + "version": "0.36.0", "private": true, "type": "module", "description": "AI-driven alternate-history simulator — the LLM is the world engine (Pax Historia style).", @@ -20,6 +20,7 @@ "build:region-adjacency": "node scripts/build-region-adjacency.mjs", "build:region-centroids": "node scripts/build-region-centroids.mjs", "build:region-geo": "node scripts/build-region-geo.mjs", + "build:region-resources": "node scripts/build-region-resources.mjs", "extract:admin0-pop": "node scripts/extract-admin0-pop.mjs", "typecheck": "tsc --noEmit", "lint": "eslint .", diff --git a/public/region-resources.json b/public/region-resources.json new file mode 100644 index 0000000..f1a7e2e --- /dev/null +++ b/public/region-resources.json @@ -0,0 +1,10802 @@ +{ + "aberdeenshire-kzrn": { + "oil": 0.64, + "iron": 0.39, + "food": 0.01, + "industry": 0.81 + }, + "abra-cmfg": { + "oil": 0.43, + "iron": 0.98, + "food": 0.9, + "industry": 0.95 + }, + "abu-dhabi-mywn": { + "oil": 1, + "iron": 0.08, + "food": 0.3, + "industry": 0.16 + }, + "abyan-oexn": { + "oil": 0.41, + "iron": 0.79, + "food": 1, + "industry": 0.13 + }, + "aceh-ocsz": { + "oil": 0.23, + "iron": 0.42, + "food": 0.6, + "industry": 0.6 + }, + "acklins-qehg": { + "oil": 0.29, + "iron": 0.67, + "food": 1, + "industry": 0.75 + }, + "acre-ekzw": { + "oil": 0.26, + "iron": 0.52, + "food": 0.15, + "industry": 0.79 + }, + "ad-dakhliyah-qtih": { + "oil": 0.83, + "iron": 0.49, + "food": 0.73, + "industry": 1 + }, + "adamaoua-kqsc": { + "oil": 0.37, + "iron": 0.56, + "food": 0.26, + "industry": 0.1 + }, + "adamawa-ehbv": { + "oil": 0.12, + "iron": 1, + "food": 0.46, + "industry": 0.85 + }, + "adana-wdhs": { + "oil": 1, + "iron": 0.38, + "food": 0.08, + "industry": 0.57 + }, + "adrar-ctwy": { + "oil": 0.41, + "iron": 0.15, + "food": 0.26, + "industry": 0.29 + }, + "adrar-dffe": { + "oil": 0.34, + "iron": 0.3, + "food": 0.39, + "industry": 1 + }, + "afar-cnlj": { + "oil": 0.15, + "iron": 1, + "food": 0.86, + "industry": 0.18 + }, + "afyonkarahisar-gghu": { + "oil": 0.25, + "iron": 0.62, + "food": 0.37, + "industry": 0.93 + }, + "agadez-ijfb": { + "oil": 0.41, + "iron": 0.24, + "food": 1, + "industry": 0.72 + }, + "agcabadi-yazh": { + "oil": 0.91, + "iron": 0.98, + "food": 0.98, + "industry": 0.03 + }, + "agneby-glsq": { + "oil": 0.97, + "iron": 0.04, + "food": 0.91, + "industry": 0 + }, + "agri-cvhn": { + "oil": 0.55, + "iron": 0.67, + "food": 0.27, + "industry": 0.17 + }, + "agusan-del-sur-efza": { + "oil": 0.44, + "iron": 0.92, + "food": 0.66, + "industry": 0.39 + }, + "ahal-weco": { + "oil": 0.89, + "iron": 0.45, + "food": 0.67, + "industry": 0.81 + }, + "ain-lqtt": { + "oil": 0.94, + "iron": 0.92, + "food": 0.51, + "industry": 0.4 + }, + "aisen-del-general-carlos-ibanez-del-campo-mrpn": { + "oil": 0.63, + "iron": 0.8, + "food": 0.34, + "industry": 0.08 + }, + "aisne-gstu": { + "oil": 0.3, + "iron": 0.78, + "food": 0.81, + "industry": 0.88 + }, + "ajdabiya-ikqv": { + "oil": 0.77, + "iron": 1, + "food": 1, + "industry": 0.37 + }, + "akershus-ityh": { + "oil": 0.53, + "iron": 0.96, + "food": 0.45, + "industry": 0.5 + }, + "akita-mmft": { + "oil": 0.53, + "iron": 0.03, + "food": 0.77, + "industry": 0.68 + }, + "aksaray-cbcb": { + "oil": 0.22, + "iron": 1, + "food": 1, + "industry": 0.83 + }, + "al-anbar-yjqa": { + "oil": 0.7, + "iron": 0.17, + "food": 0.77, + "industry": 0.96 + }, + "al-bahah-ajsr": { + "oil": 0.03, + "iron": 0.66, + "food": 0.23, + "industry": 0.96 + }, + "al-bahr-al-ahmar-oaom": { + "oil": 0.62, + "iron": 0.86, + "food": 0.61, + "industry": 0.45 + }, + "al-basrah-lrsw": { + "oil": 0.94, + "iron": 0.13, + "food": 0.89, + "industry": 0.94 + }, + "al-batnah-north-ilnl": { + "oil": 0.17, + "iron": 0.38, + "food": 0.12, + "industry": 0.02 + }, + "al-buhayrah-ilnf": { + "oil": 0.13, + "iron": 0.12, + "food": 0.22, + "industry": 0.58 + }, + "al-butnan-gytn": { + "oil": 0.37, + "iron": 0.84, + "food": 0.45, + "industry": 0.55 + }, + "al-dhahira-eqif": { + "oil": 0.64, + "iron": 0.37, + "food": 0.91, + "industry": 0.04 + }, + "al-fayyum-wdgf": { + "oil": 0.98, + "iron": 0.46, + "food": 0.2, + "industry": 0.34 + }, + "al-hudaydah-aubl": { + "oil": 0.45, + "iron": 0.84, + "food": 0.45, + "industry": 0.06 + }, + "al-hudud-ash-shamaliyah-kdqu": { + "oil": 0.82, + "iron": 0.67, + "food": 0.7, + "industry": 0.98 + }, + "al-jahrah-cvgx": { + "oil": 0.13, + "iron": 0.22, + "food": 0.96, + "industry": 0.59 + }, + "al-jawf-misq": { + "oil": 0.4, + "iron": 0.36, + "food": 0.22, + "industry": 0.07 + }, + "al-jawf-wngz": { + "oil": 0.6, + "iron": 0.32, + "food": 1, + "industry": 1 + }, + "al-jizah-abuz": { + "oil": 0.88, + "iron": 0.16, + "food": 0.01, + "industry": 0.68 + }, + "al-jufrah-mrvm": { + "oil": 0.01, + "iron": 0.1, + "food": 0.14, + "industry": 0.7 + }, + "al-kufrah-ehbh": { + "oil": 0.21, + "iron": 1, + "food": 0.67, + "industry": 0.64 + }, + "al-madinah-uwqp": { + "oil": 0.42, + "iron": 0.81, + "food": 0.13, + "industry": 0.51 + }, + "al-mahrah-gatz": { + "oil": 0.07, + "iron": 0.47, + "food": 0.44, + "industry": 0.19 + }, + "al-marj-ydhn": { + "oil": 0.37, + "iron": 0.36, + "food": 0.47, + "industry": 0.37 + }, + "al-minya-mjfl": { + "oil": 0.7, + "iron": 0.54, + "food": 0.7, + "industry": 0.49 + }, + "al-muthannia-pffh": { + "oil": 0.37, + "iron": 0.47, + "food": 0.58, + "industry": 0.77 + }, + "al-quassim-imqj": { + "oil": 0.96, + "iron": 1, + "food": 0.97, + "industry": 1 + }, + "al-qubbah-wlez": { + "oil": 0.69, + "iron": 0.38, + "food": 0.53, + "industry": 1 + }, + "al-wadi-at-jadid-spvg": { + "oil": 0.27, + "iron": 0.3, + "food": 0.49, + "industry": 1 + }, + "al-wusta-mdok": { + "oil": 0.86, + "iron": 0.15, + "food": 0.61, + "industry": 0.7 + }, + "alabama-uqeu": { + "oil": 0.91, + "iron": 0.27, + "food": 0.84, + "industry": 0.61 + }, + "alagoas-ivzd": { + "oil": 0.5, + "iron": 0.32, + "food": 0.89, + "industry": 0.31 + }, + "alajuela-vwmk": { + "oil": 0.27, + "iron": 0.43, + "food": 0.46, + "industry": 0.46 + }, + "alaotra-mangoro-lper": { + "oil": 0.94, + "iron": 0.09, + "food": 0.96, + "industry": 0.68 + }, + "alaska-qfen": { + "oil": 0.65, + "iron": 0.11, + "food": 0.26, + "industry": 0.22 + }, + "alba-kbti": { + "oil": 1, + "iron": 0.34, + "food": 0.69, + "industry": 1 + }, + "albacete-attf": { + "oil": 0.96, + "iron": 0.23, + "food": 0.45, + "industry": 0.08 + }, + "alberta-zopq": { + "oil": 1, + "iron": 0.13, + "food": 0.85, + "industry": 0.29 + }, + "aleppo-cqlh": { + "oil": 0.7, + "iron": 0.08, + "food": 0.95, + "industry": 0.53 + }, + "alessandria-shfc": { + "oil": 0.58, + "iron": 1, + "food": 0.73, + "industry": 0.74 + }, + "alibori-smbm": { + "oil": 0.06, + "iron": 0.85, + "food": 1, + "industry": 1 + }, + "allier-butv": { + "oil": 0.18, + "iron": 0.41, + "food": 0.93, + "industry": 0.54 + }, + "almaty-waxb": { + "oil": 0.99, + "iron": 0.74, + "food": 0.27, + "industry": 0.01 + }, + "alpes-de-haute-provence-svtw": { + "oil": 0.69, + "iron": 0.67, + "food": 0.89, + "industry": 0.94 + }, + "alta-verapaz-myed": { + "oil": 0.24, + "iron": 0.06, + "food": 0.93, + "industry": 0.23 + }, + "altay-mfuq": { + "oil": 0.32, + "iron": 0.73, + "food": 0.58, + "industry": 0.12 + }, + "alto-paraguay-ezmh": { + "oil": 0.82, + "iron": 0.43, + "food": 0.68, + "industry": 0.19 + }, + "alto-parana-mimn": { + "oil": 0.21, + "iron": 0.01, + "food": 0.18, + "industry": 0.21 + }, + "amambay-kemk": { + "oil": 0.17, + "iron": 0.44, + "food": 0.79, + "industry": 0.94 + }, + "amapa-gozp": { + "oil": 0.73, + "iron": 1, + "food": 0.59, + "industry": 0.5 + }, + "amazonas-isdt": { + "oil": 0.43, + "iron": 0.4, + "food": 0.81, + "industry": 0.59 + }, + "amazonas-nthu": { + "oil": 0.32, + "iron": 0.39, + "food": 0.07, + "industry": 0.5 + }, + "amazonas-qfqs": { + "oil": 0.03, + "iron": 1, + "food": 0.66, + "industry": 0.01 + }, + "amazonas-qtzc": { + "oil": 0.76, + "iron": 0.17, + "food": 0.11, + "industry": 1 + }, + "ambeno-kpna": { + "oil": 0.33, + "iron": 0.12, + "food": 0.86, + "industry": 0.94 + }, + "amhara-kylq": { + "oil": 0.49, + "iron": 0.78, + "food": 0.94, + "industry": 0.58 + }, + "amman-avrc": { + "oil": 0.27, + "iron": 0.2, + "food": 0.58, + "industry": 0.94 + }, + "amoron-i-mania-ulvj": { + "oil": 0.23, + "iron": 1, + "food": 0.29, + "industry": 0.54 + }, + "ampara-oqcc": { + "oil": 0.47, + "iron": 0.07, + "food": 0.42, + "industry": 0.93 + }, + "amur-clbp": { + "oil": 0.26, + "iron": 0.56, + "food": 0.16, + "industry": 0.61 + }, + "amuria-izaz": { + "oil": 0.37, + "iron": 0.83, + "food": 0.48, + "industry": 1 + }, + "amuru-fprn": { + "oil": 0.41, + "iron": 0.15, + "food": 0.89, + "industry": 0.13 + }, + "an-najaf-buiy": { + "oil": 0.99, + "iron": 0.25, + "food": 0.42, + "industry": 0.86 + }, + "an-nuqat-al-khams-ehkx": { + "oil": 0.97, + "iron": 0.86, + "food": 0.71, + "industry": 0.41 + }, + "analamanga-szdu": { + "oil": 0.08, + "iron": 0.42, + "food": 0.19, + "industry": 0.87 + }, + "analanjirofo-hgdp": { + "oil": 0.36, + "iron": 0.04, + "food": 0.74, + "industry": 0.91 + }, + "anatoliki-makedonia-kai-thraki-abyd": { + "oil": 0.86, + "iron": 0.78, + "food": 0.79, + "industry": 0.67 + }, + "ancash-mtdg": { + "oil": 1, + "iron": 1, + "food": 0.08, + "industry": 0.33 + }, + "andaman-and-nicobar-stzm": { + "oil": 1, + "iron": 0.27, + "food": 0.56, + "industry": 0.31 + }, + "andhra-pradesh-amam": { + "oil": 0.99, + "iron": 0.53, + "food": 0.95, + "industry": 0.55 + }, + "androy-wzfq": { + "oil": 0.1, + "iron": 0.73, + "food": 0.83, + "industry": 1 + }, + "anhui-sanz": { + "oil": 0.99, + "iron": 0.16, + "food": 0.76, + "industry": 0.34 + }, + "ankara-oyhp": { + "oil": 0.17, + "iron": 0.22, + "food": 0.22, + "industry": 0.31 + }, + "annobon-eedl": { + "oil": 0.84, + "iron": 0.89, + "food": 0.6, + "industry": 0.61 + }, + "anosy-jadv": { + "oil": 0.1, + "iron": 0.75, + "food": 0.33, + "industry": 0.91 + }, + "antalya-iahq": { + "oil": 0.17, + "iron": 0.29, + "food": 0.74, + "industry": 0.44 + }, + "antarctica-ccbf": { + "oil": 0.43, + "iron": 0.31, + "food": 0.67, + "industry": 0.89 + }, + "antarctica-mvxe": { + "oil": 0.36, + "iron": 0.28, + "food": 0.87, + "industry": 0.31 + }, + "antioquia-kqan": { + "oil": 0.05, + "iron": 0.64, + "food": 0.6, + "industry": 0.69 + }, + "antipodes-islands-ynit": { + "oil": 0.06, + "iron": 0.88, + "food": 0.02, + "industry": 0.87 + }, + "antofagasta-czps": { + "oil": 0.09, + "iron": 0.05, + "food": 0.93, + "industry": 0.15 + }, + "anuradhapura-jzhh": { + "oil": 0.87, + "iron": 1, + "food": 0.87, + "industry": 1 + }, + "anzoategui-mrqa": { + "oil": 0.33, + "iron": 0.2, + "food": 0.28, + "industry": 0.23 + }, + "aoste-ymff": { + "oil": 0.27, + "iron": 0.65, + "food": 1, + "industry": 0.67 + }, + "apure-gtqb": { + "oil": 0.92, + "iron": 0.84, + "food": 0.24, + "industry": 0.9 + }, + "apurimac-aghq": { + "oil": 0.38, + "iron": 0.99, + "food": 0.76, + "industry": 0.87 + }, + "aqmola-etpx": { + "oil": 0.45, + "iron": 0.53, + "food": 0.89, + "industry": 0.85 + }, + "aqtobe-sgpw": { + "oil": 0.24, + "iron": 0.12, + "food": 0.24, + "industry": 0.62 + }, + "ar-raqqah-lhjy": { + "oil": 0.22, + "iron": 0.74, + "food": 0.19, + "industry": 0.79 + }, + "ar-rayyan-ynlo": { + "oil": 1, + "iron": 1, + "food": 0.59, + "industry": 0.22 + }, + "ar-riyad-gsqn": { + "oil": 0.34, + "iron": 0.8, + "food": 0.66, + "industry": 0.58 + }, + "arauca-yxsw": { + "oil": 0.26, + "iron": 0.1, + "food": 1, + "industry": 0.23 + }, + "arbil-sbqc": { + "oil": 0.46, + "iron": 0.37, + "food": 0.28, + "industry": 0.47 + }, + "archipel-des-crozet-oypb": { + "oil": 0.26, + "iron": 0.16, + "food": 0.3, + "industry": 0.26 + }, + "archipel-des-kerguelen-fnmd": { + "oil": 0.48, + "iron": 0.53, + "food": 1, + "industry": 0.17 + }, + "ardebil-aain": { + "oil": 0.96, + "iron": 0.59, + "food": 0.6, + "industry": 0.2 + }, + "ardeche-zatz": { + "oil": 0.5, + "iron": 0.14, + "food": 0.73, + "industry": 0.04 + }, + "arequipa-avbe": { + "oil": 0.75, + "iron": 0.75, + "food": 0.77, + "industry": 0.64 + }, + "arges-hxtf": { + "oil": 0, + "iron": 0.17, + "food": 0.84, + "industry": 0.33 + }, + "arhangay-efvw": { + "oil": 0.56, + "iron": 0.82, + "food": 0.79, + "industry": 0.54 + }, + "arica-y-parinacota-mbpk": { + "oil": 0.78, + "iron": 0.73, + "food": 0.57, + "industry": 0.85 + }, + "arizona-igee": { + "oil": 0.7, + "iron": 1, + "food": 0.39, + "industry": 0.45 + }, + "arkansas-itew": { + "oil": 0.96, + "iron": 0.53, + "food": 0.99, + "industry": 1 + }, + "arkhangel-sk-lhbk": { + "oil": 0.49, + "iron": 0.52, + "food": 0.98, + "industry": 0.82 + }, + "artigas-stkw": { + "oil": 1, + "iron": 1, + "food": 0.09, + "industry": 0 + }, + "artvin-aohz": { + "oil": 0.42, + "iron": 0.87, + "food": 0.54, + "industry": 0.08 + }, + "arunachal-pradesh-mpao": { + "oil": 0.45, + "iron": 0.77, + "food": 0.35, + "industry": 0.39 + }, + "arusha-ssrk": { + "oil": 0.42, + "iron": 0.03, + "food": 0.28, + "industry": 0.97 + }, + "as-sulaymaniyah-fimw": { + "oil": 0.78, + "iron": 0.97, + "food": 0.62, + "industry": 0.08 + }, + "as-suwayda-jzmr": { + "oil": 0.68, + "iron": 0.81, + "food": 0.45, + "industry": 0.38 + }, + "ash-sharqiyah-north-qdza": { + "oil": 0.32, + "iron": 1, + "food": 0.84, + "industry": 0 + }, + "ash-sharqiyah-qlqi": { + "oil": 0.3, + "iron": 0.47, + "food": 0.09, + "industry": 0.91 + }, + "ash-sharqiyah-south-gkzv": { + "oil": 0.71, + "iron": 0.6, + "food": 0.36, + "industry": 0.75 + }, + "ash-sharqiyah-wcnm": { + "oil": 0.35, + "iron": 1, + "food": 0.64, + "industry": 0.69 + }, + "ash-shati-qbtm": { + "oil": 0.37, + "iron": 1, + "food": 0.19, + "industry": 1 + }, + "ashanti-abux": { + "oil": 0.55, + "iron": 0.39, + "food": 0.32, + "industry": 0.09 + }, + "asir-yfso": { + "oil": 0.01, + "iron": 0.03, + "food": 0.18, + "industry": 0.37 + }, + "assaba-fzfa": { + "oil": 0.57, + "iron": 0.86, + "food": 0.49, + "industry": 0.25 + }, + "assam-dqap": { + "oil": 0.52, + "iron": 0.15, + "food": 1, + "industry": 0.49 + }, + "astrakhan-anec": { + "oil": 0.79, + "iron": 0.54, + "food": 0.17, + "industry": 0.35 + }, + "asturias-usbk": { + "oil": 0.61, + "iron": 0.33, + "food": 0.57, + "industry": 0.47 + }, + "aswan-sxuz": { + "oil": 0.27, + "iron": 0.95, + "food": 0.36, + "industry": 0.8 + }, + "at-ta-mim-xbob": { + "oil": 0.6, + "iron": 0.92, + "food": 0.38, + "industry": 0.54 + }, + "atacama-khpo": { + "oil": 0.13, + "iron": 0.38, + "food": 0.42, + "industry": 0.18 + }, + "atakora-oobn": { + "oil": 0.14, + "iron": 0.23, + "food": 0.79, + "industry": 0.9 + }, + "atlantico-norte-ieag": { + "oil": 0.12, + "iron": 0.73, + "food": 0, + "industry": 1 + }, + "atlantico-sur-ylal": { + "oil": 0.24, + "iron": 0.35, + "food": 0.19, + "industry": 0.44 + }, + "atsimo-andrefana-qbfr": { + "oil": 0.22, + "iron": 0.5, + "food": 0.8, + "industry": 0.68 + }, + "atsimo-atsinanana-cjvi": { + "oil": 0.19, + "iron": 0.44, + "food": 1, + "industry": 0.85 + }, + "atsinanana-uoeq": { + "oil": 0.97, + "iron": 0.35, + "food": 0.69, + "industry": 0.71 + }, + "attapu-cxyj": { + "oil": 0.12, + "iron": 0.24, + "food": 1, + "industry": 0.9 + }, + "atyrau-ixli": { + "oil": 0.14, + "iron": 0.62, + "food": 0.16, + "industry": 0.32 + }, + "auckland-islands-ujmt": { + "oil": 0.03, + "iron": 0.89, + "food": 0.96, + "industry": 0.75 + }, + "aude-pmva": { + "oil": 0.29, + "iron": 0.56, + "food": 0.48, + "industry": 0.53 + }, + "aust-agder-ufyy": { + "oil": 0.71, + "iron": 0.31, + "food": 0.32, + "industry": 0.44 + }, + "austurland-cdfj": { + "oil": 0.38, + "iron": 0.24, + "food": 0.19, + "industry": 0.56 + }, + "aveyron-kovb": { + "oil": 0.89, + "iron": 0.11, + "food": 1, + "industry": 1 + }, + "ayacucho-vhko": { + "oil": 0.15, + "iron": 0.06, + "food": 0.91, + "industry": 1 + }, + "ayeyarwady-mhrr": { + "oil": 0.96, + "iron": 1, + "food": 0.55, + "industry": 0.14 + }, + "azad-kashmir-ajpr": { + "oil": 0.29, + "iron": 0.7, + "food": 0.99, + "industry": 0.88 + }, + "azores-ayly": { + "oil": 0.6, + "iron": 0.43, + "food": 0.13, + "industry": 0.59 + }, + "azuay-kruk": { + "oil": 0.86, + "iron": 0.27, + "food": 0.42, + "industry": 0.93 + }, + "babil-emst": { + "oil": 0.04, + "iron": 0.49, + "food": 0.19, + "industry": 0.52 + }, + "bacau-zdvy": { + "oil": 0.94, + "iron": 0.63, + "food": 1, + "industry": 0.32 + }, + "bacs-kiskun-udpx": { + "oil": 0.42, + "iron": 0.43, + "food": 0.46, + "industry": 1 + }, + "badajoz-ciwt": { + "oil": 0.04, + "iron": 0.23, + "food": 0.57, + "industry": 0.8 + }, + "badakhshan-qjrt": { + "oil": 0.92, + "iron": 0.42, + "food": 0.45, + "industry": 0.17 + }, + "baden-wurttemberg-oyje": { + "oil": 0.35, + "iron": 0.87, + "food": 0.17, + "industry": 0.89 + }, + "badghis-werz": { + "oil": 0.28, + "iron": 0.17, + "food": 1, + "industry": 1 + }, + "bafata-krfg": { + "oil": 0.01, + "iron": 0.03, + "food": 0.13, + "industry": 0.22 + }, + "baghlan-wqdr": { + "oil": 0.84, + "iron": 0.68, + "food": 0.83, + "industry": 0.83 + }, + "bagmati-ungl": { + "oil": 0.64, + "iron": 0.69, + "food": 0.39, + "industry": 0.32 + }, + "bago-uzrm": { + "oil": 0.48, + "iron": 0.28, + "food": 0.39, + "industry": 0.16 + }, + "bahia-gncm": { + "oil": 0.64, + "iron": 0.91, + "food": 0.49, + "industry": 0.39 + }, + "baja-california-rkil": { + "oil": 0.99, + "iron": 0.25, + "food": 0.02, + "industry": 0.46 + }, + "baja-california-sur-uoie": { + "oil": 0.03, + "iron": 0.69, + "food": 0.24, + "industry": 0.54 + }, + "baja-verapaz-ongg": { + "oil": 0.66, + "iron": 1, + "food": 1, + "industry": 0.87 + }, + "bakool-grdf": { + "oil": 0.73, + "iron": 1, + "food": 0.16, + "industry": 0.77 + }, + "baleares-ayfx": { + "oil": 0.15, + "iron": 0.97, + "food": 0.35, + "industry": 0.38 + }, + "balikesir-exjy": { + "oil": 0.34, + "iron": 0.41, + "food": 0.37, + "industry": 0.83 + }, + "balkan-edcn": { + "oil": 0.79, + "iron": 0.62, + "food": 0.72, + "industry": 0.92 + }, + "balkh-ckka": { + "oil": 0.83, + "iron": 0.37, + "food": 0.77, + "industry": 0.14 + }, + "baluchistan-ihjh": { + "oil": 0.87, + "iron": 1, + "food": 0.68, + "industry": 0.84 + }, + "bamingui-bangoran-ilrg": { + "oil": 0.65, + "iron": 0.57, + "food": 0.73, + "industry": 0.52 + }, + "bamyan-mjkz": { + "oil": 0.61, + "iron": 0.72, + "food": 0.76, + "industry": 0.52 + }, + "bandundu-gzcq": { + "oil": 0.23, + "iron": 1, + "food": 0.91, + "industry": 0.26 + }, + "bangka-belitung-ixwo": { + "oil": 0.34, + "iron": 0.69, + "food": 0.88, + "industry": 0.57 + }, + "banja-luka-qguu": { + "oil": 1, + "iron": 0.54, + "food": 0.17, + "industry": 0.49 + }, + "banskobystricky-iono": { + "oil": 0.94, + "iron": 0.9, + "food": 0.38, + "industry": 0.66 + }, + "banten-stwc": { + "oil": 0.58, + "iron": 1, + "food": 0.73, + "industry": 0.74 + }, + "barcelona-iybx": { + "oil": 0.84, + "iron": 0.32, + "food": 1, + "industry": 0.2 + }, + "barh-el-gazel-nhes": { + "oil": 1, + "iron": 0.91, + "food": 1, + "industry": 0.97 + }, + "bari-gtie": { + "oil": 0.81, + "iron": 0.82, + "food": 0.87, + "industry": 0.04 + }, + "bari-sedg": { + "oil": 0.21, + "iron": 0.22, + "food": 0.82, + "industry": 0.12 + }, + "barima-waini-wifs": { + "oil": 0.08, + "iron": 0.45, + "food": 0.31, + "industry": 0.37 + }, + "barinas-uwqd": { + "oil": 1, + "iron": 0.5, + "food": 0.74, + "industry": 0.14 + }, + "bas-congo-yhcf": { + "oil": 0.39, + "iron": 0.6, + "food": 0.28, + "industry": 0.71 + }, + "bas-sassandra-muqc": { + "oil": 0.19, + "iron": 0.16, + "food": 0.26, + "industry": 0.21 + }, + "bashkortostan-uovk": { + "oil": 0.99, + "iron": 0.18, + "food": 0.27, + "industry": 1 + }, + "basse-kotto-earz": { + "oil": 0.1, + "iron": 0.32, + "food": 1, + "industry": 0.78 + }, + "batanes-orcp": { + "oil": 0.8, + "iron": 0.75, + "food": 1, + "industry": 0.63 + }, + "batdambang-jett": { + "oil": 0.29, + "iron": 0.18, + "food": 0.53, + "industry": 0.83 + }, + "batha-dyem": { + "oil": 0.72, + "iron": 0.54, + "food": 0.64, + "industry": 0.11 + }, + "batken-cbll": { + "oil": 0.71, + "iron": 0.52, + "food": 1, + "industry": 0.55 + }, + "batna-enwu": { + "oil": 0.41, + "iron": 0.13, + "food": 0.99, + "industry": 0.1 + }, + "bauchi-spdb": { + "oil": 0.04, + "iron": 1, + "food": 0.1, + "industry": 0.67 + }, + "bay-of-plenty-wlsa": { + "oil": 1, + "iron": 0.42, + "food": 0.05, + "industry": 0.65 + }, + "bay-uvdr": { + "oil": 0.27, + "iron": 1, + "food": 0, + "industry": 0.45 + }, + "bayan-olgiy-ucvu": { + "oil": 0.65, + "iron": 0.53, + "food": 0.28, + "industry": 0.41 + }, + "bayanhongor-udsh": { + "oil": 0.8, + "iron": 0.99, + "food": 1, + "industry": 0.27 + }, + "bayern-aiju": { + "oil": 0.96, + "iron": 0.7, + "food": 0.7, + "industry": 0.72 + }, + "bazega-ufdx": { + "oil": 0.07, + "iron": 0.82, + "food": 0.57, + "industry": 0.08 + }, + "bechar-kfwp": { + "oil": 0.16, + "iron": 0.21, + "food": 0.98, + "industry": 0.43 + }, + "beijing-qsqi": { + "oil": 0.66, + "iron": 0.12, + "food": 0.08, + "industry": 0.87 + }, + "beja-yaie": { + "oil": 0.64, + "iron": 0.79, + "food": 0.94, + "industry": 0.02 + }, + "beja-ykgw": { + "oil": 0.63, + "iron": 0.95, + "food": 0.5, + "industry": 0.66 + }, + "bekes-itph": { + "oil": 0.21, + "iron": 0.52, + "food": 0.76, + "industry": 0.39 + }, + "belait-asmw": { + "oil": 0.01, + "iron": 0.27, + "food": 0.39, + "industry": 1 + }, + "belgorod-wxjk": { + "oil": 0.71, + "iron": 0.08, + "food": 0.43, + "industry": 1 + }, + "belluno-iojp": { + "oil": 0.39, + "iron": 0.81, + "food": 0.35, + "industry": 0.5 + }, + "bengkulu-qwwn": { + "oil": 0.53, + "iron": 0.55, + "food": 0.55, + "industry": 0.57 + }, + "bengo-awxb": { + "oil": 0.66, + "iron": 0.05, + "food": 0.29, + "industry": 0.05 + }, + "benguela-ifxx": { + "oil": 0.69, + "iron": 0.08, + "food": 0.62, + "industry": 0.73 + }, + "benshangul-gumaz-iznr": { + "oil": 0.93, + "iron": 0.14, + "food": 0.53, + "industry": 0.81 + }, + "benue-uwdf": { + "oil": 0.35, + "iron": 0.91, + "food": 0.02, + "industry": 0.8 + }, + "beqaa-ryfc": { + "oil": 0.05, + "iron": 0, + "food": 0.04, + "industry": 0.5 + }, + "bern-pmiz": { + "oil": 0.86, + "iron": 0.28, + "food": 0.04, + "industry": 0.8 + }, + "berry-islands-wejq": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 0.39 + }, + "betsiboka-upag": { + "oil": 0.8, + "iron": 0.02, + "food": 0.9, + "industry": 1 + }, + "beyla-vyfv": { + "oil": 0.21, + "iron": 0.11, + "food": 1, + "industry": 0.95 + }, + "bheri-czgc": { + "oil": 0.33, + "iron": 0.76, + "food": 0.3, + "industry": 0.86 + }, + "bhojpur-uxpy": { + "oil": 0.94, + "iron": 0.02, + "food": 0.44, + "industry": 1 + }, + "bie-usov": { + "oil": 0.75, + "iron": 0.53, + "food": 0.22, + "industry": 0.98 + }, + "bihar-cbcp": { + "oil": 0.38, + "iron": 0.77, + "food": 0.17, + "industry": 0.09 + }, + "bilecik-wyjz": { + "oil": 0.92, + "iron": 0.29, + "food": 0.45, + "industry": 0.23 + }, + "bimini-sdjg": { + "oil": 0.76, + "iron": 0.82, + "food": 0.41, + "industry": 0.33 + }, + "binh-phuoc-qysb": { + "oil": 0.36, + "iron": 0.23, + "food": 0.97, + "industry": 0.74 + }, + "bio-bio-kfrw": { + "oil": 0.18, + "iron": 0.65, + "food": 0.8, + "industry": 0.04 + }, + "bioko-sur-yvgu": { + "oil": 0.97, + "iron": 0.19, + "food": 0.7, + "industry": 0.18 + }, + "biskra-oqww": { + "oil": 0.23, + "iron": 0.89, + "food": 0.92, + "industry": 0.79 + }, + "bitlis-gbjb": { + "oil": 0.98, + "iron": 0.3, + "food": 0.83, + "industry": 1 + }, + "blue-nile-conz": { + "oil": 0.72, + "iron": 1, + "food": 0.19, + "industry": 0.49 + }, + "boeny-fmdt": { + "oil": 0.5, + "iron": 0.21, + "food": 0.16, + "industry": 0.76 + }, + "boke-jifl": { + "oil": 0.47, + "iron": 0.24, + "food": 0.25, + "industry": 0.95 + }, + "bolikhamxai-csag": { + "oil": 0.28, + "iron": 0.98, + "food": 0.74, + "industry": 0.26 + }, + "bolivar-oyqe": { + "oil": 0.25, + "iron": 0.57, + "food": 0.66, + "industry": 0.54 + }, + "bolivar-shkq": { + "oil": 0.9, + "iron": 1, + "food": 1, + "industry": 0.77 + }, + "bologna-otjs": { + "oil": 0.32, + "iron": 0.97, + "food": 1, + "industry": 0.55 + }, + "bolu-cdjc": { + "oil": 0.89, + "iron": 0.75, + "food": 0.83, + "industry": 0.05 + }, + "bonaire-makp": { + "oil": 0.04, + "iron": 0.31, + "food": 0.45, + "industry": 0.48 + }, + "bongolava-irjg": { + "oil": 0.45, + "iron": 0.43, + "food": 0.53, + "industry": 0.13 + }, + "boqueron-uume": { + "oil": 1, + "iron": 0.89, + "food": 0.36, + "industry": 0.84 + }, + "borgou-yqft": { + "oil": 0.56, + "iron": 0.09, + "food": 0.47, + "industry": 0.13 + }, + "borkou-nuea": { + "oil": 0.38, + "iron": 0.33, + "food": 0.91, + "industry": 0.44 + }, + "borno-emdz": { + "oil": 0.96, + "iron": 0.89, + "food": 0.11, + "industry": 0.76 + }, + "bouenza-elwk": { + "oil": 0.97, + "iron": 0.22, + "food": 0.8, + "industry": 0.72 + }, + "boulgou-oyva": { + "oil": 0.4, + "iron": 0.1, + "food": 0.45, + "industry": 0.62 + }, + "bouvet-island-vssk": { + "oil": 0.11, + "iron": 0.58, + "food": 0.45, + "industry": 0.32 + }, + "boyaca-uekx": { + "oil": 1, + "iron": 0.43, + "food": 0.28, + "industry": 0.86 + }, + "bozen-ukjd": { + "oil": 0.47, + "iron": 0.92, + "food": 0.41, + "industry": 0.87 + }, + "brakna-rcfc": { + "oil": 0.81, + "iron": 0.84, + "food": 0.29, + "industry": 0.34 + }, + "brandenburg-yrjj": { + "oil": 0.77, + "iron": 0.53, + "food": 0.23, + "industry": 0.77 + }, + "branicevski-nitf": { + "oil": 0.84, + "iron": 0.99, + "food": 0.42, + "industry": 0.66 + }, + "brescia-mzjw": { + "oil": 0.01, + "iron": 0, + "food": 0.81, + "industry": 1 + }, + "brest-uhpa": { + "oil": 0.69, + "iron": 0.74, + "food": 1, + "industry": 0.79 + }, + "british-columbia-vmsh": { + "oil": 1, + "iron": 0.38, + "food": 0.42, + "industry": 1 + }, + "brong-ahafo-qqwr": { + "oil": 0.5, + "iron": 0.99, + "food": 0.46, + "industry": 0.38 + }, + "bryansk-hxom": { + "oil": 1, + "iron": 0.83, + "food": 0.69, + "industry": 0.41 + }, + "buenos-aires-mwnv": { + "oil": 0.69, + "iron": 0.1, + "food": 0.81, + "industry": 0.31 + }, + "bukhoro-udcy": { + "oil": 0.86, + "iron": 1, + "food": 0.05, + "industry": 0.89 + }, + "bukidnon-faet": { + "oil": 0.24, + "iron": 0.26, + "food": 0.26, + "industry": 0.98 + }, + "bulgan-czsv": { + "oil": 0.21, + "iron": 0.01, + "food": 0.44, + "industry": 0.13 + }, + "burgas-nowy": { + "oil": 0.79, + "iron": 0.11, + "food": 0.55, + "industry": 1 + }, + "burgos-asxn": { + "oil": 0.68, + "iron": 0.77, + "food": 0.41, + "industry": 0.04 + }, + "buri-ram-ghiq": { + "oil": 0.05, + "iron": 0.28, + "food": 1, + "industry": 0.16 + }, + "bursa-ogje": { + "oil": 1, + "iron": 0.35, + "food": 0.69, + "industry": 0.64 + }, + "bururi-uaba": { + "oil": 0.95, + "iron": 0.2, + "food": 0.13, + "industry": 0.17 + }, + "buryat-wvvy": { + "oil": 0.41, + "iron": 0.4, + "food": 0.57, + "industry": 0.92 + }, + "bushehr-ksii": { + "oil": 0.29, + "iron": 0.86, + "food": 0.97, + "industry": 1 + }, + "buskerud-onyd": { + "oil": 0.43, + "iron": 1, + "food": 0.52, + "industry": 0.93 + }, + "buvuma-gikj": { + "oil": 0.56, + "iron": 0.06, + "food": 0.93, + "industry": 0.44 + }, + "buzau-ipvp": { + "oil": 0.32, + "iron": 0.34, + "food": 0.93, + "industry": 0.99 + }, + "caaguazu-xlmh": { + "oil": 0.71, + "iron": 0.4, + "food": 0.27, + "industry": 0.93 + }, + "caazapa-snmi": { + "oil": 0.07, + "iron": 0.4, + "food": 1, + "industry": 0.1 + }, + "cabo-delgado-mdft": { + "oil": 1, + "iron": 0.08, + "food": 0.85, + "industry": 0.44 + }, + "caceres-kdze": { + "oil": 1, + "iron": 0.38, + "food": 0.92, + "industry": 0.33 + }, + "cadiz-aazc": { + "oil": 0.85, + "iron": 0.96, + "food": 0.62, + "industry": 0.84 + }, + "cagayan-sezc": { + "oil": 0.17, + "iron": 1, + "food": 0.03, + "industry": 0.4 + }, + "cajamarca-mjjy": { + "oil": 1, + "iron": 0.25, + "food": 1, + "industry": 0.49 + }, + "caldas-wkha": { + "oil": 0.64, + "iron": 0.66, + "food": 0.57, + "industry": 1 + }, + "california-kikh": { + "oil": 0.31, + "iron": 0.1, + "food": 0.82, + "industry": 0.97 + }, + "camaguey-ewbu": { + "oil": 0.58, + "iron": 0.76, + "food": 0.36, + "industry": 1 + }, + "camarines-sur-ulzq": { + "oil": 0.27, + "iron": 0.2, + "food": 0.16, + "industry": 0.61 + }, + "cambridgeshire-fwds": { + "oil": 0.79, + "iron": 0.46, + "food": 0.7, + "industry": 0.46 + }, + "campbell-islands-ywks": { + "oil": 0.63, + "iron": 0.84, + "food": 0.35, + "industry": 0.48 + }, + "campeche-qfna": { + "oil": 0.04, + "iron": 0.12, + "food": 0.3, + "industry": 0.03 + }, + "campobasso-wmlo": { + "oil": 0.74, + "iron": 0.71, + "food": 0.88, + "industry": 0.44 + }, + "canindeyu-ocmj": { + "oil": 0.88, + "iron": 0.31, + "food": 0.06, + "industry": 0.97 + }, + "cantal-rgvw": { + "oil": 0.75, + "iron": 0.91, + "food": 0.45, + "industry": 1 + }, + "canterbury-kxye": { + "oil": 0.3, + "iron": 0.06, + "food": 0.41, + "industry": 1 + }, + "caprivi-yapw": { + "oil": 0.32, + "iron": 0.48, + "food": 0.13, + "industry": 0.18 + }, + "caqueta-qfhx": { + "oil": 0.5, + "iron": 0.01, + "food": 0.17, + "industry": 0.75 + }, + "casanare-aihz": { + "oil": 0.33, + "iron": 0.24, + "food": 0.63, + "industry": 0.57 + }, + "castelo-branco-gcgr": { + "oil": 0.72, + "iron": 0.34, + "food": 0.75, + "industry": 0.92 + }, + "cat-island-kqms": { + "oil": 0.35, + "iron": 0.8, + "food": 0.44, + "industry": 0.54 + }, + "catamarca-ekne": { + "oil": 0.09, + "iron": 1, + "food": 0.79, + "industry": 0.74 + }, + "catania-kqla": { + "oil": 0.21, + "iron": 0.33, + "food": 0.93, + "industry": 0.42 + }, + "cauca-szht": { + "oil": 0.85, + "iron": 0.74, + "food": 1, + "industry": 0.28 + }, + "cavally-qqst": { + "oil": 0.6, + "iron": 0.67, + "food": 0.04, + "industry": 0.63 + }, + "cayo-ejvk": { + "oil": 0.05, + "iron": 0.94, + "food": 0.81, + "industry": 0.8 + }, + "ceara-wceu": { + "oil": 0, + "iron": 0.65, + "food": 1, + "industry": 0.7 + }, + "central-cczg": { + "oil": 0.48, + "iron": 0.26, + "food": 0.12, + "industry": 0.46 + }, + "central-darfur-wrpe": { + "oil": 0.52, + "iron": 1, + "food": 1, + "industry": 0.7 + }, + "central-equatoria-sogr": { + "oil": 0.33, + "iron": 0.55, + "food": 0.48, + "industry": 0.52 + }, + "central-finland-cpkp": { + "oil": 0.36, + "iron": 0.51, + "food": 0.52, + "industry": 0.88 + }, + "central-river-qqfp": { + "oil": 0.72, + "iron": 0.73, + "food": 0.59, + "industry": 0.98 + }, + "central-sqzo": { + "oil": 0.48, + "iron": 0.24, + "food": 0.58, + "industry": 0.41 + }, + "central-svtv": { + "oil": 0.48, + "iron": 0.44, + "food": 0.45, + "industry": 0.68 + }, + "central-ypdw": { + "oil": 0.23, + "iron": 0.06, + "food": 0.3, + "industry": 0.39 + }, + "centre-aexz": { + "oil": 0.96, + "iron": 0.55, + "food": 1, + "industry": 0.47 + }, + "centre-kurt": { + "oil": 1, + "iron": 0.78, + "food": 0.53, + "industry": 0.39 + }, + "centro-sur-gwiq": { + "oil": 0.24, + "iron": 0.01, + "food": 0.37, + "industry": 0.3 + }, + "cerro-largo-sjom": { + "oil": 0.07, + "iron": 0.04, + "food": 1, + "industry": 0.85 + }, + "cesar-qcua": { + "oil": 0.63, + "iron": 0.95, + "food": 0.5, + "industry": 0.66 + }, + "chachoengsao-uwfm": { + "oil": 0.1, + "iron": 0.5, + "food": 1, + "industry": 0.31 + }, + "chaco-yfnb": { + "oil": 1, + "iron": 0.09, + "food": 0.95, + "industry": 0.57 + }, + "chagang-do-erdw": { + "oil": 0.02, + "iron": 0.53, + "food": 0.64, + "industry": 0.83 + }, + "chahar-mahall-and-bakhtiari-uiis": { + "oil": 0.76, + "iron": 0.22, + "food": 1, + "industry": 0.6 + }, + "chaiyaphum-acin": { + "oil": 1, + "iron": 0.9, + "food": 0.19, + "industry": 0.65 + }, + "champasak-agcn": { + "oil": 0.29, + "iron": 0.2, + "food": 0.85, + "industry": 0.06 + }, + "chaouia-ouardigha-edem": { + "oil": 0.17, + "iron": 0.72, + "food": 0.92, + "industry": 0.06 + }, + "chardzhou-mzcb": { + "oil": 0.97, + "iron": 0.63, + "food": 0.63, + "industry": 0.44 + }, + "charente-maritime-djvy": { + "oil": 0.22, + "iron": 0.8, + "food": 0.8, + "industry": 0.96 + }, + "chari-baguirmi-aeay": { + "oil": 0.78, + "iron": 0.17, + "food": 0.19, + "industry": 0.34 + }, + "chatham-islands-territory-svse": { + "oil": 0.02, + "iron": 0.8, + "food": 0.3, + "industry": 0.22 + }, + "chechnya-qixv": { + "oil": 0.41, + "iron": 0.68, + "food": 0.16, + "industry": 0.16 + }, + "chelyabinsk-qnxc": { + "oil": 0.48, + "iron": 0.12, + "food": 0.88, + "industry": 0.65 + }, + "cher-yyvr": { + "oil": 0.08, + "iron": 0.86, + "food": 0.86, + "industry": 0.33 + }, + "cherkasy-wzvf": { + "oil": 0.66, + "iron": 0.8, + "food": 0.14, + "industry": 0.26 + }, + "chernihiv-cevi": { + "oil": 0.7, + "iron": 0.64, + "food": 0.39, + "industry": 0.32 + }, + "chhattisgarh-yiee": { + "oil": 0.98, + "iron": 0.91, + "food": 0.55, + "industry": 0.63 + }, + "chiang-mai-qstn": { + "oil": 0.64, + "iron": 0.48, + "food": 1, + "industry": 0.65 + }, + "chiang-rai-uqtm": { + "oil": 0.69, + "iron": 0.03, + "food": 0.54, + "industry": 1 + }, + "chiapas-izef": { + "oil": 0.41, + "iron": 1, + "food": 0.49, + "industry": 0.25 + }, + "chihuahua-imen": { + "oil": 0.21, + "iron": 0.3, + "food": 0.3, + "industry": 0.46 + }, + "chikwawa-ulnn": { + "oil": 0.97, + "iron": 0.18, + "food": 0.25, + "industry": 0.31 + }, + "chin-kltn": { + "oil": 0.27, + "iron": 0.53, + "food": 0.76, + "industry": 0.01 + }, + "chiriqui-mxiy": { + "oil": 0.28, + "iron": 0.06, + "food": 0.65, + "industry": 0.42 + }, + "chita-qxms": { + "oil": 0.73, + "iron": 0.03, + "food": 1, + "industry": 0.57 + }, + "chitipa-qnno": { + "oil": 0.36, + "iron": 0.66, + "food": 0.28, + "industry": 1 + }, + "chittagong-bxry": { + "oil": 0.46, + "iron": 0.5, + "food": 0.8, + "industry": 0.82 + }, + "choco-qaew": { + "oil": 0.65, + "iron": 0.12, + "food": 0.87, + "industry": 1 + }, + "chongqing-mcsc": { + "oil": 0.69, + "iron": 1, + "food": 0.85, + "industry": 0.01 + }, + "chontales-uefv": { + "oil": 0.19, + "iron": 0.34, + "food": 1, + "industry": 0.64 + }, + "chubut-apna": { + "oil": 0.44, + "iron": 0.34, + "food": 0.45, + "industry": 0.96 + }, + "chukchi-autonomous-okrug-mmxs": { + "oil": 0.63, + "iron": 0.74, + "food": 0.7, + "industry": 0.35 + }, + "chuquisaca-mztf": { + "oil": 0.31, + "iron": 0.08, + "food": 0.24, + "industry": 0.14 + }, + "chuvash-mhxl": { + "oil": 0.98, + "iron": 0.76, + "food": 0.21, + "industry": 0.03 + }, + "chuy-xdlm": { + "oil": 0.12, + "iron": 0.89, + "food": 1, + "industry": 0.68 + }, + "cimislia-acda": { + "oil": 0.44, + "iron": 0.48, + "food": 0.49, + "industry": 1 + }, + "ciudad-real-adzn": { + "oil": 0.88, + "iron": 0.61, + "food": 0.82, + "industry": 0.27 + }, + "clarendon-muxv": { + "oil": 0.08, + "iron": 0.02, + "food": 1, + "industry": 0.54 + }, + "cluj-cgyo": { + "oil": 0.75, + "iron": 0.98, + "food": 0.61, + "industry": 0.24 + }, + "coahuila-givi": { + "oil": 0.09, + "iron": 0.82, + "food": 0.72, + "industry": 0.94 + }, + "coast-kjrv": { + "oil": 0.08, + "iron": 0.31, + "food": 1, + "industry": 0.57 + }, + "cochabamba-oqtq": { + "oil": 0.54, + "iron": 0.16, + "food": 0.51, + "industry": 0.91 + }, + "cojedes-abqg": { + "oil": 0.75, + "iron": 0.34, + "food": 0.18, + "industry": 0.35 + }, + "collines-qzhd": { + "oil": 0.79, + "iron": 0.19, + "food": 0.26, + "industry": 0.77 + }, + "colombia-weor": { + "oil": 0.9, + "iron": 0.3, + "food": 0.28, + "industry": 0.17 + }, + "colorado-wfkf": { + "oil": 0.49, + "iron": 0.02, + "food": 0.01, + "industry": 0.18 + }, + "comayagua-gvxb": { + "oil": 0.28, + "iron": 0.96, + "food": 0.99, + "industry": 0.07 + }, + "concepcion-vrml": { + "oil": 0.58, + "iron": 0.86, + "food": 0.82, + "industry": 0.08 + }, + "connecticut-apkc": { + "oil": 0.74, + "iron": 0.22, + "food": 0.6, + "industry": 0.12 + }, + "constanta-owyy": { + "oil": 0.13, + "iron": 0.99, + "food": 1, + "industry": 0.83 + }, + "copperbelt-gftb": { + "oil": 0.17, + "iron": 0.22, + "food": 0.19, + "industry": 0.5 + }, + "coquimbo-qtuj": { + "oil": 0.47, + "iron": 0.53, + "food": 0.45, + "industry": 1 + }, + "cordoba-cgnl": { + "oil": 0.38, + "iron": 0.85, + "food": 0.46, + "industry": 0.57 + }, + "cordoba-mxza": { + "oil": 0.33, + "iron": 0.84, + "food": 0.48, + "industry": 0.11 + }, + "cordoba-srwy": { + "oil": 0.01, + "iron": 0.11, + "food": 0.68, + "industry": 0.16 + }, + "cork-qnps": { + "oil": 0.55, + "iron": 0.02, + "food": 0.05, + "industry": 1 + }, + "corrientes-ksnc": { + "oil": 0.72, + "iron": 0.89, + "food": 1, + "industry": 0.55 + }, + "corum-amjr": { + "oil": 0.28, + "iron": 0.82, + "food": 0.12, + "industry": 0.15 + }, + "cosenza-oolz": { + "oil": 0.62, + "iron": 0.22, + "food": 0.98, + "industry": 0.72 + }, + "cotabato-wzzy": { + "oil": 0.42, + "iron": 0.47, + "food": 0.64, + "industry": 0.25 + }, + "cote-d-or-zhyz": { + "oil": 0.39, + "iron": 0.48, + "food": 0.91, + "industry": 0.78 + }, + "cotes-d-armor-qiya": { + "oil": 0.94, + "iron": 0.74, + "food": 0.22, + "industry": 0.08 + }, + "creuse-lkyb": { + "oil": 0.49, + "iron": 0.41, + "food": 0.97, + "industry": 0.79 + }, + "crimea-qsnu": { + "oil": 0.56, + "iron": 0.09, + "food": 0.44, + "industry": 0.46 + }, + "cross-river-erfd": { + "oil": 0.7, + "iron": 0.38, + "food": 0.72, + "industry": 1 + }, + "cuando-cubango-sifc": { + "oil": 0.58, + "iron": 0.02, + "food": 0.91, + "industry": 0.88 + }, + "cuanza-norte-avuq": { + "oil": 0.61, + "iron": 0.84, + "food": 0.88, + "industry": 0.27 + }, + "cuanza-sul-uays": { + "oil": 0.55, + "iron": 0.26, + "food": 0.36, + "industry": 0.72 + }, + "cuenca-chzq": { + "oil": 1, + "iron": 0.15, + "food": 0.26, + "industry": 0.06 + }, + "cumbria-oohy": { + "oil": 0.87, + "iron": 1, + "food": 0.67, + "industry": 0.72 + }, + "cundinamarca-ieom": { + "oil": 0.6, + "iron": 0.4, + "food": 0.04, + "industry": 0.36 + }, + "cunene-etup": { + "oil": 0.34, + "iron": 1, + "food": 0.34, + "industry": 0.8 + }, + "cusco-ypen": { + "oil": 0.71, + "iron": 0.87, + "food": 0.18, + "industry": 0.62 + }, + "cuvette-ouest-crwo": { + "oil": 0.59, + "iron": 0.23, + "food": 0.58, + "industry": 0.61 + }, + "cuvette-wtpy": { + "oil": 0.74, + "iron": 0.46, + "food": 0.48, + "industry": 0.76 + }, + "dagestan-qfgq": { + "oil": 0.77, + "iron": 0.56, + "food": 0.57, + "industry": 0.73 + }, + "dakhlet-nouadhibou-cifl": { + "oil": 0.77, + "iron": 0.8, + "food": 0.47, + "industry": 0.01 + }, + "dalarna-cluu": { + "oil": 0.22, + "iron": 0.47, + "food": 0.01, + "industry": 0.76 + }, + "darien-iziz": { + "oil": 0.5, + "iron": 0.54, + "food": 0.71, + "industry": 0.82 + }, + "davao-oriental-sxtc": { + "oil": 0.53, + "iron": 0.34, + "food": 0.86, + "industry": 0.47 + }, + "dayr-az-zawr-nthe": { + "oil": 0.64, + "iron": 0.86, + "food": 0.9, + "industry": 0.34 + }, + "debub-rtxk": { + "oil": 0.48, + "iron": 0.23, + "food": 0.93, + "industry": 0.94 + }, + "debubawi-keyih-bahri-jrxo": { + "oil": 0.37, + "iron": 0.83, + "food": 0.87, + "industry": 0.13 + }, + "delta-amacuro-wdqr": { + "oil": 0.71, + "iron": 0.23, + "food": 0.34, + "industry": 0.11 + }, + "delta-qnoh": { + "oil": 0.95, + "iron": 0.7, + "food": 0.15, + "industry": 1 + }, + "denguele-ycsk": { + "oil": 0.52, + "iron": 0.63, + "food": 0.66, + "industry": 0.45 + }, + "denizli-spld": { + "oil": 0.92, + "iron": 1, + "food": 1, + "industry": 0.54 + }, + "devon-slaz": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 0.48 + }, + "dhaka-gvrx": { + "oil": 0.64, + "iron": 0.39, + "food": 0.43, + "industry": 0.38 + }, + "dhamar-utko": { + "oil": 0.46, + "iron": 0.18, + "food": 0.59, + "industry": 0.63 + }, + "dhi-qar-pmxm": { + "oil": 0.26, + "iron": 0.78, + "food": 0.2, + "industry": 0.22 + }, + "dhofar-gtht": { + "oil": 0.86, + "iron": 0.31, + "food": 0.54, + "industry": 0.62 + }, + "diana-oydk": { + "oil": 0.16, + "iron": 0.39, + "food": 0.33, + "industry": 0.4 + }, + "diekirch-kyaq": { + "oil": 0.88, + "iron": 0.73, + "food": 0.7, + "industry": 0.45 + }, + "diffa-akfc": { + "oil": 0.37, + "iron": 0.42, + "food": 0.17, + "industry": 0.53 + }, + "dikhil-zrvh": { + "oil": 0.84, + "iron": 1, + "food": 1, + "industry": 0.49 + }, + "dinguiraye-vqqn": { + "oil": 0.65, + "iron": 0.63, + "food": 1, + "industry": 0.78 + }, + "dix-huit-montagnes-gcqh": { + "oil": 0.38, + "iron": 0.07, + "food": 0.03, + "industry": 0.32 + }, + "diyala-pzxe": { + "oil": 0.07, + "iron": 0.61, + "food": 1, + "industry": 0.71 + }, + "diyarbakir-mrle": { + "oil": 0.88, + "iron": 0.99, + "food": 0.23, + "industry": 1 + }, + "djak-lak-qdho": { + "oil": 0.39, + "iron": 0.55, + "food": 0.61, + "industry": 0.95 + }, + "djelfa-uxzd": { + "oil": 0.49, + "iron": 0.24, + "food": 0.49, + "industry": 0.07 + }, + "djien-bien-uwxm": { + "oil": 0.52, + "iron": 0.51, + "food": 0.72, + "industry": 0.87 + }, + "dnipropetrovs-k-uszu": { + "oil": 1, + "iron": 0.51, + "food": 0.54, + "industry": 0.96 + }, + "dodoma-cvrm": { + "oil": 0.69, + "iron": 1, + "food": 1, + "industry": 0.02 + }, + "dolj-yaab": { + "oil": 0.23, + "iron": 0.55, + "food": 0.41, + "industry": 0.13 + }, + "donets-k-gvzw": { + "oil": 0.57, + "iron": 1, + "food": 0.48, + "industry": 0.43 + }, + "donga-geqd": { + "oil": 0.43, + "iron": 0.16, + "food": 0.32, + "industry": 0.5 + }, + "dornod-qpsp": { + "oil": 0.39, + "iron": 0.82, + "food": 0.68, + "industry": 1 + }, + "dornogovi-assr": { + "oil": 0.43, + "iron": 0.48, + "food": 1, + "industry": 0.78 + }, + "dosso-smfd": { + "oil": 0.16, + "iron": 0.58, + "food": 0.51, + "industry": 0 + }, + "doubs-xnyd": { + "oil": 0.75, + "iron": 0.54, + "food": 0.92, + "industry": 0.17 + }, + "doukkala-abda-sghb": { + "oil": 0.61, + "iron": 0.49, + "food": 0.03, + "industry": 0.59 + }, + "dubay-kskv": { + "oil": 0, + "iron": 0.01, + "food": 0.36, + "industry": 0.15 + }, + "dumfries-and-galloway-sres": { + "oil": 1, + "iron": 0.23, + "food": 1, + "industry": 0.76 + }, + "dundgovi-mgqq": { + "oil": 0.38, + "iron": 0.72, + "food": 0.12, + "industry": 0.01 + }, + "durango-gnsc": { + "oil": 0.3, + "iron": 1, + "food": 0.52, + "industry": 0.76 + }, + "durazno-qcxo": { + "oil": 0.56, + "iron": 0.73, + "food": 0.73, + "industry": 0.89 + }, + "dytiki-ellada-mlyj": { + "oil": 0.57, + "iron": 0.41, + "food": 0.37, + "industry": 0.97 + }, + "dytiki-makedonia-keyf": { + "oil": 0.51, + "iron": 0.12, + "food": 0.2, + "industry": 0.78 + }, + "dzavhan-yqqg": { + "oil": 0.33, + "iron": 0.72, + "food": 0.28, + "industry": 0.75 + }, + "east-azarbaijan-qxil": { + "oil": 0.06, + "iron": 0.1, + "food": 0.75, + "industry": 0.62 + }, + "east-flanders-cicp": { + "oil": 0.77, + "iron": 0.29, + "food": 0.31, + "industry": 0.73 + }, + "east-kazakhstan-ipgz": { + "oil": 0.93, + "iron": 1, + "food": 0.28, + "industry": 0.89 + }, + "east-new-britain-bphy": { + "oil": 0.39, + "iron": 0.46, + "food": 0.68, + "industry": 0.9 + }, + "east-sepik-azma": { + "oil": 0.82, + "iron": 0.36, + "food": 0.42, + "industry": 0.39 + }, + "eastern-avgq": { + "oil": 0.1, + "iron": 0.05, + "food": 0.86, + "industry": 0.42 + }, + "eastern-cape-oqpg": { + "oil": 0.02, + "iron": 0.43, + "food": 0.08, + "industry": 0.41 + }, + "eastern-darfur-kbbu": { + "oil": 0.45, + "iron": 0.52, + "food": 0.11, + "industry": 0.11 + }, + "eastern-dtaw": { + "oil": 0.78, + "iron": 0.21, + "food": 0.17, + "industry": 0.12 + }, + "eastern-equatoria-ilgp": { + "oil": 0.37, + "iron": 1, + "food": 0.19, + "industry": 1 + }, + "eastern-highlands-ohoa": { + "oil": 1, + "iron": 0.37, + "food": 0.96, + "industry": 0.32 + }, + "eastern-irer": { + "oil": 0.79, + "iron": 0.97, + "food": 0.6, + "industry": 0.71 + }, + "eastern-mxtw": { + "oil": 0.98, + "iron": 0.47, + "food": 0.49, + "industry": 0.91 + }, + "eastern-qapp": { + "oil": 0.53, + "iron": 0.19, + "food": 0.19, + "industry": 0.46 + }, + "edo-utql": { + "oil": 0.79, + "iron": 0.68, + "food": 0.82, + "industry": 0.73 + }, + "el-bayadh-gadi": { + "oil": 0.74, + "iron": 1, + "food": 0.47, + "industry": 0.92 + }, + "el-beni-aptp": { + "oil": 0.61, + "iron": 0.74, + "food": 0.49, + "industry": 0.56 + }, + "el-oued-oldp": { + "oil": 0.05, + "iron": 0.53, + "food": 0.88, + "industry": 0.06 + }, + "el-paraiso-gxia": { + "oil": 0.2, + "iron": 0.53, + "food": 0.39, + "industry": 0.73 + }, + "elbasan-bjpz": { + "oil": 0.25, + "iron": 0.91, + "food": 0.53, + "industry": 0.78 + }, + "enga-yfvk": { + "oil": 0.44, + "iron": 1, + "food": 0.58, + "industry": 0.22 + }, + "ennedi-sxtm": { + "oil": 0.77, + "iron": 0.63, + "food": 0.32, + "industry": 0.11 + }, + "entre-rios-wonq": { + "oil": 1, + "iron": 0.41, + "food": 0.56, + "industry": 0.94 + }, + "enugu-ijqf": { + "oil": 0.38, + "iron": 0.91, + "food": 0.33, + "industry": 0.66 + }, + "equateur-mkpe": { + "oil": 0.89, + "iron": 0.36, + "food": 0.51, + "industry": 0.45 + }, + "erongo-mmar": { + "oil": 0.44, + "iron": 0.57, + "food": 0.22, + "industry": 0.55 + }, + "erzincan-qvlh": { + "oil": 0.23, + "iron": 0.75, + "food": 0.81, + "industry": 1 + }, + "erzurum-kxli": { + "oil": 0.98, + "iron": 0.08, + "food": 1, + "industry": 0.46 + }, + "esfahan-wpig": { + "oil": 0.09, + "iron": 1, + "food": 0.98, + "industry": 1 + }, + "eskisehir-eslf": { + "oil": 0.21, + "iron": 0.17, + "food": 0.61, + "industry": 0.98 + }, + "esmeraldas-ikug": { + "oil": 0.88, + "iron": 0.49, + "food": 0.33, + "industry": 0.05 + }, + "espirito-santo-yopi": { + "oil": 0.83, + "iron": 0.68, + "food": 0.3, + "industry": 0.26 + }, + "est-umbd": { + "oil": 0.58, + "iron": 0.54, + "food": 0.48, + "industry": 0.55 + }, + "estuaire-qawm": { + "oil": 0.58, + "iron": 0.07, + "food": 0.42, + "industry": 0.03 + }, + "eure-jqyf": { + "oil": 0.49, + "iron": 0.05, + "food": 0.34, + "industry": 0.92 + }, + "evora-qfgt": { + "oil": 0.14, + "iron": 1, + "food": 0.41, + "industry": 0.77 + }, + "extreme-nord-oubi": { + "oil": 0.43, + "iron": 0.92, + "food": 1, + "industry": 0.54 + }, + "exuma-raxf": { + "oil": 0.32, + "iron": 0.32, + "food": 0.98, + "industry": 0.91 + }, + "f-a-t-a-yhan": { + "oil": 0.48, + "iron": 0.39, + "food": 0.5, + "industry": 0.55 + }, + "falcon-scqh": { + "oil": 0.24, + "iron": 0.74, + "food": 0.41, + "industry": 0.09 + }, + "falesti-qcpf": { + "oil": 0.16, + "iron": 0.84, + "food": 0.13, + "industry": 0.33 + }, + "falkland-islands-ubzb": { + "oil": 0.4, + "iron": 0.65, + "food": 0.89, + "industry": 0.38 + }, + "farah-dajq": { + "oil": 1, + "iron": 0.82, + "food": 0.89, + "industry": 0.29 + }, + "faranah-lbvx": { + "oil": 0.24, + "iron": 0.75, + "food": 0.91, + "industry": 0.42 + }, + "fars-wxkv": { + "oil": 0.5, + "iron": 0.31, + "food": 0.17, + "industry": 1 + }, + "faryab-ztoh": { + "oil": 0.83, + "iron": 0.49, + "food": 0.35, + "industry": 0.19 + }, + "fatick-kohi": { + "oil": 1, + "iron": 0.06, + "food": 0.1, + "industry": 0.24 + }, + "ferghana-ammo": { + "oil": 0.32, + "iron": 0.08, + "food": 0.03, + "industry": 0.77 + }, + "fes-boulemane-cjeq": { + "oil": 0.89, + "iron": 0.61, + "food": 0.56, + "industry": 0.64 + }, + "finnmark-mdcj": { + "oil": 1, + "iron": 0.96, + "food": 0.82, + "industry": 0.25 + }, + "firenze-sksq": { + "oil": 0.79, + "iron": 1, + "food": 0.39, + "industry": 0.09 + }, + "florida-acct": { + "oil": 0.24, + "iron": 0.81, + "food": 0.76, + "industry": 1 + }, + "florida-gmqg": { + "oil": 0.17, + "iron": 0.99, + "food": 0.52, + "industry": 0.95 + }, + "formosa-ctnd": { + "oil": 0.54, + "iron": 0.12, + "food": 0.47, + "industry": 0.57 + }, + "free-state-idrj": { + "oil": 0.59, + "iron": 0.66, + "food": 0.35, + "industry": 0.71 + }, + "fujian-gmhk": { + "oil": 0.8, + "iron": 0.74, + "food": 0.02, + "industry": 1 + }, + "fukuoka-ylvc": { + "oil": 0.62, + "iron": 0.24, + "food": 0.18, + "industry": 0.12 + }, + "fukushima-wpfv": { + "oil": 0.2, + "iron": 0.24, + "food": 0.43, + "industry": 0.24 + }, + "gafsa-ofsu": { + "oil": 0.06, + "iron": 0.93, + "food": 0.52, + "industry": 0.55 + }, + "galapagos-sguu": { + "oil": 0.16, + "iron": 0.41, + "food": 0.56, + "industry": 0.85 + }, + "galguduud-arwl": { + "oil": 0.67, + "iron": 0.55, + "food": 0.41, + "industry": 1 + }, + "galway-kjar": { + "oil": 0.78, + "iron": 0.8, + "food": 0.17, + "industry": 0.62 + }, + "gambela-peoples-sggc": { + "oil": 0.9, + "iron": 0.57, + "food": 0.58, + "industry": 0.74 + }, + "gandaki-ohsw": { + "oil": 0.2, + "iron": 0.39, + "food": 0.74, + "industry": 0.44 + }, + "gangwon-uuoi": { + "oil": 1, + "iron": 0.69, + "food": 0.8, + "industry": 0.26 + }, + "gansu-exjm": { + "oil": 0.47, + "iron": 0.43, + "food": 0.09, + "industry": 0.19 + }, + "gao-htwg": { + "oil": 0.32, + "iron": 0.73, + "food": 0.9, + "industry": 1 + }, + "gaoual-jpxg": { + "oil": 0.6, + "iron": 0.91, + "food": 0.18, + "industry": 0.81 + }, + "gard-guab": { + "oil": 0.58, + "iron": 0.27, + "food": 0.11, + "industry": 0.8 + }, + "gash-barka-coeg": { + "oil": 0.51, + "iron": 1, + "food": 0.01, + "industry": 0.59 + }, + "gauteng-eruj": { + "oil": 0.5, + "iron": 0.78, + "food": 0.88, + "industry": 0.79 + }, + "gavleborg-ynuf": { + "oil": 0.31, + "iron": 0.1, + "food": 0.35, + "industry": 0.08 + }, + "gaza-mnfq": { + "oil": 0.78, + "iron": 0.58, + "food": 0.41, + "industry": 0.27 + }, + "gaza-strip-sazs": { + "oil": 0.97, + "iron": 1, + "food": 0.38, + "industry": 0.61 + }, + "gbapolu-iigq": { + "oil": 0, + "iron": 0.49, + "food": 0.49, + "industry": 0.65 + }, + "gedarif-oxvo": { + "oil": 0.9, + "iron": 0.33, + "food": 0.68, + "industry": 0.06 + }, + "gedo-yxwp": { + "oil": 0.12, + "iron": 0.93, + "food": 0.25, + "industry": 0.54 + }, + "gegharkunik-qezd": { + "oil": 1, + "iron": 0.81, + "food": 0.85, + "industry": 0.94 + }, + "geita-elvs": { + "oil": 0.64, + "iron": 0.88, + "food": 0.75, + "industry": 0.87 + }, + "gelderland-ygoe": { + "oil": 0.49, + "iron": 0.35, + "food": 0.7, + "industry": 0.5 + }, + "georgia-uotf": { + "oil": 0.76, + "iron": 0.02, + "food": 0.55, + "industry": 0.58 + }, + "gers-wyad": { + "oil": 0.76, + "iron": 0.4, + "food": 0.91, + "industry": 0.7 + }, + "gezira-chvu": { + "oil": 0.93, + "iron": 0.16, + "food": 0.11, + "industry": 0.75 + }, + "ghadamis-aagv": { + "oil": 0.6, + "iron": 0.97, + "food": 1, + "industry": 0.16 + }, + "ghanzi-oamb": { + "oil": 0.7, + "iron": 1, + "food": 0.69, + "industry": 0.59 + }, + "ghardaia-czme": { + "oil": 0.39, + "iron": 1, + "food": 1, + "industry": 0.71 + }, + "ghat-ebgf": { + "oil": 0.71, + "iron": 0.24, + "food": 0.1, + "industry": 0.36 + }, + "ghazni-nnab": { + "oil": 0.19, + "iron": 0.79, + "food": 0.24, + "industry": 0.4 + }, + "ghor-bxar": { + "oil": 0.67, + "iron": 1, + "food": 0.77, + "industry": 1 + }, + "gia-lai-kyhl": { + "oil": 1, + "iron": 0.81, + "food": 0.44, + "industry": 0.27 + }, + "gifu-agjj": { + "oil": 0.91, + "iron": 0.44, + "food": 0.06, + "industry": 0.11 + }, + "gilan-ugkk": { + "oil": 0.82, + "iron": 0.95, + "food": 0.27, + "industry": 0.97 + }, + "giresun-wdlv": { + "oil": 0.12, + "iron": 1, + "food": 0.96, + "industry": 1 + }, + "gironde-nzae": { + "oil": 0.56, + "iron": 0.18, + "food": 0.25, + "industry": 0.62 + }, + "gnagna-qjxm": { + "oil": 0.59, + "iron": 1, + "food": 0.08, + "industry": 0.85 + }, + "goias-suuo": { + "oil": 0.88, + "iron": 0.56, + "food": 0.6, + "industry": 0.74 + }, + "golestan-cond": { + "oil": 0.25, + "iron": 0.24, + "food": 0.8, + "industry": 0.07 + }, + "gombe-ogwc": { + "oil": 0.01, + "iron": 1, + "food": 1, + "industry": 0.79 + }, + "gomel-evel": { + "oil": 0.59, + "iron": 0.68, + "food": 1, + "industry": 0.47 + }, + "gorgol-abfb": { + "oil": 0.18, + "iron": 0.95, + "food": 0.55, + "industry": 0.97 + }, + "gorj-qeiw": { + "oil": 0.78, + "iron": 0.17, + "food": 0.2, + "industry": 0.76 + }, + "gorno-altay-cstw": { + "oil": 0.81, + "iron": 0.35, + "food": 0.55, + "industry": 0.91 + }, + "gorno-badakhshan-sgex": { + "oil": 0.27, + "iron": 0.32, + "food": 0.68, + "industry": 0.27 + }, + "gorontalo-gihp": { + "oil": 0.88, + "iron": 0.74, + "food": 0.9, + "industry": 0.13 + }, + "gotland-qouw": { + "oil": 0.4, + "iron": 0.57, + "food": 0.72, + "industry": 0.47 + }, + "gourma-okzn": { + "oil": 0.16, + "iron": 0.8, + "food": 0.56, + "industry": 0.55 + }, + "govi-altay-ovst": { + "oil": 0.93, + "iron": 1, + "food": 1, + "industry": 0.52 + }, + "gracias-a-dios-kumu": { + "oil": 0.93, + "iron": 0.99, + "food": 1, + "industry": 0.88 + }, + "granada-yhir": { + "oil": 0.76, + "iron": 0.69, + "food": 0.24, + "industry": 0.15 + }, + "grand-bassa-vzwu": { + "oil": 0.16, + "iron": 0.61, + "food": 0.83, + "industry": 0.22 + }, + "grand-cape-mount-acht": { + "oil": 0.04, + "iron": 0.59, + "food": 0.61, + "industry": 0.89 + }, + "grand-gedeh-cewx": { + "oil": 0.37, + "iron": 0.68, + "food": 0.65, + "industry": 0.54 + }, + "granma-yeei": { + "oil": 0.71, + "iron": 0.2, + "food": 0.94, + "industry": 1 + }, + "greater-poland-ausi": { + "oil": 0.88, + "iron": 1, + "food": 0.31, + "industry": 0.61 + }, + "grodno-sbey": { + "oil": 0.04, + "iron": 0.62, + "food": 0.48, + "industry": 0.75 + }, + "grosseto-gtuw": { + "oil": 0.64, + "iron": 0.47, + "food": 0.92, + "industry": 0.2 + }, + "guadalajara-izim": { + "oil": 0.07, + "iron": 0.84, + "food": 0.8, + "industry": 0.57 + }, + "guadeloupe-wqci": { + "oil": 0.21, + "iron": 0.09, + "food": 0.15, + "industry": 0.26 + }, + "guainia-utmi": { + "oil": 0.48, + "iron": 0.64, + "food": 0.4, + "industry": 0.18 + }, + "guanacaste-ffmq": { + "oil": 0.16, + "iron": 0.44, + "food": 0.39, + "industry": 0.3 + }, + "guanajuato-uvcd": { + "oil": 0.77, + "iron": 0, + "food": 0.05, + "industry": 0.47 + }, + "guangdong-eajt": { + "oil": 0.97, + "iron": 0.81, + "food": 0.89, + "industry": 0.8 + }, + "guangxi-cgjb": { + "oil": 1, + "iron": 0.47, + "food": 0.3, + "industry": 0.58 + }, + "guarico-meqi": { + "oil": 1, + "iron": 0.77, + "food": 0, + "industry": 0.02 + }, + "guaviare-spmp": { + "oil": 0.68, + "iron": 0.18, + "food": 0.53, + "industry": 0.82 + }, + "guayas-whue": { + "oil": 0.97, + "iron": 0.32, + "food": 0.43, + "industry": 0.58 + }, + "guelmim-es-semara-qzhx": { + "oil": 1, + "iron": 0.12, + "food": 0.65, + "industry": 1 + }, + "guera-qyrk": { + "oil": 0.14, + "iron": 0.47, + "food": 0.05, + "industry": 0.48 + }, + "guerrero-iroj": { + "oil": 0.5, + "iron": 0.95, + "food": 0.22, + "industry": 0.08 + }, + "guidimaka-cqhe": { + "oil": 1, + "iron": 0.92, + "food": 1, + "industry": 0.01 + }, + "guizhou-qjjd": { + "oil": 0.9, + "iron": 1, + "food": 1, + "industry": 1 + }, + "gujarat-sooi": { + "oil": 0.36, + "iron": 0.1, + "food": 0.86, + "industry": 0.51 + }, + "gulbene-gcky": { + "oil": 0.2, + "iron": 0.63, + "food": 0.19, + "industry": 0.38 + }, + "gulf-yenl": { + "oil": 0.9, + "iron": 0.94, + "food": 0.04, + "industry": 0.32 + }, + "gumushane-melw": { + "oil": 0.12, + "iron": 0.21, + "food": 0.25, + "industry": 0.7 + }, + "guyane-francaise-gmcw": { + "oil": 0.93, + "iron": 0.52, + "food": 0.75, + "industry": 0.51 + }, + "gyeonggi-asoh": { + "oil": 0.17, + "iron": 0.55, + "food": 0.49, + "industry": 0.98 + }, + "ha-il-eoqk": { + "oil": 0.03, + "iron": 1, + "food": 0.15, + "industry": 0.46 + }, + "ha-noi-shnb": { + "oil": 0.18, + "iron": 0.37, + "food": 0.84, + "industry": 1 + }, + "hadarom-uves": { + "oil": 0.02, + "iron": 0.9, + "food": 0.48, + "industry": 0.54 + }, + "hadjer-lamis-avbt": { + "oil": 0.51, + "iron": 0.38, + "food": 0.73, + "industry": 0.88 + }, + "hadramawt-itbu": { + "oil": 0.52, + "iron": 0.15, + "food": 0.21, + "industry": 0.04 + }, + "hainan-mpfj": { + "oil": 0.87, + "iron": 1, + "food": 0.96, + "industry": 0.09 + }, + "hajdu-bihar-edea": { + "oil": 0.86, + "iron": 1, + "food": 0.8, + "industry": 0.53 + }, + "hajjah-uqbs": { + "oil": 0.19, + "iron": 0.24, + "food": 0.8, + "industry": 0.15 + }, + "hamadan-akna": { + "oil": 0.96, + "iron": 0.97, + "food": 0.02, + "industry": 0.67 + }, + "hamah-xsli": { + "oil": 0.39, + "iron": 0.14, + "food": 0.56, + "industry": 0.12 + }, + "hamgyong-bukto-yzdb": { + "oil": 0.47, + "iron": 1, + "food": 0.48, + "industry": 0.16 + }, + "hamgyong-namdo-cxda": { + "oil": 1, + "iron": 0.21, + "food": 0.07, + "industry": 1 + }, + "hardap-qqnp": { + "oil": 0.25, + "iron": 0.35, + "food": 1, + "industry": 1 + }, + "harghita-ybxj": { + "oil": 0.22, + "iron": 0.5, + "food": 0.94, + "industry": 1 + }, + "harju-qnwd": { + "oil": 0.91, + "iron": 0.59, + "food": 0.62, + "industry": 0.07 + }, + "haryana-wkdb": { + "oil": 0.11, + "iron": 0.55, + "food": 0.09, + "industry": 0.98 + }, + "hasaka-al-haksa-vlle": { + "oil": 0.9, + "iron": 0.38, + "food": 1, + "industry": 0.9 + }, + "haut-mbomou-qdrb": { + "oil": 0.52, + "iron": 0.32, + "food": 0.05, + "industry": 1 + }, + "haut-ogooue-kcwn": { + "oil": 0.1, + "iron": 0.17, + "food": 0.34, + "industry": 0.77 + }, + "haut-sassandra-aiql": { + "oil": 0.87, + "iron": 1, + "food": 0.67, + "industry": 0.72 + }, + "haute-corse-gmyy": { + "oil": 0.11, + "iron": 0.04, + "food": 0.05, + "industry": 0.31 + }, + "haute-garonne-bwac": { + "oil": 0.13, + "iron": 0.82, + "food": 0.3, + "industry": 0.58 + }, + "haute-kotto-ymrh": { + "oil": 0.57, + "iron": 0.97, + "food": 1, + "industry": 0 + }, + "haute-matsiatra-iovl": { + "oil": 0.62, + "iron": 0.01, + "food": 0.34, + "industry": 0.3 + }, + "hawaii-mxvl": { + "oil": 0.6, + "iron": 0.36, + "food": 0.71, + "industry": 1 + }, + "hawke-s-bay-iunb": { + "oil": 0.09, + "iron": 0.87, + "food": 0.98, + "industry": 0.45 + }, + "hebei-owfx": { + "oil": 0.55, + "iron": 0.09, + "food": 0.32, + "industry": 0.26 + }, + "hedmark-akyb": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 0.25 + }, + "heilongjiang-shfe": { + "oil": 0.94, + "iron": 0.41, + "food": 0.5, + "industry": 0.58 + }, + "henan-qdfb": { + "oil": 0.21, + "iron": 0.21, + "food": 0.3, + "industry": 0.66 + }, + "hentiy-kufs": { + "oil": 0.04, + "iron": 0.96, + "food": 0.91, + "industry": 0.85 + }, + "hessen-bqlm": { + "oil": 0.78, + "iron": 0.52, + "food": 0.52, + "industry": 0.65 + }, + "hidalgo-drfz": { + "oil": 0.13, + "iron": 0.07, + "food": 0.49, + "industry": 0.79 + }, + "highland-saxg": { + "oil": 0.28, + "iron": 0.92, + "food": 0.93, + "industry": 1 + }, + "hiiraan-knsf": { + "oil": 0.51, + "iron": 0.09, + "food": 0.42, + "industry": 0.52 + }, + "hilmand-gmdm": { + "oil": 1, + "iron": 0.95, + "food": 0.95, + "industry": 0.55 + }, + "himachal-pradesh-ggdz": { + "oil": 0.4, + "iron": 0.65, + "food": 1, + "industry": 0.26 + }, + "hirat-yddg": { + "oil": 0.19, + "iron": 0.42, + "food": 0.01, + "industry": 0.19 + }, + "hiroshima-tqmi": { + "oil": 1, + "iron": 0.28, + "food": 0.43, + "industry": 0.87 + }, + "hodh-ech-chargui-twfu": { + "oil": 0.35, + "iron": 0.29, + "food": 0.63, + "industry": 0.59 + }, + "hodh-el-gharbi-oyfv": { + "oil": 0.41, + "iron": 0.38, + "food": 0.86, + "industry": 0.06 + }, + "hoima-dcsv": { + "oil": 1, + "iron": 1, + "food": 0.33, + "industry": 0.81 + }, + "hokkaido-ksfx": { + "oil": 0.95, + "iron": 0.13, + "food": 0.54, + "industry": 0.46 + }, + "homs-hims-vcmm": { + "oil": 0.04, + "iron": 0.88, + "food": 0.48, + "industry": 0.5 + }, + "hordaland-yrai": { + "oil": 0.75, + "iron": 0.23, + "food": 0.23, + "industry": 0.67 + }, + "hormozgan-einz": { + "oil": 0.47, + "iron": 0.52, + "food": 0.29, + "industry": 0.59 + }, + "houaphan-lmpf": { + "oil": 0.69, + "iron": 0.9, + "food": 0.55, + "industry": 0.74 + }, + "houet-yrsy": { + "oil": 0.76, + "iron": 0.32, + "food": 0.32, + "industry": 0.96 + }, + "hovd-wxnd": { + "oil": 0.77, + "iron": 0.48, + "food": 0.1, + "industry": 0.05 + }, + "hovsgol-munb": { + "oil": 0.99, + "iron": 0.78, + "food": 0.64, + "industry": 0.28 + }, + "hualien-babs": { + "oil": 1, + "iron": 0.46, + "food": 0.48, + "industry": 0.35 + }, + "huambo-czeb": { + "oil": 0.19, + "iron": 0.89, + "food": 0.98, + "industry": 0.92 + }, + "huancavelica-orqp": { + "oil": 0.46, + "iron": 0.04, + "food": 0.7, + "industry": 0.72 + }, + "huanuco-uwqc": { + "oil": 0.45, + "iron": 0.68, + "food": 0.27, + "industry": 0.84 + }, + "hubei-eefc": { + "oil": 0.79, + "iron": 0.46, + "food": 0.32, + "industry": 0.57 + }, + "huehuetenango-mjgd": { + "oil": 0.03, + "iron": 0.29, + "food": 0.88, + "industry": 0.1 + }, + "huelva-qhbd": { + "oil": 0.68, + "iron": 0.45, + "food": 0.41, + "industry": 0.91 + }, + "huesca-ihkb": { + "oil": 0.09, + "iron": 0.63, + "food": 0.28, + "industry": 0.61 + }, + "huila-appk": { + "oil": 1, + "iron": 0.67, + "food": 0.21, + "industry": 0.36 + }, + "huila-ylej": { + "oil": 0.36, + "iron": 0.6, + "food": 0.37, + "industry": 0.81 + }, + "hunan-gkfg": { + "oil": 0.43, + "iron": 0.97, + "food": 0.14, + "industry": 0.73 + }, + "hwanghae-bukto-oudy": { + "oil": 0.65, + "iron": 0.1, + "food": 1, + "industry": 0.92 + }, + "hyogo-ksja": { + "oil": 0.68, + "iron": 0.96, + "food": 0.71, + "industry": 0.93 + }, + "iasi-gzad": { + "oil": 1, + "iron": 0.01, + "food": 0.55, + "industry": 0.65 + }, + "ibaraki-odfe": { + "oil": 0.38, + "iron": 0.32, + "food": 0.74, + "industry": 0.21 + }, + "ica-hijd": { + "oil": 0.2, + "iron": 1, + "food": 1, + "industry": 0.4 + }, + "ida-viru-ictd": { + "oil": 0.44, + "iron": 0.23, + "food": 0.81, + "industry": 0.26 + }, + "idaho-slym": { + "oil": 0.57, + "iron": 0.09, + "food": 0.48, + "industry": 0.13 + }, + "idlib-yoou": { + "oil": 0.34, + "iron": 0.25, + "food": 0.26, + "industry": 0 + }, + "ihorombe-mmvk": { + "oil": 0.63, + "iron": 0.47, + "food": 1, + "industry": 0.56 + }, + "ilam-oqih": { + "oil": 0.89, + "iron": 0.39, + "food": 0.25, + "industry": 0.59 + }, + "iles-eparses-de-l-ocean-indien-zmrd": { + "oil": 0.73, + "iron": 0.83, + "food": 0.69, + "industry": 0.91 + }, + "iles-saint-paul-et-nouvelle-amsterdam-smio": { + "oil": 0.51, + "iron": 0.06, + "food": 0.67, + "industry": 0.59 + }, + "illinois-syye": { + "oil": 0.68, + "iron": 0.19, + "food": 0.91, + "industry": 0.21 + }, + "illizi-ccdj": { + "oil": 0.82, + "iron": 0.7, + "food": 0.76, + "industry": 1 + }, + "iloilo-xbzy": { + "oil": 0.65, + "iron": 1, + "food": 1, + "industry": 0.89 + }, + "imereti-vlst": { + "oil": 0.94, + "iron": 0.29, + "food": 0.29, + "industry": 0.31 + }, + "inagua-ttnr": { + "oil": 0.03, + "iron": 0.51, + "food": 0.61, + "industry": 0.83 + }, + "inchiri-othg": { + "oil": 0.04, + "iron": 0.53, + "food": 0.75, + "industry": 0.66 + }, + "indiana-ivyc": { + "oil": 0.37, + "iron": 0.96, + "food": 0.72, + "industry": 0.33 + }, + "inhambane-aqfs": { + "oil": 0.98, + "iron": 0.18, + "food": 0.11, + "industry": 0.05 + }, + "inner-mongol-ioap": { + "oil": 0.96, + "iron": 0.07, + "food": 0.34, + "industry": 0.36 + }, + "iowa-cdyh": { + "oil": 0.56, + "iron": 0.46, + "food": 0.47, + "industry": 0.06 + }, + "iringa-ykrf": { + "oil": 0.27, + "iron": 0.15, + "food": 0.24, + "industry": 0.6 + }, + "irkutsk-wjtq": { + "oil": 0.63, + "iron": 0.17, + "food": 0.42, + "industry": 1 + }, + "isere-ghaj": { + "oil": 1, + "iron": 0.57, + "food": 1, + "industry": 0.32 + }, + "isles-of-scilly-oznv": { + "oil": 0.61, + "iron": 0.1, + "food": 0.1, + "industry": 0.22 + }, + "itapua-jomj": { + "oil": 0.19, + "iron": 0.38, + "food": 0.38, + "industry": 0.82 + }, + "ivano-frankivs-k-iocz": { + "oil": 0.42, + "iron": 0.07, + "food": 0.12, + "industry": 0.53 + }, + "ivanovo-uneq": { + "oil": 0.58, + "iron": 0.51, + "food": 0.16, + "industry": 0.04 + }, + "iwate-uvfz": { + "oil": 0.72, + "iron": 0.07, + "food": 0.51, + "industry": 0.33 + }, + "izmir-ehof": { + "oil": 0.75, + "iron": 0.71, + "food": 0.93, + "industry": 0.88 + }, + "jaen-ekbf": { + "oil": 1, + "iron": 0.43, + "food": 1, + "industry": 0.71 + }, + "jalal-abad-colt": { + "oil": 0.56, + "iron": 0.39, + "food": 0.09, + "industry": 0.98 + }, + "jalisco-kpbu": { + "oil": 0.19, + "iron": 1, + "food": 0.78, + "industry": 0.42 + }, + "jambi-sxbt": { + "oil": 0.22, + "iron": 0.25, + "food": 0.32, + "industry": 0.7 + }, + "jammu-and-kashmir-vhis": { + "oil": 0.07, + "iron": 0.7, + "food": 0.71, + "industry": 0.87 + }, + "jamtland-kquh": { + "oil": 0.2, + "iron": 0.16, + "food": 0.39, + "industry": 0.01 + }, + "janub-sina-mrqx": { + "oil": 0.05, + "iron": 0.76, + "food": 0.78, + "industry": 0.37 + }, + "jawa-barat-msbq": { + "oil": 0.77, + "iron": 0.78, + "food": 0.25, + "industry": 0.68 + }, + "jawa-tengah-eqby": { + "oil": 0.93, + "iron": 0.99, + "food": 0.23, + "industry": 0.16 + }, + "jawa-timur-skbb": { + "oil": 1, + "iron": 0.62, + "food": 0.73, + "industry": 1 + }, + "jawzjan-ibdk": { + "oil": 0.82, + "iron": 0.44, + "food": 0.61, + "industry": 0.91 + }, + "jeju-afop": { + "oil": 0.42, + "iron": 0.09, + "food": 0.27, + "industry": 0.89 + }, + "jharkhand-qjit": { + "oil": 0.23, + "iron": 0.26, + "food": 0.32, + "industry": 0.85 + }, + "jiangsu-kpkl": { + "oil": 0.14, + "iron": 0.26, + "food": 1, + "industry": 0.85 + }, + "jiangxi-geke": { + "oil": 0.83, + "iron": 1, + "food": 0.73, + "industry": 0.04 + }, + "jigawa-yzkn": { + "oil": 0.59, + "iron": 1, + "food": 0.74, + "industry": 0.75 + }, + "jilin-akky": { + "oil": 0.07, + "iron": 0.67, + "food": 0.89, + "industry": 0.05 + }, + "jinotega-yvws": { + "oil": 0.74, + "iron": 0.22, + "food": 0.57, + "industry": 0.44 + }, + "jizan-gfqv": { + "oil": 0.37, + "iron": 0.31, + "food": 0.66, + "industry": 0.62 + }, + "jizzakh-uoed": { + "oil": 1, + "iron": 1, + "food": 0.24, + "industry": 0.06 + }, + "johor-omus": { + "oil": 0.84, + "iron": 0.29, + "food": 0.3, + "industry": 0.04 + }, + "jonglei-setz": { + "oil": 0.93, + "iron": 0.48, + "food": 0.83, + "industry": 0.56 + }, + "jonkoping-eiuj": { + "oil": 0.02, + "iron": 0.92, + "food": 1, + "industry": 0.4 + }, + "jubbada-dhexe-unxw": { + "oil": 0.62, + "iron": 0.89, + "food": 0.92, + "industry": 1 + }, + "jubbada-hoose-wuxk": { + "oil": 0.34, + "iron": 0.1, + "food": 0.7, + "industry": 0.05 + }, + "jujuy-yinm": { + "oil": 0.7, + "iron": 0.26, + "food": 1, + "industry": 0.96 + }, + "junin-rnyf": { + "oil": 0.36, + "iron": 0.55, + "food": 0.7, + "industry": 1 + }, + "jutiapa-wdml": { + "oil": 0.03, + "iron": 0.74, + "food": 0.75, + "industry": 0.35 + }, + "juzno-backi-girr": { + "oil": 1, + "iron": 0.78, + "food": 0.38, + "industry": 0.24 + }, + "k-maras-wiwf": { + "oil": 0.61, + "iron": 0.5, + "food": 1, + "industry": 0.05 + }, + "k-p-stsm": { + "oil": 0.88, + "iron": 1, + "food": 0.54, + "industry": 0.27 + }, + "kabardin-balkar-kgec": { + "oil": 0.41, + "iron": 0.47, + "food": 1, + "industry": 0.5 + }, + "kabul-agcw": { + "oil": 0.13, + "iron": 0.1, + "food": 0.88, + "industry": 1 + }, + "kachin-etts": { + "oil": 0.15, + "iron": 0.04, + "food": 0.83, + "industry": 0.36 + }, + "kaduna-aymn": { + "oil": 0.66, + "iron": 0.17, + "food": 0.35, + "industry": 0.18 + }, + "kaffrine-ufni": { + "oil": 0.78, + "iron": 0.88, + "food": 0.89, + "industry": 0.77 + }, + "kagera-umrg": { + "oil": 1, + "iron": 0.1, + "food": 1, + "industry": 0.81 + }, + "kainuu-ayke": { + "oil": 0.83, + "iron": 1, + "food": 1, + "industry": 0.28 + }, + "kakheti-lswd": { + "oil": 0.28, + "iron": 0.29, + "food": 0.88, + "industry": 0.47 + }, + "kalbacar-zzbg": { + "oil": 0.91, + "iron": 0.72, + "food": 0.58, + "industry": 0.64 + }, + "kalimantan-barat-qpei": { + "oil": 0.59, + "iron": 0.06, + "food": 0.78, + "industry": 0.81 + }, + "kalimantan-selatan-smex": { + "oil": 0.14, + "iron": 0.38, + "food": 0.24, + "industry": 1 + }, + "kalimantan-tengah-area": { + "oil": 0.5, + "iron": 0.23, + "food": 0.95, + "industry": 0.81 + }, + "kalimantan-timur-kxex": { + "oil": 0.96, + "iron": 1, + "food": 1, + "industry": 0.28 + }, + "kaliningrad-ihxa": { + "oil": 0.82, + "iron": 0.4, + "food": 0.4, + "industry": 0.8 + }, + "kalmar-umuv": { + "oil": 0.57, + "iron": 0.69, + "food": 0.15, + "industry": 1 + }, + "kalmyk-yjee": { + "oil": 0.22, + "iron": 0.8, + "food": 0.44, + "industry": 0.09 + }, + "kaluga-fmjg": { + "oil": 0.77, + "iron": 0.93, + "food": 0.69, + "industry": 0.99 + }, + "kamchatka-rncn": { + "oil": 0.56, + "iron": 0.62, + "food": 0.48, + "industry": 1 + }, + "kampong-spoe-gatq": { + "oil": 0.01, + "iron": 0.68, + "food": 1, + "industry": 0.69 + }, + "kampong-thum-lytp": { + "oil": 0.65, + "iron": 0.21, + "food": 0.85, + "industry": 0.17 + }, + "kanchanaburi-udyq": { + "oil": 0.63, + "iron": 0.58, + "food": 0.77, + "industry": 0.88 + }, + "kandahar-cacs": { + "oil": 0.46, + "iron": 0.11, + "food": 0.11, + "industry": 0.62 + }, + "kanem-bhvv": { + "oil": 0.05, + "iron": 0.28, + "food": 1, + "industry": 0.14 + }, + "kangwon-do-kwdz": { + "oil": 0.98, + "iron": 0.29, + "food": 0.04, + "industry": 0.86 + }, + "kankan-kmei": { + "oil": 0.69, + "iron": 0.25, + "food": 0.78, + "industry": 0.19 + }, + "kano-oomx": { + "oil": 0.02, + "iron": 0.58, + "food": 0.58, + "industry": 0.88 + }, + "kansas-ondv": { + "oil": 0.69, + "iron": 0.36, + "food": 0.97, + "industry": 0.73 + }, + "kaoh-kong-astc": { + "oil": 0.05, + "iron": 0.63, + "food": 0.57, + "industry": 0.09 + }, + "kaohsiung-city-gnnm": { + "oil": 0.99, + "iron": 0.42, + "food": 0.94, + "industry": 0.61 + }, + "kara-khrl": { + "oil": 0.71, + "iron": 0.47, + "food": 0.22, + "industry": 0.64 + }, + "karachay-cherkess-gied": { + "oil": 0.17, + "iron": 0.08, + "food": 0.6, + "industry": 0.49 + }, + "karakalpakstan-cuod": { + "oil": 0.03, + "iron": 0.44, + "food": 0.47, + "industry": 0.76 + }, + "karas-etva": { + "oil": 0.6, + "iron": 0.69, + "food": 1, + "industry": 0.48 + }, + "karelia-ohem": { + "oil": 0.78, + "iron": 0.82, + "food": 1, + "industry": 0.81 + }, + "karnali-mbpa": { + "oil": 0.3, + "iron": 0.5, + "food": 0.25, + "industry": 1 + }, + "karnataka-rslx": { + "oil": 0.89, + "iron": 0.66, + "food": 1, + "industry": 0.22 + }, + "karnten-cypo": { + "oil": 0.86, + "iron": 0.31, + "food": 0.65, + "industry": 0.81 + }, + "kars-uiog": { + "oil": 0.66, + "iron": 0.21, + "food": 0.45, + "industry": 0.63 + }, + "kasai-occidental-udyu": { + "oil": 0.14, + "iron": 0.53, + "food": 0.63, + "industry": 0.82 + }, + "kasai-oriental-gzyi": { + "oil": 1, + "iron": 0.92, + "food": 0.51, + "industry": 0.09 + }, + "kasese-khsy": { + "oil": 0.68, + "iron": 0.35, + "food": 0.64, + "industry": 0.39 + }, + "kashkadarya-uvou": { + "oil": 0.72, + "iron": 1, + "food": 0.54, + "industry": 1 + }, + "kassala-odzh": { + "oil": 0.45, + "iron": 0.75, + "food": 0.87, + "industry": 0.12 + }, + "kastamonu-okoh": { + "oil": 0.98, + "iron": 0.92, + "food": 0.93, + "industry": 0.25 + }, + "kasungu-scgl": { + "oil": 0.3, + "iron": 0.11, + "food": 0.76, + "industry": 0.76 + }, + "katakwi-xlyx": { + "oil": 0.95, + "iron": 0.7, + "food": 0.8, + "industry": 0.83 + }, + "katanga-igym": { + "oil": 0.09, + "iron": 1, + "food": 0.25, + "industry": 0.54 + }, + "katavi-ytvx": { + "oil": 0.03, + "iron": 1, + "food": 0.72, + "industry": 0.6 + }, + "katsina-ezmx": { + "oil": 0.99, + "iron": 0.7, + "food": 0.44, + "industry": 0.09 + }, + "kauno-keod": { + "oil": 0.14, + "iron": 0.14, + "food": 0.57, + "industry": 0.59 + }, + "kavadartsi-yiil": { + "oil": 0.12, + "iron": 0.24, + "food": 1, + "industry": 0.9 + }, + "kavango-gglu": { + "oil": 0.95, + "iron": 1, + "food": 1, + "industry": 0.27 + }, + "kayah-uutt": { + "oil": 0.8, + "iron": 0.71, + "food": 0.02, + "industry": 0.6 + }, + "kayes-twwi": { + "oil": 0.66, + "iron": 0.73, + "food": 0.35, + "industry": 0.88 + }, + "kayin-owtu": { + "oil": 0.19, + "iron": 0.91, + "food": 0.66, + "industry": 0.45 + }, + "kayseri-kzoa": { + "oil": 0.42, + "iron": 0.57, + "food": 0.96, + "industry": 0.4 + }, + "kebbi-wamo": { + "oil": 1, + "iron": 0.24, + "food": 0.94, + "industry": 0.44 + }, + "kebili-ecss": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 1 + }, + "kedah-gout": { + "oil": 0.5, + "iron": 0.33, + "food": 0.67, + "industry": 0.41 + }, + "kedougou-syne": { + "oil": 0.23, + "iron": 0.89, + "food": 0.91, + "industry": 0.36 + }, + "kelantan-ypuu": { + "oil": 0.39, + "iron": 0.14, + "food": 0.56, + "industry": 0.12 + }, + "kemerovo-larh": { + "oil": 0.98, + "iron": 0, + "food": 0.17, + "industry": 0.93 + }, + "kemo-uuzv": { + "oil": 0.5, + "iron": 1, + "food": 0.7, + "industry": 0.4 + }, + "kenedougou-yxcn": { + "oil": 1, + "iron": 0.66, + "food": 0.52, + "industry": 0.93 + }, + "kentriki-makedonia-wdye": { + "oil": 0.16, + "iron": 0.96, + "food": 0.82, + "industry": 0.38 + }, + "kentucky-abeb": { + "oil": 0.66, + "iron": 0.78, + "food": 0.32, + "industry": 0.37 + }, + "kerala-clls": { + "oil": 0.68, + "iron": 0.44, + "food": 1, + "industry": 0.39 + }, + "kermadec-islands-ocbs": { + "oil": 0.71, + "iron": 0.37, + "food": 0.75, + "industry": 0.92 + }, + "kerman-oykw": { + "oil": 0.94, + "iron": 0.95, + "food": 1, + "industry": 0.58 + }, + "kermanshah-ccky": { + "oil": 0.12, + "iron": 0.68, + "food": 0.62, + "industry": 0.83 + }, + "kgalagadi-gaxy": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 0.86 + }, + "khabarovsk-vetk": { + "oil": 0.76, + "iron": 0.32, + "food": 0.51, + "industry": 0.16 + }, + "khakass-cuel": { + "oil": 1, + "iron": 0.51, + "food": 0.6, + "industry": 0.76 + }, + "khammouan-qmwz": { + "oil": 0.09, + "iron": 0.47, + "food": 0.5, + "industry": 0.37 + }, + "khanty-mansiy-tkto": { + "oil": 0.52, + "iron": 0.28, + "food": 0.89, + "industry": 1 + }, + "kharkiv-mesc": { + "oil": 0.27, + "iron": 0.06, + "food": 0.62, + "industry": 0.08 + }, + "khartoum-wpzy": { + "oil": 0.18, + "iron": 1, + "food": 0.16, + "industry": 0.41 + }, + "khatlon-qlhv": { + "oil": 0.78, + "iron": 0.73, + "food": 0.02, + "industry": 1 + }, + "khenchela-yomx": { + "oil": 0.15, + "iron": 0.11, + "food": 0.49, + "industry": 0.57 + }, + "kherson-ybsa": { + "oil": 0.12, + "iron": 1, + "food": 0.63, + "industry": 0.78 + }, + "khmel-nyts-kyy-etsv": { + "oil": 0.51, + "iron": 0.91, + "food": 0.77, + "industry": 0.56 + }, + "khomas-ievh": { + "oil": 1, + "iron": 0.57, + "food": 0.57, + "industry": 0.73 + }, + "khon-kaen-msqg": { + "oil": 0.54, + "iron": 0.72, + "food": 0.17, + "industry": 0.33 + }, + "khulna-purw": { + "oil": 0.76, + "iron": 0.9, + "food": 0.04, + "industry": 0.32 + }, + "khuzestan-yrkr": { + "oil": 0.34, + "iron": 1, + "food": 0.08, + "industry": 0.13 + }, + "kidal-yhwp": { + "oil": 0.5, + "iron": 0.46, + "food": 0.56, + "industry": 0.75 + }, + "kien-giang-qaqj": { + "oil": 0.48, + "iron": 0.88, + "food": 0.97, + "industry": 0.9 + }, + "kiev-yefc": { + "oil": 1, + "iron": 0.9, + "food": 0.77, + "industry": 0.06 + }, + "kigoma-aerb": { + "oil": 0.12, + "iron": 0.52, + "food": 0.37, + "industry": 0.11 + }, + "kilimanjaro-wgrc": { + "oil": 0.46, + "iron": 0.5, + "food": 0.84, + "industry": 0.72 + }, + "kindia-gbod": { + "oil": 0.07, + "iron": 0.33, + "food": 0.37, + "industry": 0.55 + }, + "kinmen-mdpx": { + "oil": 0.45, + "iron": 0.4, + "food": 0.85, + "industry": 0.76 + }, + "kinshasa-city-aoyb": { + "oil": 0.26, + "iron": 0.7, + "food": 0.81, + "industry": 0.45 + }, + "kirov-gfvm": { + "oil": 0.84, + "iron": 0.62, + "food": 0.1, + "industry": 0.99 + }, + "kirovohrad-gwfx": { + "oil": 0.53, + "iron": 0.47, + "food": 0.53, + "industry": 0.09 + }, + "kirsehir-iywz": { + "oil": 0.85, + "iron": 0.89, + "food": 0.3, + "industry": 0.88 + }, + "kissidougou-hloa": { + "oil": 1, + "iron": 0.1, + "food": 1, + "industry": 0.8 + }, + "kitgum-hetq": { + "oil": 1, + "iron": 0.63, + "food": 1, + "industry": 1 + }, + "klaipedos-kooa": { + "oil": 0.24, + "iron": 0.42, + "food": 0.45, + "industry": 0.82 + }, + "kocevje-gyjj": { + "oil": 0.38, + "iron": 0.47, + "food": 0.06, + "industry": 0.62 + }, + "kochi-aimd": { + "oil": 0.64, + "iron": 0.41, + "food": 0.8, + "industry": 1 + }, + "kogi-gqmy": { + "oil": 0.54, + "iron": 0.51, + "food": 0.52, + "industry": 0.51 + }, + "kohgiluyeh-and-buyer-ahmad-yekj": { + "oil": 0.67, + "iron": 0.05, + "food": 0.39, + "industry": 1 + }, + "kolda-oanf": { + "oil": 0.09, + "iron": 0.47, + "food": 0.52, + "industry": 0.65 + }, + "komi-eoeh": { + "oil": 0.86, + "iron": 0.22, + "food": 0.27, + "industry": 0.69 + }, + "kommune-kujalleq-nbjz": { + "oil": 0.92, + "iron": 0.3, + "food": 0.26, + "industry": 0.83 + }, + "kommuneqarfik-sermersooq-eqcb": { + "oil": 0.34, + "iron": 0.43, + "food": 1, + "industry": 0.81 + }, + "komoe-siqa": { + "oil": 0.94, + "iron": 0.77, + "food": 0.35, + "industry": 0.55 + }, + "kompienga-wuin": { + "oil": 0.08, + "iron": 0.23, + "food": 0.46, + "industry": 0.23 + }, + "kon-tum-ywew": { + "oil": 0.02, + "iron": 0.38, + "food": 0.14, + "industry": 0.14 + }, + "konya-ubwb": { + "oil": 0.05, + "iron": 0.17, + "food": 0.12, + "industry": 0.9 + }, + "kordestan-gakx": { + "oil": 0.57, + "iron": 1, + "food": 0.34, + "industry": 0.94 + }, + "kostroma-hmrp": { + "oil": 1, + "iron": 0, + "food": 0.7, + "industry": 0.44 + }, + "kouilou-qfqd": { + "oil": 0.64, + "iron": 0.18, + "food": 0.44, + "industry": 0.05 + }, + "koulikoro-oywj": { + "oil": 0.54, + "iron": 1, + "food": 0.3, + "industry": 1 + }, + "kouroussa-jsoo": { + "oil": 0.86, + "iron": 0.37, + "food": 0.95, + "industry": 0.4 + }, + "kracheh-suom": { + "oil": 0.07, + "iron": 0.93, + "food": 0.02, + "industry": 0.92 + }, + "krasnodar-nzpm": { + "oil": 0.01, + "iron": 0.53, + "food": 0.18, + "industry": 1 + }, + "krasnoyarsk-znif": { + "oil": 0.17, + "iron": 0.65, + "food": 0.23, + "industry": 0.96 + }, + "kronoberg-ykuk": { + "oil": 0.12, + "iron": 0.14, + "food": 1, + "industry": 0.45 + }, + "kunene-cmvm": { + "oil": 1, + "iron": 0.59, + "food": 0.65, + "industry": 0.29 + }, + "kurgan-yyxu": { + "oil": 0.73, + "iron": 1, + "food": 0.01, + "industry": 0.5 + }, + "kursk-obra": { + "oil": 0.98, + "iron": 0.4, + "food": 1, + "industry": 0.49 + }, + "kusini-pemba-iltp": { + "oil": 0.07, + "iron": 0.75, + "food": 0.38, + "industry": 0.75 + }, + "kutahya-odwc": { + "oil": 0.04, + "iron": 0.78, + "food": 0.82, + "industry": 0.45 + }, + "kuyavian-pomeranian-gfwe": { + "oil": 0.15, + "iron": 0.86, + "food": 0.82, + "industry": 0.62 + }, + "kwara-kema": { + "oil": 0.37, + "iron": 1, + "food": 1, + "industry": 0.05 + }, + "kwazulu-natal-capj": { + "oil": 0.5, + "iron": 0.81, + "food": 0.21, + "industry": 0.38 + }, + "kweneng-kxwi": { + "oil": 0.33, + "iron": 0.84, + "food": 0.84, + "industry": 0.41 + }, + "l-artibonite-egma": { + "oil": 0.11, + "iron": 0.09, + "food": 0.76, + "industry": 0.12 + }, + "l-viv-wbox": { + "oil": 0.88, + "iron": 0.32, + "food": 1, + "industry": 0.77 + }, + "la-altagracia-iexf": { + "oil": 0.65, + "iron": 0.71, + "food": 0.2, + "industry": 1 + }, + "la-araucania-aepm": { + "oil": 0.95, + "iron": 0.33, + "food": 0.36, + "industry": 0.41 + }, + "la-guajira-utww": { + "oil": 0.6, + "iron": 0.05, + "food": 0.25, + "industry": 0.32 + }, + "la-libertad-sqmm": { + "oil": 0.8, + "iron": 0.28, + "food": 0.72, + "industry": 0.54 + }, + "la-pampa-aznx": { + "oil": 0.41, + "iron": 1, + "food": 0.26, + "industry": 1 + }, + "la-paz-kftj": { + "oil": 1, + "iron": 0.73, + "food": 0.89, + "industry": 1 + }, + "la-reunion-voeo": { + "oil": 0.86, + "iron": 0.05, + "food": 0.68, + "industry": 0.83 + }, + "la-rioja-anut": { + "oil": 0.33, + "iron": 0.41, + "food": 0.63, + "industry": 0.16 + }, + "la-rioja-opnr": { + "oil": 0.81, + "iron": 0.86, + "food": 0.45, + "industry": 0.91 + }, + "laayoune-boujdour-sakia-el-hamra-cyhw": { + "oil": 0.06, + "iron": 0.45, + "food": 0.08, + "industry": 0.75 + }, + "lac-rmsk": { + "oil": 0.33, + "iron": 0.28, + "food": 0.2, + "industry": 0.11 + }, + "ladakh-ppmi": { + "oil": 0.71, + "iron": 0.58, + "food": 0.32, + "industry": 0.04 + }, + "laghouat-mwwa": { + "oil": 1, + "iron": 0.11, + "food": 0.98, + "industry": 0.91 + }, + "lagunes-igqk": { + "oil": 0.24, + "iron": 0.62, + "food": 0.39, + "industry": 0.03 + }, + "lahij-saqb": { + "oil": 0.78, + "iron": 0.81, + "food": 0.79, + "industry": 0.68 + }, + "lakes-uvxp": { + "oil": 0.01, + "iron": 0.1, + "food": 0.86, + "industry": 0.35 + }, + "lam-djong-iuhi": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 0.85 + }, + "lambayeque-yoml": { + "oil": 0.05, + "iron": 0.82, + "food": 0.52, + "industry": 0.58 + }, + "lampang-avtp": { + "oil": 0.5, + "iron": 0.94, + "food": 0.84, + "industry": 1 + }, + "lampung-yjht": { + "oil": 0.27, + "iron": 0.27, + "food": 1, + "industry": 0.87 + }, + "landes-kudi": { + "oil": 0.45, + "iron": 0.33, + "food": 0.71, + "industry": 0.92 + }, + "lang-son-yfzb": { + "oil": 0.8, + "iron": 0.35, + "food": 0.02, + "industry": 0.12 + }, + "lao-cai-suzu": { + "oil": 0.65, + "iron": 0.48, + "food": 0.32, + "industry": 1 + }, + "lapland-gcno": { + "oil": 0.18, + "iron": 0.37, + "food": 0.86, + "industry": 1 + }, + "lara-ggqj": { + "oil": 0.79, + "iron": 0.27, + "food": 0.56, + "industry": 0.17 + }, + "las-palmas-ujic": { + "oil": 0.03, + "iron": 0.14, + "food": 0.08, + "industry": 0.56 + }, + "lavalleja-mdrw": { + "oil": 0.4, + "iron": 0.45, + "food": 0.83, + "industry": 0.77 + }, + "le-kef-oxic": { + "oil": 0.27, + "iron": 0.01, + "food": 0.16, + "industry": 0.8 + }, + "lekoumou-inqi": { + "oil": 0.48, + "iron": 0.51, + "food": 0.91, + "industry": 0.68 + }, + "leninabad-dnbu": { + "oil": 0.7, + "iron": 0.28, + "food": 0.25, + "industry": 0.42 + }, + "leningrad-mknu": { + "oil": 0.05, + "iron": 0.5, + "food": 0.65, + "industry": 1 + }, + "leon-gvhg": { + "oil": 0.05, + "iron": 0.4, + "food": 0.73, + "industry": 0.27 + }, + "leon-uyuj": { + "oil": 0.93, + "iron": 0.44, + "food": 0.2, + "industry": 0.32 + }, + "lerida-onbh": { + "oil": 0.97, + "iron": 0.82, + "food": 0.41, + "industry": 0.3 + }, + "lesser-poland-ukhv": { + "oil": 0.32, + "iron": 0.88, + "food": 0.36, + "industry": 1 + }, + "liaoning-wswa": { + "oil": 1, + "iron": 0.98, + "food": 0.9, + "industry": 0.67 + }, + "libertador-general-bernardo-o-higgins-ghiu": { + "oil": 0.83, + "iron": 0.21, + "food": 0.55, + "industry": 0.67 + }, + "licko-senjska-cvjk": { + "oil": 0.84, + "iron": 0.43, + "food": 0.84, + "industry": 0.18 + }, + "likouala-aiqf": { + "oil": 0.57, + "iron": 0.84, + "food": 0.96, + "industry": 0.49 + }, + "lilongwe-kdpi": { + "oil": 1, + "iron": 0.45, + "food": 0.15, + "industry": 0.89 + }, + "lima-iioy": { + "oil": 0.95, + "iron": 0.26, + "food": 0.91, + "industry": 1 + }, + "limon-ynmv": { + "oil": 0.5, + "iron": 0.02, + "food": 0.89, + "industry": 0.81 + }, + "limpopo-kvkx": { + "oil": 0.51, + "iron": 0.51, + "food": 0.93, + "industry": 0.25 + }, + "lincolnshire-odkr": { + "oil": 0.7, + "iron": 0.59, + "food": 0.21, + "industry": 1 + }, + "lindi-yitn": { + "oil": 0.23, + "iron": 0.1, + "food": 0.1, + "industry": 0.4 + }, + "lipetsk-qvwo": { + "oil": 0.5, + "iron": 0.4, + "food": 0.83, + "industry": 0.57 + }, + "littoral-oyts": { + "oil": 0.21, + "iron": 0.91, + "food": 0.91, + "industry": 0.63 + }, + "lobaye-uriq": { + "oil": 0.97, + "iron": 0.2, + "food": 1, + "industry": 0.58 + }, + "lodz-gveo": { + "oil": 0.95, + "iron": 1, + "food": 0.18, + "industry": 0.25 + }, + "loei-avqi": { + "oil": 0.93, + "iron": 0.93, + "food": 0.42, + "industry": 0.06 + }, + "logone-oriental-wotz": { + "oil": 0.91, + "iron": 0.6, + "food": 0.72, + "industry": 0.95 + }, + "loir-et-cher-fwdj": { + "oil": 0.93, + "iron": 1, + "food": 0.69, + "industry": 0.73 + }, + "loire-atlantique-mode": { + "oil": 0.71, + "iron": 1, + "food": 0.09, + "industry": 0.38 + }, + "loja-czuz": { + "oil": 0.69, + "iron": 0.31, + "food": 0.53, + "industry": 0.81 + }, + "long-an-irqd": { + "oil": 0.12, + "iron": 0.65, + "food": 0.28, + "industry": 0.94 + }, + "lord-howe-island-krnq": { + "oil": 0.91, + "iron": 0.59, + "food": 0.25, + "industry": 0.53 + }, + "lorestan-ydnw": { + "oil": 1, + "iron": 0.63, + "food": 0.65, + "industry": 0.94 + }, + "loreto-ipkx": { + "oil": 0.99, + "iron": 0.84, + "food": 0.54, + "industry": 0.23 + }, + "lori-aqmn": { + "oil": 0.51, + "iron": 0.24, + "food": 0.16, + "industry": 0.62 + }, + "los-lagos-mmix": { + "oil": 0.29, + "iron": 0.53, + "food": 0.49, + "industry": 0.67 + }, + "los-rios-gxix": { + "oil": 0.46, + "iron": 0.92, + "food": 0.78, + "industry": 0.35 + }, + "los-rios-mouz": { + "oil": 0.07, + "iron": 0.54, + "food": 0.38, + "industry": 0.94 + }, + "lot-et-garonne-psdh": { + "oil": 0.96, + "iron": 1, + "food": 0.96, + "industry": 0.87 + }, + "louang-namtha-fbyj": { + "oil": 1, + "iron": 0.16, + "food": 0.61, + "industry": 0.45 + }, + "louangphrabang-quyo": { + "oil": 1, + "iron": 0.97, + "food": 0.01, + "industry": 0.3 + }, + "louga-wgwg": { + "oil": 0.31, + "iron": 0.97, + "food": 0.91, + "industry": 0.29 + }, + "louisiana-wlgr": { + "oil": 1, + "iron": 0.25, + "food": 1, + "industry": 1 + }, + "lower-silesian-eayz": { + "oil": 0.65, + "iron": 1, + "food": 0.78, + "industry": 0.37 + }, + "luapula-imtp": { + "oil": 0.18, + "iron": 1, + "food": 0.37, + "industry": 0.96 + }, + "lublin-gyez": { + "oil": 0.49, + "iron": 0.92, + "food": 0.57, + "industry": 0.31 + }, + "lubombo-ybpl": { + "oil": 1, + "iron": 0.65, + "food": 1, + "industry": 0.36 + }, + "lubusz-wsem": { + "oil": 0.67, + "iron": 0.93, + "food": 0.63, + "industry": 1 + }, + "lugo-qbvz": { + "oil": 0.68, + "iron": 0.74, + "food": 1, + "industry": 0.78 + }, + "luhans-k-whxu": { + "oil": 1, + "iron": 0.85, + "food": 1, + "industry": 0.29 + }, + "lunda-norte-kkid": { + "oil": 0.51, + "iron": 0.97, + "food": 0.72, + "industry": 0.02 + }, + "lunda-sul-iyot": { + "oil": 0.73, + "iron": 0.77, + "food": 0.95, + "industry": 0.96 + }, + "lusaka-ygtc": { + "oil": 1, + "iron": 0.59, + "food": 0.79, + "industry": 0.06 + }, + "luxembourg-krjs": { + "oil": 0.08, + "iron": 0.46, + "food": 0.46, + "industry": 1 + }, + "m-sila-sobh": { + "oil": 0.14, + "iron": 0.52, + "food": 0.62, + "industry": 0.8 + }, + "ma-an-lrvp": { + "oil": 0.34, + "iron": 0.5, + "food": 0.69, + "industry": 0.07 + }, + "ma-rib-oyto": { + "oil": 0.04, + "iron": 0.13, + "food": 0.29, + "industry": 0.91 + }, + "machinga-mtss": { + "oil": 0.38, + "iron": 0.48, + "food": 0.9, + "industry": 0.78 + }, + "macquarie-island-yijx": { + "oil": 0.47, + "iron": 0.2, + "food": 0.53, + "industry": 0.28 + }, + "madang-elun": { + "oil": 0.37, + "iron": 1, + "food": 0.67, + "industry": 1 + }, + "madeira-croh": { + "oil": 0.08, + "iron": 1, + "food": 0.78, + "industry": 0.53 + }, + "madhya-pradesh-qlpo": { + "oil": 0.71, + "iron": 0.06, + "food": 0.33, + "industry": 0.21 + }, + "madre-de-dios-fpxm": { + "oil": 0.16, + "iron": 0.76, + "food": 0.39, + "industry": 0.46 + }, + "madrid-kpbi": { + "oil": 0.68, + "iron": 0.53, + "food": 0.96, + "industry": 0.56 + }, + "mae-hong-son-qftf": { + "oil": 0.5, + "iron": 0.76, + "food": 0.06, + "industry": 0.26 + }, + "maekel-litf": { + "oil": 0.17, + "iron": 0.39, + "food": 0.48, + "industry": 0.28 + }, + "mafraq-invm": { + "oil": 0.69, + "iron": 0.29, + "food": 0.14, + "industry": 0.72 + }, + "maga-buryatdan-wvtk": { + "oil": 0.3, + "iron": 0.85, + "food": 0.85, + "industry": 0.73 + }, + "magallanes-y-antartica-chilena-eqmb": { + "oil": 0.95, + "iron": 0.3, + "food": 0.27, + "industry": 0.58 + }, + "magdalena-wrsg": { + "oil": 0.98, + "iron": 0.46, + "food": 0.16, + "industry": 0.79 + }, + "magway-karn": { + "oil": 0.91, + "iron": 1, + "food": 0.66, + "industry": 0.57 + }, + "mahaica-berbice-igzl": { + "oil": 0.44, + "iron": 0.54, + "food": 1, + "industry": 0.64 + }, + "maharashtra-qypg": { + "oil": 0.79, + "iron": 0.96, + "food": 0.43, + "industry": 0.15 + }, + "maine-maiz": { + "oil": 0.15, + "iron": 1, + "food": 0.35, + "industry": 0.39 + }, + "makira-qcnj": { + "oil": 0.95, + "iron": 0.62, + "food": 0.27, + "industry": 0.46 + }, + "makkah-yuqo": { + "oil": 0.53, + "iron": 0.42, + "food": 0.33, + "industry": 0.1 + }, + "malanje-quaz": { + "oil": 0.55, + "iron": 0.8, + "food": 0.28, + "industry": 0.14 + }, + "malatya-kfwd": { + "oil": 0.83, + "iron": 0.52, + "food": 0.99, + "industry": 0.2 + }, + "mali-ayzp": { + "oil": 0.4, + "iron": 0.5, + "food": 0.59, + "industry": 0.11 + }, + "maluku-qzjd": { + "oil": 0.29, + "iron": 0.38, + "food": 0.38, + "industry": 0.96 + }, + "maluku-utara-osjp": { + "oil": 0.84, + "iron": 0.9, + "food": 0.66, + "industry": 0.17 + }, + "mambere-kadei-carz": { + "oil": 0.41, + "iron": 0.07, + "food": 0.47, + "industry": 0.53 + }, + "mamou-rzzq": { + "oil": 0.39, + "iron": 0.92, + "food": 0.56, + "industry": 0.08 + }, + "manabi-myuy": { + "oil": 0.72, + "iron": 0.36, + "food": 0.71, + "industry": 0.65 + }, + "manawatu-wanganui-zrxu": { + "oil": 0.43, + "iron": 1, + "food": 0.64, + "industry": 0.28 + }, + "mandalay-gcro": { + "oil": 0.97, + "iron": 0.96, + "food": 1, + "industry": 0.26 + }, + "mandiana-alzh": { + "oil": 0.17, + "iron": 0.09, + "food": 0.44, + "industry": 0.47 + }, + "mandoul-jypx": { + "oil": 1, + "iron": 0.54, + "food": 0.24, + "industry": 0.04 + }, + "mangghystau-ooqu": { + "oil": 0.81, + "iron": 0.63, + "food": 0.65, + "industry": 0.8 + }, + "mangochi-qesd": { + "oil": 0.61, + "iron": 0.78, + "food": 0.19, + "industry": 0 + }, + "manica-wffl": { + "oil": 0.59, + "iron": 0.73, + "food": 0.28, + "industry": 0.75 + }, + "manicaland-czzx": { + "oil": 0.98, + "iron": 0.08, + "food": 0.51, + "industry": 0.2 + }, + "maniema-eoks": { + "oil": 0.35, + "iron": 0.51, + "food": 0.58, + "industry": 0.54 + }, + "manipur-ahpm": { + "oil": 0.03, + "iron": 0.31, + "food": 0.26, + "industry": 0.63 + }, + "manisa-cgwe": { + "oil": 0.7, + "iron": 0.43, + "food": 0.9, + "industry": 0.94 + }, + "manitoba-thmy": { + "oil": 0.93, + "iron": 0.89, + "food": 0.63, + "industry": 0.63 + }, + "manus-oxpg": { + "oil": 0.75, + "iron": 0.69, + "food": 1, + "industry": 0.73 + }, + "manyara-mkvr": { + "oil": 1, + "iron": 0.67, + "food": 0.37, + "industry": 1 + }, + "maputo-gvfv": { + "oil": 1, + "iron": 0.29, + "food": 0.99, + "industry": 0.72 + }, + "mara-cgtm": { + "oil": 0.02, + "iron": 0.76, + "food": 0.84, + "industry": 0.2 + }, + "maradi-knfe": { + "oil": 0.54, + "iron": 0.56, + "food": 0.41, + "industry": 0.8 + }, + "maramures-iwjv": { + "oil": 0.7, + "iron": 1, + "food": 0.01, + "industry": 0.83 + }, + "maranhao-ojve": { + "oil": 0.31, + "iron": 0.11, + "food": 1, + "industry": 0.99 + }, + "mariy-el-umod": { + "oil": 0.26, + "iron": 0.17, + "food": 0.17, + "industry": 0.61 + }, + "markazi-qhny": { + "oil": 1, + "iron": 0.89, + "food": 0.24, + "industry": 0.77 + }, + "marlborough-district-oyxs": { + "oil": 0.03, + "iron": 1, + "food": 0.47, + "industry": 0.44 + }, + "marne-hpgs": { + "oil": 0.16, + "iron": 0.54, + "food": 0.64, + "industry": 0.93 + }, + "marrakech-tensift-al-haouz-weha": { + "oil": 0.27, + "iron": 0.5, + "food": 0.5, + "industry": 0.66 + }, + "martinique-tuau": { + "oil": 1, + "iron": 0.9, + "food": 0.19, + "industry": 1 + }, + "mary-qxca": { + "oil": 0.68, + "iron": 0.65, + "food": 0.21, + "industry": 0.68 + }, + "maryland-ecia": { + "oil": 0.34, + "iron": 0.95, + "food": 0.81, + "industry": 0.04 + }, + "maseru-quuq": { + "oil": 0.11, + "iron": 0.19, + "food": 0.57, + "industry": 0.57 + }, + "mashonaland-central-mczz": { + "oil": 0.84, + "iron": 0.73, + "food": 0.14, + "industry": 0.3 + }, + "mashonaland-east-afzb": { + "oil": 0.91, + "iron": 0.24, + "food": 0.32, + "industry": 1 + }, + "mashonaland-west-ojzn": { + "oil": 0.18, + "iron": 0.47, + "food": 1, + "industry": 0.7 + }, + "masovian-uuhs": { + "oil": 0.09, + "iron": 0.01, + "food": 0.86, + "industry": 0.35 + }, + "massachusetts-ggid": { + "oil": 1, + "iron": 0.61, + "food": 1, + "industry": 0.46 + }, + "masvingo-wizm": { + "oil": 0.29, + "iron": 0.14, + "food": 0.12, + "industry": 0.28 + }, + "matabeleland-north-otzk": { + "oil": 0.5, + "iron": 0.45, + "food": 0.8, + "industry": 0.22 + }, + "matabeleland-south-qdzj": { + "oil": 0.16, + "iron": 1, + "food": 0.14, + "industry": 0.59 + }, + "matagalpa-iykc": { + "oil": 0.15, + "iron": 0.47, + "food": 0.81, + "industry": 1 + }, + "matam-qxzf": { + "oil": 0.51, + "iron": 0.14, + "food": 0.73, + "industry": 0.04 + }, + "matanzas-kobf": { + "oil": 0.95, + "iron": 0.08, + "food": 0.78, + "industry": 0.51 + }, + "mato-grosso-aqvz": { + "oil": 0.16, + "iron": 0.65, + "food": 0.22, + "industry": 1 + }, + "mato-grosso-do-sul-wfvs": { + "oil": 0.43, + "iron": 1, + "food": 0.54, + "industry": 0.74 + }, + "matruh-cafp": { + "oil": 0.31, + "iron": 1, + "food": 1, + "industry": 0.18 + }, + "maule-kvme": { + "oil": 0.46, + "iron": 0.87, + "food": 0.32, + "industry": 0.69 + }, + "mayaguana-kkei": { + "oil": 0.48, + "iron": 0.85, + "food": 0.72, + "industry": 0.3 + }, + "mayo-kebbi-est-hepb": { + "oil": 0.07, + "iron": 0.83, + "food": 0.38, + "industry": 0.29 + }, + "mayo-kebbi-ouest-tupl": { + "oil": 0.81, + "iron": 0.14, + "food": 0.41, + "industry": 0.56 + }, + "mayotte-gthm": { + "oil": 0.49, + "iron": 0.06, + "food": 0.97, + "industry": 0.57 + }, + "maysan-rzfn": { + "oil": 0.87, + "iron": 0.73, + "food": 0.83, + "industry": 0.84 + }, + "mazandaran-ufnx": { + "oil": 0.07, + "iron": 0.86, + "food": 0.09, + "industry": 0.11 + }, + "mbarara-mcue": { + "oil": 0.9, + "iron": 0.84, + "food": 0.5, + "industry": 0.99 + }, + "mbarara-yqvb": { + "oil": 0.76, + "iron": 0.28, + "food": 0.99, + "industry": 0.46 + }, + "mbeya-getl": { + "oil": 0.29, + "iron": 0.51, + "food": 0.06, + "industry": 0.39 + }, + "mbomou-ydky": { + "oil": 0.35, + "iron": 0.34, + "food": 0.52, + "industry": 0.38 + }, + "mecklenburg-vorpommern-pqcp": { + "oil": 0.41, + "iron": 0.92, + "food": 0.91, + "industry": 1 + }, + "medea-elbf": { + "oil": 0.65, + "iron": 0.17, + "food": 0.34, + "industry": 0.18 + }, + "meghalaya-oepk": { + "oil": 0.41, + "iron": 0.54, + "food": 0.16, + "industry": 0.12 + }, + "meknes-tafilalet-yler": { + "oil": 0.43, + "iron": 0.76, + "food": 0.98, + "industry": 0.56 + }, + "melaky-ynaf": { + "oil": 1, + "iron": 1, + "food": 0.72, + "industry": 0.64 + }, + "melilla-uuxv": { + "oil": 0.91, + "iron": 0.63, + "food": 0.95, + "industry": 0.7 + }, + "menabe-icfs": { + "oil": 0.5, + "iron": 0.14, + "food": 0.17, + "industry": 0.94 + }, + "mendoza-sany": { + "oil": 0.55, + "iron": 0.69, + "food": 0.84, + "industry": 1 + }, + "merida-yhqk": { + "oil": 0.47, + "iron": 0.35, + "food": 0.19, + "industry": 1 + }, + "mersin-mqol": { + "oil": 0.16, + "iron": 0.45, + "food": 0.75, + "industry": 1 + }, + "meta-ymbx": { + "oil": 0.84, + "iron": 0.18, + "food": 0.75, + "industry": 0.15 + }, + "mexico-ewrz": { + "oil": 0.1, + "iron": 0.44, + "food": 0.99, + "industry": 0.87 + }, + "mexico-mpba": { + "oil": 1, + "iron": 0.34, + "food": 0.99, + "industry": 0.31 + }, + "michigan-gtil": { + "oil": 0.94, + "iron": 0.47, + "food": 0.67, + "industry": 0.07 + }, + "michoacan-uekn": { + "oil": 0.89, + "iron": 0.05, + "food": 0.4, + "industry": 0.5 + }, + "midlands-cmzf": { + "oil": 0.91, + "iron": 0.78, + "food": 0.78, + "industry": 0.49 + }, + "midtjylland-gjbs": { + "oil": 0.67, + "iron": 0.65, + "food": 0.28, + "industry": 0.91 + }, + "mie-iljm": { + "oil": 0.76, + "iron": 0.85, + "food": 0.84, + "industry": 1 + }, + "milne-bay-gubz": { + "oil": 0.77, + "iron": 0.52, + "food": 0.52, + "industry": 0.65 + }, + "minas-gerais-ymvg": { + "oil": 0.59, + "iron": 0.48, + "food": 0.23, + "industry": 0.98 + }, + "mindoro-occidental-sjgh": { + "oil": 0.33, + "iron": 0.54, + "food": 0.24, + "industry": 0.3 + }, + "minnesota-qlig": { + "oil": 0.47, + "iron": 0.93, + "food": 0.37, + "industry": 0.41 + }, + "minsk-sirf": { + "oil": 0.62, + "iron": 1, + "food": 1, + "industry": 0.86 + }, + "miranda-ujql": { + "oil": 0.1, + "iron": 1, + "food": 0.44, + "industry": 0.36 + }, + "misiones-ocnz": { + "oil": 1, + "iron": 1, + "food": 0.81, + "industry": 0.88 + }, + "misratah-cbhm": { + "oil": 0.28, + "iron": 0.34, + "food": 0.49, + "industry": 0.65 + }, + "mississippi-scir": { + "oil": 0.63, + "iron": 0.13, + "food": 0.09, + "industry": 0.55 + }, + "missouri-ykif": { + "oil": 0.96, + "iron": 0.79, + "food": 0.86, + "industry": 0.67 + }, + "miyazaki-stvh": { + "oil": 0.52, + "iron": 0.97, + "food": 0.61, + "industry": 0.1 + }, + "mizdah-uchd": { + "oil": 0.24, + "iron": 0.71, + "food": 0.8, + "industry": 0.17 + }, + "mizoram-yapy": { + "oil": 0.13, + "iron": 1, + "food": 0.25, + "industry": 0.96 + }, + "mogilev-srqt": { + "oil": 0.79, + "iron": 1, + "food": 0.78, + "industry": 0.01 + }, + "mon-cmto": { + "oil": 0.94, + "iron": 1, + "food": 0.12, + "industry": 0.34 + }, + "monagas-kkqm": { + "oil": 1, + "iron": 0.67, + "food": 1, + "industry": 0.72 + }, + "monaragala-wspd": { + "oil": 0.97, + "iron": 0.76, + "food": 0.21, + "industry": 0.03 + }, + "mondol-kiri-jvon": { + "oil": 0.35, + "iron": 0.26, + "food": 0.93, + "industry": 0.84 + }, + "montana-abiq": { + "oil": 1, + "iron": 0.69, + "food": 0.42, + "industry": 0.57 + }, + "mopti-vqwe": { + "oil": 0.56, + "iron": 0.82, + "food": 0.82, + "industry": 0.35 + }, + "moquegua-xwwn": { + "oil": 0.2, + "iron": 0.55, + "food": 0.95, + "industry": 1 + }, + "moravskoslezsky-sbcc": { + "oil": 0.18, + "iron": 0.53, + "food": 0.16, + "industry": 1 + }, + "mordovia-abon": { + "oil": 0.61, + "iron": 0.17, + "food": 0.41, + "industry": 1 + }, + "more-og-romsdal-aval": { + "oil": 0.31, + "iron": 0.79, + "food": 0.85, + "industry": 1 + }, + "morobe-anuo": { + "oil": 0.08, + "iron": 0.71, + "food": 0.55, + "industry": 0.41 + }, + "morogoro-wbtj": { + "oil": 0.34, + "iron": 0.69, + "food": 0.14, + "industry": 0.96 + }, + "morona-santiago-unuy": { + "oil": 0.77, + "iron": 0.52, + "food": 0.26, + "industry": 0.27 + }, + "moselle-rygy": { + "oil": 0.44, + "iron": 0.04, + "food": 0.38, + "industry": 0.88 + }, + "moskovskaya-chlr": { + "oil": 0.4, + "iron": 0.98, + "food": 0.52, + "industry": 1 + }, + "mou-houn-azqo": { + "oil": 0.18, + "iron": 0.4, + "food": 0.3, + "industry": 0.65 + }, + "moxico-ievb": { + "oil": 1, + "iron": 0.85, + "food": 1, + "industry": 0.26 + }, + "moyen-chari-vbpz": { + "oil": 0.51, + "iron": 0.7, + "food": 0.7, + "industry": 0.16 + }, + "moyen-ogooue-eewo": { + "oil": 0.24, + "iron": 0.69, + "food": 0.84, + "industry": 0.78 + }, + "mpumalanga-yrnu": { + "oil": 0.1, + "iron": 0.3, + "food": 0.9, + "industry": 0.34 + }, + "mtskheta-mtianeti-dbcb": { + "oil": 0.03, + "iron": 0.35, + "food": 0.51, + "industry": 0.42 + }, + "mtwara-eati": { + "oil": 0.25, + "iron": 0.22, + "food": 0.91, + "industry": 0.79 + }, + "mubende-stqq": { + "oil": 0.59, + "iron": 0.88, + "food": 0.63, + "industry": 0.01 + }, + "muchinga-kova": { + "oil": 0.05, + "iron": 0.09, + "food": 0.2, + "industry": 0.95 + }, + "mudug-kpld": { + "oil": 0.14, + "iron": 1, + "food": 0.48, + "industry": 0.05 + }, + "mugla-mmwr": { + "oil": 0.8, + "iron": 0.62, + "food": 1, + "industry": 0.93 + }, + "mukdahan-ihqz": { + "oil": 0.33, + "iron": 0.21, + "food": 0.36, + "industry": 0.8 + }, + "mukono-khqz": { + "oil": 0.15, + "iron": 0.29, + "food": 1, + "industry": 0.87 + }, + "murcia-qjxo": { + "oil": 0.91, + "iron": 0.91, + "food": 0.82, + "industry": 0.62 + }, + "mures-yhjv": { + "oil": 0.14, + "iron": 1, + "food": 0.84, + "industry": 0.18 + }, + "murmansk-etas": { + "oil": 0.23, + "iron": 0.18, + "food": 0.29, + "industry": 0.89 + }, + "murzuq-cohu": { + "oil": 0.13, + "iron": 0.15, + "food": 0.81, + "industry": 0.25 + }, + "musandam-ubnu": { + "oil": 0.85, + "iron": 0.2, + "food": 0.07, + "industry": 0.85 + }, + "mwanza-iyth": { + "oil": 0.17, + "iron": 1, + "food": 0.3, + "industry": 0.91 + }, + "mykolayiv-obnj": { + "oil": 0.51, + "iron": 0.14, + "food": 0.18, + "industry": 0.54 + }, + "mzimba-svso": { + "oil": 0.73, + "iron": 0.14, + "food": 0.73, + "industry": 0.18 + }, + "n-zi-comoe-uesl": { + "oil": 1, + "iron": 0.63, + "food": 0.17, + "industry": 0.73 + }, + "naama-swmc": { + "oil": 0.74, + "iron": 1, + "food": 0.5, + "industry": 0.88 + }, + "nagaland-yvrv": { + "oil": 0.14, + "iron": 0.98, + "food": 0.47, + "industry": 0.05 + }, + "nagano-kfji": { + "oil": 0.8, + "iron": 0.27, + "food": 0.88, + "industry": 0.5 + }, + "najran-wlss": { + "oil": 0.49, + "iron": 0.59, + "food": 0.74, + "industry": 0.33 + }, + "nakasongola-gjqa": { + "oil": 0.56, + "iron": 0.01, + "food": 0.49, + "industry": 0.53 + }, + "nakhon-ratchasima-kfip": { + "oil": 1, + "iron": 0.19, + "food": 0.75, + "industry": 0.38 + }, + "nakhon-sawan-ckvs": { + "oil": 0.34, + "iron": 0.97, + "food": 0.62, + "industry": 0.81 + }, + "nakhon-si-thammarat-utgo": { + "oil": 0.45, + "iron": 0.68, + "food": 0.26, + "industry": 0.83 + }, + "namibe-mitv": { + "oil": 0.65, + "iron": 1, + "food": 0.34, + "industry": 0.98 + }, + "nampula-qyfx": { + "oil": 0.73, + "iron": 0.18, + "food": 0.6, + "industry": 0.35 + }, + "nan-kntk": { + "oil": 0.36, + "iron": 1, + "food": 0.68, + "industry": 0.96 + }, + "nana-grebizi-mcza": { + "oil": 0.16, + "iron": 0.8, + "food": 0.04, + "industry": 0 + }, + "nana-mambere-glnv": { + "oil": 0.47, + "iron": 0.76, + "food": 0.86, + "industry": 0.18 + }, + "napak-yzyn": { + "oil": 0.93, + "iron": 0.65, + "food": 0.4, + "industry": 0.46 + }, + "narino-osue": { + "oil": 0.44, + "iron": 0.33, + "food": 0.55, + "industry": 1 + }, + "naryn-eilp": { + "oil": 0.75, + "iron": 0.7, + "food": 0.71, + "industry": 0.31 + }, + "nassarawa-mrzh": { + "oil": 0.16, + "iron": 0.45, + "food": 0.67, + "industry": 0.44 + }, + "nationalparken-menh": { + "oil": 0.8, + "iron": 1, + "food": 1, + "industry": 0.55 + }, + "navoi-ahpf": { + "oil": 0.66, + "iron": 1, + "food": 1, + "industry": 0.29 + }, + "nayarit-chkm": { + "oil": 1, + "iron": 1, + "food": 0.6, + "industry": 0.39 + }, + "nebraska-wikv": { + "oil": 0.24, + "iron": 0.51, + "food": 0.51, + "industry": 0.82 + }, + "neembucu-cfml": { + "oil": 0.76, + "iron": 0.22, + "food": 0.87, + "industry": 0.35 + }, + "negros-occidental-erlu": { + "oil": 0.82, + "iron": 0.4, + "food": 0.55, + "industry": 0.78 + }, + "nenets-qyga": { + "oil": 0.46, + "iron": 0.11, + "food": 0.97, + "industry": 0.87 + }, + "neuquen-yvne": { + "oil": 0.76, + "iron": 0.17, + "food": 0.08, + "industry": 0.15 + }, + "nevada-uekc": { + "oil": 0.62, + "iron": 0.87, + "food": 0.93, + "industry": 0.9 + }, + "new-brunswick-wcni": { + "oil": 0.6, + "iron": 0.23, + "food": 0.27, + "industry": 1 + }, + "new-earth-eikt": { + "oil": 0.6, + "iron": 0.56, + "food": 0.91, + "industry": 0.66 + }, + "new-hampshire-koki": { + "oil": 0.74, + "iron": 0.77, + "food": 0.78, + "industry": 0.8 + }, + "new-jersey-wlkg": { + "oil": 0.14, + "iron": 0.93, + "food": 0.16, + "industry": 0.53 + }, + "new-mexico-awkn": { + "oil": 0.03, + "iron": 0.92, + "food": 0.27, + "industry": 0.03 + }, + "new-south-wales-guah": { + "oil": 0.3, + "iron": 0.42, + "food": 0.77, + "industry": 0.43 + }, + "new-taipei-city-wbtm": { + "oil": 0.7, + "iron": 0.93, + "food": 0.98, + "industry": 0.78 + }, + "new-york-cqkt": { + "oil": 0.97, + "iron": 0.26, + "food": 0.51, + "industry": 0.37 + }, + "newfoundland-and-labrador-kmno": { + "oil": 0.87, + "iron": 0.75, + "food": 0.71, + "industry": 0.5 + }, + "nghe-an-ifec": { + "oil": 0.52, + "iron": 0.22, + "food": 0.67, + "industry": 0.37 + }, + "ngounie-atwh": { + "oil": 0.74, + "iron": 0.27, + "food": 0.36, + "industry": 0.57 + }, + "niari-svpz": { + "oil": 0.39, + "iron": 0.22, + "food": 0.95, + "industry": 0.09 + }, + "niassa-eefk": { + "oil": 0.63, + "iron": 0.14, + "food": 0.49, + "industry": 0.08 + }, + "nicosia-gzli": { + "oil": 0.01, + "iron": 0.45, + "food": 0.4, + "industry": 0.21 + }, + "niederosterreich-uapp": { + "oil": 0.54, + "iron": 0.81, + "food": 0.97, + "industry": 0.2 + }, + "niedersachsen-vxfc": { + "oil": 0.62, + "iron": 0.37, + "food": 0.42, + "industry": 1 + }, + "niger-qfzz": { + "oil": 0.71, + "iron": 0.46, + "food": 0.31, + "industry": 0.19 + }, + "niigata-idhx": { + "oil": 0.68, + "iron": 0.45, + "food": 0.39, + "industry": 0.32 + }, + "niksic-mcna": { + "oil": 0.08, + "iron": 0.02, + "food": 0.21, + "industry": 0.32 + }, + "nimba-xaov": { + "oil": 0.84, + "iron": 0.87, + "food": 0.77, + "industry": 0.98 + }, + "nimroz-eoll": { + "oil": 0.92, + "iron": 0.7, + "food": 0.28, + "industry": 0.02 + }, + "ninawa-bhig": { + "oil": 0.65, + "iron": 0.53, + "food": 1, + "industry": 0.62 + }, + "ningxia-kwbm": { + "oil": 1, + "iron": 0.54, + "food": 0.24, + "industry": 0.92 + }, + "nitriansky-muds": { + "oil": 1, + "iron": 0.72, + "food": 0.97, + "industry": 0.76 + }, + "nizhegorod-clce": { + "oil": 0.6, + "iron": 0.85, + "food": 0.92, + "industry": 0.74 + }, + "njombe-qvvy": { + "oil": 0.32, + "iron": 1, + "food": 0.17, + "industry": 0.37 + }, + "nkhata-bay-sgvt": { + "oil": 1, + "iron": 0.6, + "food": 0.94, + "industry": 0.27 + }, + "noord-holland-otrk": { + "oil": 0.09, + "iron": 0.47, + "food": 0.52, + "industry": 0.66 + }, + "nord-gkzb": { + "oil": 0.14, + "iron": 0.31, + "food": 0.56, + "industry": 0.14 + }, + "nord-kivu-gxmp": { + "oil": 0.37, + "iron": 0.98, + "food": 0.67, + "industry": 0.61 + }, + "nord-ouest-yvzz": { + "oil": 0.2, + "iron": 1, + "food": 0.82, + "industry": 1 + }, + "nord-trondelag-kyan": { + "oil": 0.64, + "iron": 0.48, + "food": 0.25, + "industry": 1 + }, + "nord-wofd": { + "oil": 0.1, + "iron": 0.25, + "food": 0.03, + "industry": 0.61 + }, + "nordland-gaao": { + "oil": 0.12, + "iron": 0.21, + "food": 0.21, + "industry": 0.9 + }, + "nordrhein-westfalen-hafe": { + "oil": 0.21, + "iron": 0.65, + "food": 0.82, + "industry": 0.52 + }, + "nordurland-eystra-kbfi": { + "oil": 0.67, + "iron": 0.29, + "food": 0.48, + "industry": 0.45 + }, + "nordurland-vestra-safh": { + "oil": 1, + "iron": 0.69, + "food": 0.78, + "industry": 0.02 + }, + "norrbotten-gqvp": { + "oil": 1, + "iron": 0.2, + "food": 0.8, + "industry": 1 + }, + "norte-de-santander-svgs": { + "oil": 0.86, + "iron": 0.23, + "food": 0.96, + "industry": 0.36 + }, + "north-andros-dagc": { + "oil": 0.46, + "iron": 0.96, + "food": 0.21, + "industry": 0.97 + }, + "north-carolina-ozkp": { + "oil": 0.41, + "iron": 0.5, + "food": 0.66, + "industry": 0.73 + }, + "north-chungcheong-kvoj": { + "oil": 0.56, + "iron": 0.11, + "food": 0.99, + "industry": 0.32 + }, + "north-dakota-ehku": { + "oil": 0.36, + "iron": 0.44, + "food": 0.28, + "industry": 0.13 + }, + "north-darfur-mfpn": { + "oil": 0.08, + "iron": 0.54, + "food": 0.29, + "industry": 0.22 + }, + "north-eastern-ewzp": { + "oil": 0.75, + "iron": 0.91, + "food": 0.51, + "industry": 0.96 + }, + "north-eleuthera-nwgq": { + "oil": 0.27, + "iron": 0.62, + "food": 0.58, + "industry": 0.8 + }, + "north-gyeongsang-mpof": { + "oil": 0.18, + "iron": 0.58, + "food": 0.79, + "industry": 0.94 + }, + "north-karelia-mhnr": { + "oil": 0.42, + "iron": 0.13, + "food": 0.54, + "industry": 0.57 + }, + "north-kazakhstan-kdzy": { + "oil": 1, + "iron": 0.33, + "food": 0.33, + "industry": 0.07 + }, + "north-khorasan-yfqe": { + "oil": 0.28, + "iron": 0.91, + "food": 0.77, + "industry": 0.41 + }, + "north-kordufan-kmzw": { + "oil": 0.96, + "iron": 1, + "food": 0.18, + "industry": 0.32 + }, + "north-ossetia-arkb": { + "oil": 0.6, + "iron": 1, + "food": 0.98, + "industry": 0.98 + }, + "north-solomons-yvrf": { + "oil": 0.97, + "iron": 0.15, + "food": 0.91, + "industry": 0.65 + }, + "north-west-ispe": { + "oil": 0.57, + "iron": 0.35, + "food": 0.96, + "industry": 0.03 + }, + "north-west-qhdz": { + "oil": 0.64, + "iron": 0.57, + "food": 0.04, + "industry": 0.24 + }, + "north-western-uptr": { + "oil": 0.88, + "iron": 0.25, + "food": 1, + "industry": 1 + }, + "north-yorkshire-qalk": { + "oil": 0.17, + "iron": 0.38, + "food": 0.12, + "industry": 0.02 + }, + "northern-areas-mevu": { + "oil": 0.52, + "iron": 0.14, + "food": 0.18, + "industry": 0.55 + }, + "northern-bahr-el-ghazal-civj": { + "oil": 0.23, + "iron": 0.49, + "food": 0.87, + "industry": 0.25 + }, + "northern-cape-glpq": { + "oil": 0.33, + "iron": 0.85, + "food": 0.25, + "industry": 0.99 + }, + "northern-cyprus-mvnb": { + "oil": 0.79, + "iron": 0.58, + "food": 0.73, + "industry": 1 + }, + "northern-eotq": { + "oil": 0.03, + "iron": 0.8, + "food": 0.49, + "industry": 0.75 + }, + "northern-ibne": { + "oil": 0.19, + "iron": 0.51, + "food": 0.38, + "industry": 0.49 + }, + "northern-ostrobothnia-eins": { + "oil": 0.21, + "iron": 0, + "food": 0.01, + "industry": 0.17 + }, + "northern-qinm": { + "oil": 0.22, + "iron": 0.7, + "food": 0.23, + "industry": 0.52 + }, + "northern-savonia-aknt": { + "oil": 0.18, + "iron": 0.54, + "food": 0.57, + "industry": 0.66 + }, + "northern-swud": { + "oil": 0.12, + "iron": 0.9, + "food": 0.01, + "industry": 0.65 + }, + "northern-territory-ylns": { + "oil": 0.62, + "iron": 0.7, + "food": 0.34, + "industry": 0.64 + }, + "northern-yiap": { + "oil": 0.47, + "iron": 0.2, + "food": 0.72, + "industry": 0.12 + }, + "northland-aqhd": { + "oil": 0.55, + "iron": 0.68, + "food": 0.63, + "industry": 0.71 + }, + "northwest-territories-gynw": { + "oil": 0.02, + "iron": 0.28, + "food": 0.31, + "industry": 0.17 + }, + "nova-scotia-ndnz": { + "oil": 0.7, + "iron": 1, + "food": 0.55, + "industry": 0.29 + }, + "novgorod-cvlo": { + "oil": 0.69, + "iron": 0.7, + "food": 1, + "industry": 0.46 + }, + "novosibirsk-mivi": { + "oil": 0.52, + "iron": 0.79, + "food": 0.01, + "industry": 0.27 + }, + "nuble-wmop": { + "oil": 0.27, + "iron": 0.25, + "food": 0.34, + "industry": 0.27 + }, + "nueva-ecija-ilyq": { + "oil": 0.04, + "iron": 0.36, + "food": 0.65, + "industry": 0.68 + }, + "nuevo-leon-rfly": { + "oil": 0.72, + "iron": 0.74, + "food": 0.49, + "industry": 0.63 + }, + "nugaal-gznd": { + "oil": 0.97, + "iron": 0.85, + "food": 0.6, + "industry": 0.12 + }, + "nunavut-banx": { + "oil": 0.17, + "iron": 0.56, + "food": 0.75, + "industry": 0.69 + }, + "nuristan-ofkf": { + "oil": 0.12, + "iron": 0.25, + "food": 0.77, + "industry": 0.41 + }, + "nusa-tenggara-barat-ywlq": { + "oil": 0.87, + "iron": 0.03, + "food": 0.14, + "industry": 0.05 + }, + "nusa-tenggara-timur-iflm": { + "oil": 0.93, + "iron": 0.05, + "food": 0.57, + "industry": 0.95 + }, + "nwoya-payo": { + "oil": 0.25, + "iron": 0.59, + "food": 0.56, + "industry": 0.18 + }, + "nyanga-suwi": { + "oil": 0.21, + "iron": 0.03, + "food": 0.37, + "industry": 0.74 + }, + "nyanza-wpnv": { + "oil": 0.89, + "iron": 0.35, + "food": 1, + "industry": 0.33 + }, + "oaxaca-vcjz": { + "oil": 0.91, + "iron": 0.93, + "food": 0.77, + "industry": 0.24 + }, + "oberosterreich-mbpq": { + "oil": 0.66, + "iron": 0.37, + "food": 0.38, + "industry": 0.94 + }, + "odessa-kpqz": { + "oil": 0.3, + "iron": 0.01, + "food": 0.07, + "industry": 0.7 + }, + "odisha-uxvk": { + "oil": 0.05, + "iron": 0.65, + "food": 0.6, + "industry": 0.7 + }, + "ogooue-ivindo-mwwj": { + "oil": 0.66, + "iron": 0.56, + "food": 0.32, + "industry": 0.01 + }, + "ogooue-lolo-cxwk": { + "oil": 0.26, + "iron": 0.94, + "food": 1, + "industry": 0.93 + }, + "ogooue-maritime-ulwt": { + "oil": 0.8, + "iron": 1, + "food": 0.23, + "industry": 0.46 + }, + "ogun-soba": { + "oil": 0.8, + "iron": 0.8, + "food": 0.66, + "industry": 0.86 + }, + "ohangwena-ialq": { + "oil": 0.65, + "iron": 0.55, + "food": 1, + "industry": 0.78 + }, + "ohio-kgmu": { + "oil": 0.88, + "iron": 0.67, + "food": 1, + "industry": 0.56 + }, + "oio-eyrz": { + "oil": 0.25, + "iron": 0.57, + "food": 0.72, + "industry": 0.18 + }, + "oita-asvg": { + "oil": 0.11, + "iron": 0.33, + "food": 1, + "industry": 0.89 + }, + "okayama-mymn": { + "oil": 0.61, + "iron": 0.22, + "food": 0.41, + "industry": 0.9 + }, + "okinawa-cwvj": { + "oil": 0.52, + "iron": 0.62, + "food": 0.29, + "industry": 0.39 + }, + "oklahoma-cimv": { + "oil": 0.73, + "iron": 0.78, + "food": 0.42, + "industry": 1 + }, + "olancho-qasq": { + "oil": 1, + "iron": 0.98, + "food": 0.05, + "industry": 0.19 + }, + "omagh-gocy": { + "oil": 0.78, + "iron": 0.97, + "food": 0.04, + "industry": 0.04 + }, + "omaheke-ablr": { + "oil": 0.37, + "iron": 0.52, + "food": 0.49, + "industry": 1 + }, + "ombella-m-poko-iklq": { + "oil": 0.48, + "iron": 0.62, + "food": 1, + "industry": 0.03 + }, + "omnogovi-axqk": { + "oil": 0.18, + "iron": 0.87, + "food": 0.45, + "industry": 0.34 + }, + "omsk-aufy": { + "oil": 0.8, + "iron": 0.19, + "food": 0.23, + "industry": 0.72 + }, + "omusati-gtlm": { + "oil": 0.41, + "iron": 0.62, + "food": 0.57, + "industry": 1 + }, + "ondo-aabr": { + "oil": 0.98, + "iron": 0.55, + "food": 0.51, + "industry": 1 + }, + "ontario-bzqu": { + "oil": 0.32, + "iron": 0.45, + "food": 0.31, + "industry": 0.28 + }, + "oppland-slyc": { + "oil": 0.11, + "iron": 0.81, + "food": 0.4, + "industry": 0.71 + }, + "oregon-qznu": { + "oil": 0.93, + "iron": 1, + "food": 0.47, + "industry": 0.3 + }, + "orel-svfw": { + "oil": 0.53, + "iron": 0.34, + "food": 0.09, + "industry": 0.65 + }, + "orellana-cmuh": { + "oil": 0.98, + "iron": 1, + "food": 0.14, + "industry": 0.14 + }, + "orenburg-nkfp": { + "oil": 0.55, + "iron": 0.27, + "food": 0.98, + "industry": 0.57 + }, + "orense-aqch": { + "oil": 0.43, + "iron": 0.07, + "food": 0.87, + "industry": 0.81 + }, + "oriental-kiep": { + "oil": 0.34, + "iron": 0.31, + "food": 0.9, + "industry": 0.49 + }, + "orientale-scpz": { + "oil": 0.27, + "iron": 0.62, + "food": 0.73, + "industry": 0.06 + }, + "orne-jeiv": { + "oil": 0.21, + "iron": 0.39, + "food": 0.42, + "industry": 0.83 + }, + "oromiya-otzl": { + "oil": 0.24, + "iron": 0.85, + "food": 0.44, + "industry": 0.02 + }, + "oruro-qktm": { + "oil": 0.66, + "iron": 0.73, + "food": 0.91, + "industry": 0.21 + }, + "osh-vjlq": { + "oil": 0.45, + "iron": 0.39, + "food": 0.47, + "industry": 0.27 + }, + "oshikoto-cvln": { + "oil": 0.01, + "iron": 1, + "food": 0.14, + "industry": 0.88 + }, + "osjecko-baranjska-ivlu": { + "oil": 0.69, + "iron": 0.5, + "food": 0.88, + "industry": 0.54 + }, + "ostergotland-ohui": { + "oil": 1, + "iron": 0.6, + "food": 0.82, + "industry": 0.07 + }, + "osun-qhbm": { + "oil": 0.82, + "iron": 0.61, + "food": 0.38, + "industry": 1 + }, + "otago-ctsh": { + "oil": 0, + "iron": 0.92, + "food": 0.88, + "industry": 0 + }, + "otjozondjupa-yuld": { + "oil": 0.53, + "iron": 0.3, + "food": 0.45, + "industry": 1 + }, + "ouaddai-ukka": { + "oil": 1, + "iron": 1, + "food": 0.16, + "industry": 1 + }, + "ouaka-mmrt": { + "oil": 0.7, + "iron": 0.1, + "food": 0.25, + "industry": 0.96 + }, + "ouargla-wxdg": { + "oil": 1, + "iron": 0.06, + "food": 0.11, + "industry": 0.25 + }, + "oudalan-ooyt": { + "oil": 0.54, + "iron": 0.84, + "food": 0.6, + "industry": 0.39 + }, + "oudomxai-trgc": { + "oil": 0.42, + "iron": 0.66, + "food": 0.32, + "industry": 0.12 + }, + "oued-el-dahab-gwhv": { + "oil": 1, + "iron": 0.72, + "food": 0.92, + "industry": 1 + }, + "ouest-kdbx": { + "oil": 0.55, + "iron": 1, + "food": 0.12, + "industry": 0.61 + }, + "ouest-wjof": { + "oil": 0.42, + "iron": 0.58, + "food": 0.33, + "industry": 0.34 + }, + "ouham-mnot": { + "oil": 0.59, + "iron": 0.52, + "food": 0.7, + "industry": 0 + }, + "ouham-pende-obpq": { + "oil": 0.49, + "iron": 0.46, + "food": 0.58, + "industry": 0.81 + }, + "ovorhangay-onqe": { + "oil": 0.19, + "iron": 0.84, + "food": 0.32, + "industry": 0.6 + }, + "oxfordshire-qxcr": { + "oil": 0.31, + "iron": 0.01, + "food": 0.04, + "industry": 0.94 + }, + "oyo-ksbc": { + "oil": 0.67, + "iron": 0.26, + "food": 0.45, + "industry": 0.53 + }, + "p-yongan-bukto-ipdv": { + "oil": 0.58, + "iron": 0.69, + "food": 0.88, + "industry": 0.72 + }, + "p-yongan-namdo-uodu": { + "oil": 0.71, + "iron": 0.05, + "food": 0.28, + "industry": 0.46 + }, + "pahang-ihup": { + "oil": 0.27, + "iron": 1, + "food": 0.03, + "industry": 0.42 + }, + "paijat-hame-olnu": { + "oil": 0.65, + "iron": 0.25, + "food": 0.35, + "industry": 0.67 + }, + "paktika-wbrf": { + "oil": 0.58, + "iron": 1, + "food": 0.7, + "industry": 1 + }, + "paktya-opvd": { + "oil": 0.03, + "iron": 1, + "food": 0.64, + "industry": 0.01 + }, + "palawan-imjh": { + "oil": 0.03, + "iron": 1, + "food": 0.06, + "industry": 0.25 + }, + "palencia-qubl": { + "oil": 0.68, + "iron": 0.31, + "food": 0.46, + "industry": 0.2 + }, + "palermo-cprw": { + "oil": 0.71, + "iron": 0.83, + "food": 0.1, + "industry": 0.59 + }, + "panama-oriu": { + "oil": 0.73, + "iron": 0.62, + "food": 0.73, + "industry": 0.36 + }, + "pando-uitl": { + "oil": 0.93, + "iron": 1, + "food": 0.35, + "industry": 1 + }, + "panevezio-cpal": { + "oil": 1, + "iron": 0.15, + "food": 0.37, + "industry": 0.18 + }, + "pangasinan-cmhx": { + "oil": 0.23, + "iron": 0.13, + "food": 0.65, + "industry": 0.12 + }, + "papua-barat-mady": { + "oil": 0.83, + "iron": 0.7, + "food": 0.73, + "industry": 0.23 + }, + "papua-rydx": { + "oil": 1, + "iron": 0.16, + "food": 0.94, + "industry": 0.31 + }, + "para-mmiu": { + "oil": 0.2, + "iron": 0.4, + "food": 0.4, + "industry": 0.85 + }, + "para-scsi": { + "oil": 0.8, + "iron": 0.36, + "food": 0.96, + "industry": 0.18 + }, + "paracel-islands-yftc": { + "oil": 0.65, + "iron": 0.62, + "food": 0.78, + "industry": 0.55 + }, + "paraguari-vemt": { + "oil": 0.75, + "iron": 0.66, + "food": 0.62, + "industry": 0.02 + }, + "paraiba-aniv": { + "oil": 0.45, + "iron": 0.53, + "food": 0.88, + "industry": 0.84 + }, + "parana-arjl": { + "oil": 0.56, + "iron": 0.23, + "food": 0.16, + "industry": 0.63 + }, + "parma-uqrn": { + "oil": 0.46, + "iron": 0.24, + "food": 0.33, + "industry": 0.62 + }, + "pas-de-calais-egiw": { + "oil": 0.67, + "iron": 0.15, + "food": 0.81, + "industry": 1 + }, + "pasco-ydtb": { + "oil": 1, + "iron": 0.45, + "food": 0.63, + "industry": 1 + }, + "pastaza-gdus": { + "oil": 0.49, + "iron": 0.3, + "food": 0.86, + "industry": 1 + }, + "pavlodar-abzq": { + "oil": 0.11, + "iron": 0.93, + "food": 0.51, + "industry": 0.38 + }, + "paysandu-ikte": { + "oil": 0.72, + "iron": 0.64, + "food": 0.6, + "industry": 0.12 + }, + "pechora-qwhs": { + "oil": 0.11, + "iron": 0.16, + "food": 1, + "industry": 0.04 + }, + "peloponnisos-wqyw": { + "oil": 1, + "iron": 0.52, + "food": 1, + "industry": 0.43 + }, + "penghu-oghr": { + "oil": 0.86, + "iron": 0.81, + "food": 1, + "industry": 0.73 + }, + "pennsylvania-ylkc": { + "oil": 0.17, + "iron": 0.42, + "food": 0.57, + "industry": 0.88 + }, + "penza-mzew": { + "oil": 0.79, + "iron": 0.45, + "food": 0.21, + "industry": 0.21 + }, + "perak-sxuz": { + "oil": 0.36, + "iron": 0.41, + "food": 0.17, + "industry": 0.52 + }, + "perm-cphx": { + "oil": 0.26, + "iron": 0.23, + "food": 0.67, + "industry": 0.97 + }, + "pernambuco-kfiq": { + "oil": 0.63, + "iron": 0.82, + "food": 0.93, + "industry": 0.97 + }, + "perugia-ozrc": { + "oil": 0.36, + "iron": 1, + "food": 0.74, + "industry": 0.93 + }, + "pest-akxn": { + "oil": 0.51, + "iron": 0.16, + "food": 0.01, + "industry": 0.73 + }, + "peten-kent": { + "oil": 0.74, + "iron": 0.17, + "food": 0.13, + "industry": 0.83 + }, + "phetchabun-mcvn": { + "oil": 0.95, + "iron": 0.06, + "food": 0.29, + "industry": 0.61 + }, + "phetchaburi-klyv": { + "oil": 0.86, + "iron": 0.01, + "food": 0.53, + "industry": 0.2 + }, + "phitsanulok-agvp": { + "oil": 0.71, + "iron": 0.01, + "food": 0.36, + "industry": 0.51 + }, + "phongsali-okhy": { + "oil": 0.28, + "iron": 0.36, + "food": 0.74, + "industry": 0.41 + }, + "phra-nakhon-si-ayutthaya-eddh": { + "oil": 0.69, + "iron": 0.74, + "food": 0.78, + "industry": 0.5 + }, + "piaui-icjc": { + "oil": 0.81, + "iron": 1, + "food": 0.41, + "industry": 0.1 + }, + "pichincha-wrub": { + "oil": 0.7, + "iron": 0.32, + "food": 0.02, + "industry": 0.56 + }, + "pinar-del-rio-ejbc": { + "oil": 0.96, + "iron": 0.93, + "food": 0.3, + "industry": 0.61 + }, + "pirkanmaa-cenp": { + "oil": 1, + "iron": 0.08, + "food": 0.49, + "industry": 0.29 + }, + "pita-rhov": { + "oil": 0.75, + "iron": 0.06, + "food": 0.92, + "industry": 0.03 + }, + "piura-whve": { + "oil": 1, + "iron": 0.7, + "food": 0.76, + "industry": 0.6 + }, + "plateau-oako": { + "oil": 0.82, + "iron": 0, + "food": 0.35, + "industry": 0.87 + }, + "plateaux-kqwn": { + "oil": 0.25, + "iron": 0.99, + "food": 0.17, + "industry": 0.2 + }, + "plateaux-myrm": { + "oil": 0.76, + "iron": 0.82, + "food": 0.28, + "industry": 1 + }, + "plovdiv-euus": { + "oil": 0.76, + "iron": 0.66, + "food": 0.75, + "industry": 0.41 + }, + "plzensky-ysxk": { + "oil": 0.39, + "iron": 0.16, + "food": 0.31, + "industry": 0.67 + }, + "podlachian-amui": { + "oil": 0.12, + "iron": 0.35, + "food": 0.26, + "industry": 1 + }, + "podujevo-ozes": { + "oil": 0.79, + "iron": 0.45, + "food": 0.7, + "industry": 0.42 + }, + "poltava-usqb": { + "oil": 0.33, + "iron": 0.41, + "food": 0.64, + "industry": 0.96 + }, + "pomeranian-saur": { + "oil": 0.3, + "iron": 0.15, + "food": 0.26, + "industry": 0.17 + }, + "pomeroon-supenaam-iooq": { + "oil": 0.38, + "iron": 0.07, + "food": 0.03, + "industry": 0.32 + }, + "poni-upoo": { + "oil": 0.53, + "iron": 0.83, + "food": 0.98, + "industry": 0.32 + }, + "pool-umwl": { + "oil": 0.43, + "iron": 0.41, + "food": 0.51, + "industry": 0 + }, + "portuguesa-epqi": { + "oil": 0.66, + "iron": 0.41, + "food": 0.75, + "industry": 0.73 + }, + "potaro-siparuni-qaor": { + "oil": 0.53, + "iron": 0.63, + "food": 1, + "industry": 0.84 + }, + "potenza-yerf": { + "oil": 0.6, + "iron": 0.71, + "food": 0.86, + "industry": 0.68 + }, + "potosi-iltd": { + "oil": 1, + "iron": 0.75, + "food": 0.07, + "industry": 0.59 + }, + "pouthisat-lcor": { + "oil": 0.18, + "iron": 0.56, + "food": 0.94, + "industry": 0.26 + }, + "powys-zcfq": { + "oil": 0.47, + "iron": 0.99, + "food": 0.11, + "industry": 0.84 + }, + "preah-vihear-xsol": { + "oil": 0.7, + "iron": 0.46, + "food": 0.53, + "industry": 0.58 + }, + "presidente-hayes-abmi": { + "oil": 0.83, + "iron": 1, + "food": 1, + "industry": 0.63 + }, + "presov-kpwz": { + "oil": 0.42, + "iron": 0.54, + "food": 1, + "industry": 0.64 + }, + "prey-veng-qaoq": { + "oil": 0.59, + "iron": 0.56, + "food": 0.32, + "industry": 1 + }, + "primor-ye-edix": { + "oil": 0.84, + "iron": 0.77, + "food": 0.03, + "industry": 0.39 + }, + "pskov-kakm": { + "oil": 0.53, + "iron": 0.4, + "food": 0.57, + "industry": 0.04 + }, + "puebla-apfj": { + "oil": 0.51, + "iron": 0.3, + "food": 0.37, + "industry": 0.47 + }, + "puerto-rico-qqlt": { + "oil": 0.04, + "iron": 0.55, + "food": 0.79, + "industry": 0.97 + }, + "punjab-ghlp": { + "oil": 0.38, + "iron": 0.9, + "food": 0.65, + "industry": 1 + }, + "punjab-kjkb": { + "oil": 0.39, + "iron": 0.19, + "food": 0.05, + "industry": 0.6 + }, + "puno-vaqi": { + "oil": 0.13, + "iron": 0.95, + "food": 0.71, + "industry": 0.18 + }, + "puntarenas-evmt": { + "oil": 0.48, + "iron": 1, + "food": 0.53, + "industry": 0.94 + }, + "putumayo-ksux": { + "oil": 0.35, + "iron": 0.22, + "food": 1, + "industry": 0.04 + }, + "pwani-qxtg": { + "oil": 0.46, + "iron": 0.9, + "food": 0.55, + "industry": 0.6 + }, + "qaasuitsup-kommunia-kawz": { + "oil": 0.39, + "iron": 0.33, + "food": 0.77, + "industry": 0.21 + }, + "qaraghandy-khxs": { + "oil": 1, + "iron": 0.69, + "food": 0.65, + "industry": 0.17 + }, + "qazvin-crno": { + "oil": 1, + "iron": 0.54, + "food": 0.02, + "industry": 0.02 + }, + "qeqqata-kommunia-mhwd": { + "oil": 0.64, + "iron": 0.15, + "food": 0.72, + "industry": 0.6 + }, + "qinghai-cnbf": { + "oil": 1, + "iron": 0.47, + "food": 0.33, + "industry": 0.73 + }, + "qom-knnc": { + "oil": 0.32, + "iron": 0.43, + "food": 0.68, + "industry": 0.13 + }, + "qostanay-qwtp": { + "oil": 0.95, + "iron": 0.02, + "food": 0.69, + "industry": 0.3 + }, + "quang-binh-wpei": { + "oil": 0.8, + "iron": 0.19, + "food": 1, + "industry": 0.48 + }, + "quang-nam-cneh": { + "oil": 1, + "iron": 1, + "food": 0.06, + "industry": 0.29 + }, + "quba-nxpp": { + "oil": 0.17, + "iron": 0.49, + "food": 0.64, + "industry": 0.58 + }, + "quebec-yegk": { + "oil": 1, + "iron": 0.75, + "food": 0.85, + "industry": 0.9 + }, + "queensland-opqa": { + "oil": 0.87, + "iron": 0.81, + "food": 0.99, + "industry": 1 + }, + "queretaro-mpre": { + "oil": 0.88, + "iron": 0.74, + "food": 0.7, + "industry": 0.71 + }, + "quezon-scfg": { + "oil": 0.47, + "iron": 0.72, + "food": 0.2, + "industry": 0.9 + }, + "quintana-roo-ieho": { + "oil": 0.19, + "iron": 0.57, + "food": 0.96, + "industry": 0.26 + }, + "qyzylorda-emfx": { + "oil": 0.6, + "iron": 0.37, + "food": 0.34, + "industry": 0.65 + }, + "ragged-island-fprn": { + "oil": 0.6, + "iron": 0.79, + "food": 0.45, + "industry": 0.29 + }, + "rajasthan-sfpr": { + "oil": 0.87, + "iron": 0.96, + "food": 0.44, + "industry": 1 + }, + "rajshahi-usrv": { + "oil": 0.44, + "iron": 0.96, + "food": 0.96, + "industry": 0.84 + }, + "rakhine-wotp": { + "oil": 0.14, + "iron": 0.83, + "food": 1, + "industry": 0.87 + }, + "rangpur-drru": { + "oil": 0.58, + "iron": 0.43, + "food": 0.43, + "industry": 0.73 + }, + "rapti-ewpq": { + "oil": 0.69, + "iron": 0.54, + "food": 0.45, + "industry": 0.09 + }, + "ratnapura-llsf": { + "oil": 0.96, + "iron": 0.43, + "food": 0.99, + "industry": 1 + }, + "razavi-khorasan-cdqd": { + "oil": 0.93, + "iron": 0.72, + "food": 0.47, + "industry": 0.04 + }, + "red-sea-zspo": { + "oil": 0.16, + "iron": 0.21, + "food": 0.92, + "industry": 0.98 + }, + "region-metropolitana-de-santiago-qwdi": { + "oil": 0.16, + "iron": 0.05, + "food": 0.08, + "industry": 0.03 + }, + "relizane-ybmf": { + "oil": 0.73, + "iron": 0.21, + "food": 0.17, + "industry": 0.9 + }, + "rennell-and-bellona-amuo": { + "oil": 0.1, + "iron": 0.01, + "food": 0.01, + "industry": 0.1 + }, + "rezeknes-mmcq": { + "oil": 0.1, + "iron": 0.59, + "food": 1, + "industry": 0.48 + }, + "rheinland-pfalz-cfwr": { + "oil": 0.29, + "iron": 0.83, + "food": 0.83, + "industry": 0.71 + }, + "riau-zdhp": { + "oil": 0.09, + "iron": 0.94, + "food": 1, + "industry": 0.06 + }, + "rif-dimashq-smjb": { + "oil": 0.03, + "iron": 1, + "food": 0.81, + "industry": 0.71 + }, + "rift-valley-wlpc": { + "oil": 1, + "iron": 0.05, + "food": 0.02, + "industry": 0.9 + }, + "rio-claro-mayaro-ojxf": { + "oil": 0.44, + "iron": 0.96, + "food": 0.8, + "industry": 0.39 + }, + "rio-de-janeiro-mhoj": { + "oil": 0.46, + "iron": 0.51, + "food": 0.96, + "industry": 0.08 + }, + "rio-grande-do-norte-knon": { + "oil": 0.76, + "iron": 0.14, + "food": 0.29, + "industry": 0.58 + }, + "rio-grande-do-sul-auoi": { + "oil": 0.46, + "iron": 0.1, + "food": 0.16, + "industry": 0.42 + }, + "rio-negro-qxnf": { + "oil": 1, + "iron": 0.76, + "food": 0.45, + "industry": 0.01 + }, + "river-gee-uqio": { + "oil": 0.7, + "iron": 0.59, + "food": 0.21, + "industry": 1 + }, + "river-nile-gpnj": { + "oil": 0.09, + "iron": 0.51, + "food": 0.14, + "industry": 1 + }, + "rivers-esqx": { + "oil": 0.28, + "iron": 0.13, + "food": 0.31, + "industry": 0.17 + }, + "rivne-ekqw": { + "oil": 0.08, + "iron": 0.38, + "food": 0.73, + "industry": 0.94 + }, + "rocha-ymzo": { + "oil": 0.78, + "iron": 0.45, + "food": 0.47, + "industry": 0.2 + }, + "roi-et-gerl": { + "oil": 0.32, + "iron": 0.19, + "food": 0.13, + "industry": 0.34 + }, + "roma-sawi": { + "oil": 0.39, + "iron": 1, + "food": 0.15, + "industry": 0.73 + }, + "rondonia-gpoo": { + "oil": 0.44, + "iron": 0.71, + "food": 0.79, + "industry": 0.54 + }, + "roraima-itoh": { + "oil": 0.57, + "iron": 0.4, + "food": 0.39, + "industry": 0.98 + }, + "roscommon-ytzq": { + "oil": 0.46, + "iron": 0.63, + "food": 0.63, + "industry": 0.65 + }, + "rostov-ylrd": { + "oil": 1, + "iron": 1, + "food": 0.33, + "industry": 0.83 + }, + "rotanokiri-exoo": { + "oil": 0.11, + "iron": 0.75, + "food": 0.08, + "industry": 1 + }, + "rotuma-kdui": { + "oil": 0.64, + "iron": 0.83, + "food": 0.91, + "industry": 0.31 + }, + "rukwa-ygvp": { + "oil": 0.45, + "iron": 0.12, + "food": 1, + "industry": 1 + }, + "ruvuma-qivq": { + "oil": 0.28, + "iron": 0.62, + "food": 0.2, + "industry": 0.65 + }, + "ruyigi-kdjc": { + "oil": 1, + "iron": 1, + "food": 0.69, + "industry": 0.87 + }, + "ryanggang-ggfz": { + "oil": 0.97, + "iron": 0.32, + "food": 0.39, + "industry": 0.76 + }, + "ryazan-ggrj": { + "oil": 0.81, + "iron": 0.56, + "food": 0.56, + "industry": 0.58 + }, + "sa-dah-kvqv": { + "oil": 0.95, + "iron": 0.33, + "food": 1, + "industry": 0.29 + }, + "sa-kaeo-cufl": { + "oil": 0.44, + "iron": 0.72, + "food": 0.38, + "industry": 0.01 + }, + "saba-gckq": { + "oil": 0.12, + "iron": 0.04, + "food": 0.1, + "industry": 0.16 + }, + "sabah-knxa": { + "oil": 0.47, + "iron": 0.34, + "food": 0.8, + "industry": 0.22 + }, + "sabha-sukt": { + "oil": 0.3, + "iron": 0.67, + "food": 0.88, + "industry": 0.19 + }, + "sachsen-anhalt-arad": { + "oil": 0.75, + "iron": 0.48, + "food": 0.54, + "industry": 0.09 + }, + "sachsen-oiah": { + "oil": 0.37, + "iron": 0.54, + "food": 0.5, + "industry": 0.72 + }, + "sagaing-axrl": { + "oil": 1, + "iron": 0.58, + "food": 0.57, + "industry": 0.74 + }, + "sagarmatha-otrd": { + "oil": 0.53, + "iron": 0.77, + "food": 0.63, + "industry": 0.48 + }, + "saint-louis-iuhj": { + "oil": 0.36, + "iron": 0.71, + "food": 0.92, + "industry": 0.93 + }, + "sakha-yakutia-yxkf": { + "oil": 0.45, + "iron": 0.1, + "food": 0.21, + "industry": 0.08 + }, + "sakhalin-wlzc": { + "oil": 0.02, + "iron": 0.96, + "food": 0.7, + "industry": 1 + }, + "sakon-nakhon-qhrn": { + "oil": 0.47, + "iron": 0.75, + "food": 0.78, + "industry": 0.3 + }, + "sala-ad-din-simf": { + "oil": 0.71, + "iron": 0.2, + "food": 0.55, + "industry": 0.07 + }, + "salamanca-qrmw": { + "oil": 0.63, + "iron": 0.37, + "food": 0.9, + "industry": 0.04 + }, + "salamat-nrnf": { + "oil": 1, + "iron": 0.46, + "food": 0.63, + "industry": 1 + }, + "salta-uunu": { + "oil": 1, + "iron": 0.52, + "food": 0.6, + "industry": 0.37 + }, + "salto-aobp": { + "oil": 0.94, + "iron": 0.53, + "food": 0.7, + "industry": 0.17 + }, + "samangan-iybb": { + "oil": 0.36, + "iron": 0.73, + "food": 0.01, + "industry": 0.09 + }, + "samar-vdxo": { + "oil": 0.35, + "iron": 1, + "food": 0.67, + "industry": 1 + }, + "samara-koze": { + "oil": 0.29, + "iron": 0.49, + "food": 0.33, + "industry": 0.64 + }, + "samarkand-ansu": { + "oil": 0.16, + "iron": 0.04, + "food": 0.51, + "industry": 0.97 + }, + "samegrelo-zemo-svaneti-wjlp": { + "oil": 1, + "iron": 0.56, + "food": 1, + "industry": 0.72 + }, + "samsun-inzb": { + "oil": 0.17, + "iron": 0.32, + "food": 0.66, + "industry": 0.05 + }, + "san-andres-y-providencia-sbat": { + "oil": 0.49, + "iron": 0.94, + "food": 0.64, + "industry": 0.01 + }, + "san-jose-qcby": { + "oil": 0.16, + "iron": 0.04, + "food": 0.91, + "industry": 0.19 + }, + "san-juan-iczh": { + "oil": 0.03, + "iron": 1, + "food": 0.48, + "industry": 0.81 + }, + "san-juan-iind": { + "oil": 0.55, + "iron": 0.88, + "food": 0.01, + "industry": 1 + }, + "san-luis-amnp": { + "oil": 1, + "iron": 0.77, + "food": 0.32, + "industry": 0.75 + }, + "san-luis-potosi-wfta": { + "oil": 0.73, + "iron": 0.39, + "food": 0.56, + "industry": 0.39 + }, + "san-marcos-cvvw": { + "oil": 0.43, + "iron": 0.96, + "food": 0.41, + "industry": 0.02 + }, + "san-martin-orum": { + "oil": 0.18, + "iron": 0.61, + "food": 0.08, + "industry": 0.55 + }, + "san-pedro-qtmm": { + "oil": 0.3, + "iron": 0.24, + "food": 0.9, + "industry": 0.78 + }, + "san-salvador-kzur": { + "oil": 0.21, + "iron": 0.81, + "food": 0.29, + "industry": 0.51 + }, + "sana-a-ylqp": { + "oil": 0.4, + "iron": 0.85, + "food": 0.9, + "industry": 0.48 + }, + "sancti-spiritus-msbi": { + "oil": 0.11, + "iron": 0.4, + "food": 0.65, + "industry": 0.85 + }, + "sandaun-swut": { + "oil": 0.87, + "iron": 0.4, + "food": 1, + "industry": 0.87 + }, + "sangha-mbaere-mqfz": { + "oil": 0.72, + "iron": 0.24, + "food": 0.49, + "industry": 0.21 + }, + "sangha-oowm": { + "oil": 0.57, + "iron": 1, + "food": 0.74, + "industry": 0.54 + }, + "sanguie-skxs": { + "oil": 0.13, + "iron": 0.6, + "food": 0.01, + "industry": 0.24 + }, + "sanliurfa-imci": { + "oil": 0.42, + "iron": 0.1, + "food": 0.16, + "industry": 1 + }, + "sanma-yzht": { + "oil": 0.01, + "iron": 0.51, + "food": 1, + "industry": 0.97 + }, + "sanmatenga-alfl": { + "oil": 0.69, + "iron": 1, + "food": 1, + "industry": 1 + }, + "santa-barbara-qgiw": { + "oil": 0.57, + "iron": 0.11, + "food": 1, + "industry": 0.22 + }, + "santa-catarina-ourg": { + "oil": 0.72, + "iron": 0.2, + "food": 0.56, + "industry": 0.07 + }, + "santa-cruz-de-tenerife-ggog": { + "oil": 0.05, + "iron": 0.7, + "food": 0.03, + "industry": 0.32 + }, + "santa-cruz-kptg": { + "oil": 0.06, + "iron": 0.8, + "food": 0.28, + "industry": 0.76 + }, + "santa-cruz-mjnn": { + "oil": 0.5, + "iron": 0.94, + "food": 0.58, + "industry": 0.31 + }, + "santa-fe-iyng": { + "oil": 0.06, + "iron": 0.17, + "food": 0.12, + "industry": 0.91 + }, + "santander-mmat": { + "oil": 1, + "iron": 0.8, + "food": 1, + "industry": 0.67 + }, + "santarem-sojz": { + "oil": 0.48, + "iron": 0.63, + "food": 0.78, + "industry": 0.32 + }, + "santiago-de-cuba-qfej": { + "oil": 0.78, + "iron": 0.81, + "food": 0.84, + "industry": 0.79 + }, + "santiago-del-estero-grns": { + "oil": 0.62, + "iron": 0.54, + "food": 0.65, + "industry": 1 + }, + "sao-paulo-eurp": { + "oil": 1, + "iron": 0.07, + "food": 0.23, + "industry": 0.52 + }, + "saratov-avzz": { + "oil": 0.99, + "iron": 0.65, + "food": 0.09, + "industry": 0.28 + }, + "sarawak-cpxb": { + "oil": 0.94, + "iron": 0.77, + "food": 0.35, + "industry": 0.95 + }, + "sari-pul-eubi": { + "oil": 0.57, + "iron": 0.48, + "food": 0.34, + "industry": 0.06 + }, + "sarthe-ebkd": { + "oil": 0.21, + "iron": 0.68, + "food": 0.44, + "industry": 0.71 + }, + "saskatchewan-cmli": { + "oil": 0.66, + "iron": 0.76, + "food": 0.72, + "industry": 0.24 + }, + "sassari-aeyz": { + "oil": 0.95, + "iron": 1, + "food": 0.2, + "industry": 0.64 + }, + "sava-atuj": { + "oil": 0.87, + "iron": 0.8, + "food": 1, + "industry": 0.14 + }, + "savanes-sjqm": { + "oil": 0.63, + "iron": 0.28, + "food": 0.94, + "industry": 0.85 + }, + "savannakhet-ulpr": { + "oil": 1, + "iron": 0.99, + "food": 0.04, + "industry": 1 + }, + "savoie-zdke": { + "oil": 0.46, + "iron": 0.85, + "food": 0.17, + "industry": 0.46 + }, + "schleswig-holstein-gmaj": { + "oil": 0.99, + "iron": 1, + "food": 0.62, + "industry": 0.63 + }, + "sedhiou-qgha": { + "oil": 0.64, + "iron": 0.27, + "food": 0.27, + "industry": 0.81 + }, + "segou-aowd": { + "oil": 0.59, + "iron": 0.19, + "food": 0.2, + "industry": 0.92 + }, + "seien-et-marne-bxka": { + "oil": 0.32, + "iron": 1, + "food": 0.49, + "industry": 0.24 + }, + "selangor-wkxy": { + "oil": 0.55, + "iron": 0.04, + "food": 1, + "industry": 1 + }, + "selenge-mhnj": { + "oil": 0.89, + "iron": 0.75, + "food": 0.71, + "industry": 0.72 + }, + "semenawi-keyih-bahri-comw": { + "oil": 0.29, + "iron": 0.22, + "food": 0.82, + "industry": 1 + }, + "semnan-mukt": { + "oil": 0.93, + "iron": 0.03, + "food": 0.49, + "industry": 0.46 + }, + "sennar-dssz": { + "oil": 0.31, + "iron": 0.96, + "food": 0.99, + "industry": 0.36 + }, + "sergipe-glra": { + "oil": 0.48, + "iron": 0.59, + "food": 1, + "industry": 0.27 + }, + "seti-qarh": { + "oil": 0.39, + "iron": 0.47, + "food": 0.07, + "industry": 0.49 + }, + "setif-mbzf": { + "oil": 0.27, + "iron": 0.99, + "food": 0.41, + "industry": 0.88 + }, + "severnaya-zemlya-awqp": { + "oil": 0.1, + "iron": 0.48, + "food": 1, + "industry": 0.3 + }, + "sevilla-oxma": { + "oil": 0.1, + "iron": 0.16, + "food": 0.85, + "industry": 0.22 + }, + "sfax-ktva": { + "oil": 0.93, + "iron": 0.39, + "food": 0.05, + "industry": 1 + }, + "shaanxi-kyfb": { + "oil": 0.03, + "iron": 1, + "food": 0.14, + "industry": 0.57 + }, + "shabeellaha-dhexe-ueua": { + "oil": 0.91, + "iron": 1, + "food": 0.42, + "industry": 0.46 + }, + "shabeellaha-hoose-sxum": { + "oil": 0.02, + "iron": 0.29, + "food": 0.15, + "industry": 0.69 + }, + "shabwah-mpqr": { + "oil": 0.97, + "iron": 0.34, + "food": 0.54, + "industry": 0.23 + }, + "shamal-sina-uhqn": { + "oil": 0.63, + "iron": 1, + "food": 1, + "industry": 0.48 + }, + "shan-qqtq": { + "oil": 0.05, + "iron": 0.4, + "food": 0.32, + "industry": 0.93 + }, + "shandong-ajfr": { + "oil": 0.68, + "iron": 0.26, + "food": 0.97, + "industry": 0.16 + }, + "shanxi-ubft": { + "oil": 0.33, + "iron": 0.01, + "food": 0.43, + "industry": 0.22 + }, + "shetland-islands-ypae": { + "oil": 0.8, + "iron": 0.26, + "food": 0.02, + "industry": 0.23 + }, + "shinyanga-kdvn": { + "oil": 0.01, + "iron": 0.75, + "food": 0.48, + "industry": 0.66 + }, + "shizuoka-ycjg": { + "oil": 0.56, + "iron": 0.67, + "food": 0.12, + "industry": 0.72 + }, + "shkoder-gmnr": { + "oil": 1, + "iron": 0.97, + "food": 0.63, + "industry": 0.98 + }, + "shropshire-mhvl": { + "oil": 0.91, + "iron": 0.86, + "food": 0.47, + "industry": 0.35 + }, + "shumen-ahrd": { + "oil": 0.13, + "iron": 0.46, + "food": 0.57, + "industry": 0.61 + }, + "sichuan-eufy": { + "oil": 0.78, + "iron": 0.57, + "food": 0.93, + "industry": 0.51 + }, + "sidi-bel-abbes-kfbb": { + "oil": 0.21, + "iron": 0.8, + "food": 0.36, + "industry": 0.97 + }, + "sidi-bou-zid-ifqk": { + "oil": 0.25, + "iron": 0.07, + "food": 0.49, + "industry": 0.37 + }, + "siemreab-vyop": { + "oil": 0.07, + "iron": 0.1, + "food": 0.45, + "industry": 0.27 + }, + "siguiri-juvq": { + "oil": 0.97, + "iron": 0.49, + "food": 1, + "industry": 0.17 + }, + "siirt-yozc": { + "oil": 0.13, + "iron": 0.54, + "food": 0.28, + "industry": 0.56 + }, + "sikasso-fzwk": { + "oil": 1, + "iron": 0.17, + "food": 0.88, + "industry": 0.89 + }, + "sila-rfnx": { + "oil": 0.61, + "iron": 0.34, + "food": 0.9, + "industry": 0.58 + }, + "silesian-igbk": { + "oil": 0.9, + "iron": 0.89, + "food": 0.65, + "industry": 0.21 + }, + "simiyu-iyyt": { + "oil": 0.29, + "iron": 1, + "food": 0.09, + "industry": 0.69 + }, + "sinaloa-ahmy": { + "oil": 0.91, + "iron": 0.99, + "food": 0.44, + "industry": 0.32 + }, + "sind-atud": { + "oil": 0.73, + "iron": 0.97, + "food": 0.92, + "industry": 0.79 + }, + "singida-gfvo": { + "oil": 0.34, + "iron": 0.22, + "food": 1, + "industry": 0.88 + }, + "sipaliwini-lvya": { + "oil": 0.38, + "iron": 0.33, + "food": 0.9, + "industry": 0.44 + }, + "sissili-amog": { + "oil": 0.56, + "iron": 1, + "food": 0.41, + "industry": 0.58 + }, + "sistan-and-baluchestan-avku": { + "oil": 0.85, + "iron": 0.21, + "food": 0.57, + "industry": 0.69 + }, + "sivas-ofzw": { + "oil": 0.33, + "iron": 1, + "food": 0.24, + "industry": 0.41 + }, + "skane-ouua": { + "oil": 0.01, + "iron": 0.57, + "food": 0.75, + "industry": 1 + }, + "skikda-odba": { + "oil": 0.46, + "iron": 0.85, + "food": 0.17, + "industry": 0.46 + }, + "smolensk-qrwu": { + "oil": 0.53, + "iron": 0.17, + "food": 0.29, + "industry": 0.39 + }, + "sodermanland-sfuh": { + "oil": 0.7, + "iron": 0.78, + "food": 0.74, + "industry": 0.97 + }, + "sofala-ohfw": { + "oil": 0.17, + "iron": 0.14, + "food": 1, + "industry": 0.23 + }, + "sofia-corh": { + "oil": 1, + "iron": 0.52, + "food": 0.15, + "industry": 0.93 + }, + "sofia-kmae": { + "oil": 0.08, + "iron": 0.83, + "food": 1, + "industry": 0.63 + }, + "sogn-og-fjordane-iuak": { + "oil": 0.8, + "iron": 0.22, + "food": 0.06, + "industry": 0.5 + }, + "sokoto-mjsi": { + "oil": 0.13, + "iron": 0.89, + "food": 0.17, + "industry": 0.52 + }, + "somali-eiea": { + "oil": 0.84, + "iron": 0.61, + "food": 0.86, + "industry": 0.79 + }, + "somaliland-gapg": { + "oil": 0.27, + "iron": 0.08, + "food": 0.23, + "industry": 0.31 + }, + "somerset-drhz": { + "oil": 0.53, + "iron": 0.82, + "food": 0.75, + "industry": 0.97 + }, + "somme-sgzc": { + "oil": 0.63, + "iron": 0.81, + "food": 0.06, + "industry": 0.29 + }, + "somogy-ymes": { + "oil": 0.19, + "iron": 0.46, + "food": 0.31, + "industry": 0.28 + }, + "son-la-amzp": { + "oil": 0.26, + "iron": 0.15, + "food": 0.34, + "industry": 0.31 + }, + "songkhla-eojn": { + "oil": 0.22, + "iron": 0.45, + "food": 0.6, + "industry": 0.49 + }, + "sonora-otbs": { + "oil": 1, + "iron": 0.15, + "food": 0.54, + "industry": 0.05 + }, + "sor-trondelag-sxam": { + "oil": 0.7, + "iron": 0.43, + "food": 0.05, + "industry": 0.43 + }, + "soria-comu": { + "oil": 0.35, + "iron": 0.31, + "food": 0.17, + "industry": 0.42 + }, + "soriano-ixbv": { + "oil": 0.61, + "iron": 0.71, + "food": 0.86, + "industry": 0.21 + }, + "souk-ahras-uqmy": { + "oil": 0.31, + "iron": 0.19, + "food": 0.15, + "industry": 0.93 + }, + "soum-whaq": { + "oil": 0.69, + "iron": 0.34, + "food": 0.59, + "industry": 0.93 + }, + "souss-massa-draa-mbhy": { + "oil": 0.59, + "iron": 0.06, + "food": 0.77, + "industry": 0.81 + }, + "south-australia-cutu": { + "oil": 1, + "iron": 1, + "food": 0.82, + "industry": 0.16 + }, + "south-carolina-izro": { + "oil": 0.59, + "iron": 0.56, + "food": 0.31, + "industry": 1 + }, + "south-dakota-oerr": { + "oil": 0.45, + "iron": 0.34, + "food": 0.57, + "industry": 0.76 + }, + "south-gyeongsang-edoo": { + "oil": 0.68, + "iron": 0.31, + "food": 0.46, + "industry": 0.2 + }, + "south-jeolla-wooe": { + "oil": 0.39, + "iron": 0.12, + "food": 0.37, + "industry": 0.58 + }, + "south-kazakhstan-qtgc": { + "oil": 0.23, + "iron": 0.33, + "food": 0.8, + "industry": 0.07 + }, + "south-khorasan-usnp": { + "oil": 0.15, + "iron": 0.94, + "food": 0.34, + "industry": 0.29 + }, + "south-kordufan-ygzz": { + "oil": 0.48, + "iron": 0.31, + "food": 0.31, + "industry": 0.3 + }, + "southern-ctpk": { + "oil": 0.37, + "iron": 0.55, + "food": 0.59, + "industry": 0.91 + }, + "southern-darfur-iopm": { + "oil": 0.4, + "iron": 0.38, + "food": 0.05, + "industry": 0.57 + }, + "southern-highlands-wdcq": { + "oil": 0.4, + "iron": 0.57, + "food": 0.92, + "industry": 0.1 + }, + "southern-nations-nationalities-and-peoples-ohez": { + "oil": 0.46, + "iron": 0.02, + "food": 0.99, + "industry": 0.99 + }, + "southern-ncas": { + "oil": 0.52, + "iron": 0.87, + "food": 0.98, + "industry": 0.09 + }, + "southern-orts": { + "oil": 0.92, + "iron": 0.78, + "food": 0.37, + "industry": 0.69 + }, + "southern-ostrobothnia-ihkk": { + "oil": 0.6, + "iron": 0.86, + "food": 0.82, + "industry": 0.41 + }, + "southern-savonia-ewkd": { + "oil": 1, + "iron": 1, + "food": 0.07, + "industry": 0.51 + }, + "southland-ukrs": { + "oil": 0.93, + "iron": 0.34, + "food": 0.93, + "industry": 0.57 + }, + "sremski-xjrs": { + "oil": 0.65, + "iron": 0.54, + "food": 0.69, + "industry": 0.84 + }, + "st-eustatius-wdkr": { + "oil": 0.07, + "iron": 0.17, + "food": 0.69, + "industry": 0.15 + }, + "stara-zagora-hmrg": { + "oil": 0.65, + "iron": 0.24, + "food": 0.64, + "industry": 0.15 + }, + "stavropol-mizd": { + "oil": 0.72, + "iron": 0.12, + "food": 0.47, + "industry": 0.31 + }, + "steiermark-afps": { + "oil": 0.21, + "iron": 1, + "food": 0.07, + "industry": 0.07 + }, + "sterea-ellada-inyu": { + "oil": 0.55, + "iron": 1, + "food": 0.83, + "industry": 0.85 + }, + "stoeng-treng-jiov": { + "oil": 0.25, + "iron": 0.45, + "food": 0.56, + "industry": 0.66 + }, + "stredocesky-ihft": { + "oil": 0.73, + "iron": 0.35, + "food": 0.35, + "industry": 0.37 + }, + "subcarpathian-ajux": { + "oil": 0.03, + "iron": 0.91, + "food": 0.88, + "industry": 0.08 + }, + "sucre-glea": { + "oil": 0.12, + "iron": 0.26, + "food": 0.36, + "industry": 1 + }, + "sucre-qsqk": { + "oil": 0.16, + "iron": 0.39, + "food": 0.35, + "industry": 0.22 + }, + "sucumbios-ejuw": { + "oil": 0.23, + "iron": 0.96, + "food": 0.64, + "industry": 0.23 + }, + "sud-bandama-sksp": { + "oil": 0.09, + "iron": 0.4, + "food": 0.55, + "industry": 0.05 + }, + "sud-kivu-katu": { + "oil": 0.65, + "iron": 0.64, + "food": 1, + "industry": 0.07 + }, + "sud-mukj": { + "oil": 0.44, + "iron": 0.77, + "food": 0.47, + "industry": 0.31 + }, + "sud-ouest-yxkl": { + "oil": 0.37, + "iron": 0.83, + "food": 0.31, + "industry": 0.73 + }, + "sudurland-ysfc": { + "oil": 0.09, + "iron": 0.59, + "food": 0.35, + "industry": 0.35 + }, + "suffolk-peqe": { + "oil": 0.11, + "iron": 0.19, + "food": 0.09, + "industry": 0.44 + }, + "suhbaatar-quqi": { + "oil": 0.29, + "iron": 0.46, + "food": 1, + "industry": 1 + }, + "sulawesi-barat-zpku": { + "oil": 0.67, + "iron": 0.48, + "food": 0.41, + "industry": 0.45 + }, + "sulawesi-selatan-thkw": { + "oil": 0.76, + "iron": 0.83, + "food": 0.79, + "industry": 0.6 + }, + "sulawesi-tengah-lskw": { + "oil": 0.47, + "iron": 0.18, + "food": 0.71, + "industry": 0.35 + }, + "sulawesi-tenggara-ctkn": { + "oil": 1, + "iron": 0.37, + "food": 0.43, + "industry": 0.54 + }, + "sulawesi-utara-ojkh": { + "oil": 0.82, + "iron": 0.56, + "food": 0.33, + "industry": 0.11 + }, + "sultan-kudarat-pnsz": { + "oil": 0.23, + "iron": 0.19, + "food": 0.29, + "industry": 0.88 + }, + "sumatera-barat-vokk": { + "oil": 0.83, + "iron": 0.2, + "food": 0.2, + "industry": 1 + }, + "sumatera-selatan-enkt": { + "oil": 1, + "iron": 0.14, + "food": 0.57, + "industry": 0.45 + }, + "sumatera-utara-qqkv": { + "oil": 0.1, + "iron": 0.57, + "food": 0.68, + "industry": 0.48 + }, + "sumy-kcqr": { + "oil": 0.04, + "iron": 1, + "food": 0.83, + "industry": 0.94 + }, + "surat-thani-wngk": { + "oil": 0.71, + "iron": 0.12, + "food": 0.88, + "industry": 0.79 + }, + "surkhandarya-usso": { + "oil": 0.44, + "iron": 1, + "food": 0.1, + "industry": 1 + }, + "surt-otkn": { + "oil": 0.27, + "iron": 0.6, + "food": 0.95, + "industry": 0.65 + }, + "svalbard-eeck": { + "oil": 0.12, + "iron": 0.93, + "food": 0.25, + "industry": 0.54 + }, + "sverdlovsk-eefj": { + "oil": 0.02, + "iron": 0.38, + "food": 1, + "industry": 0.12 + }, + "swietokrzyskie-yobp": { + "oil": 0.77, + "iron": 0.1, + "food": 0.32, + "industry": 0.4 + }, + "syddanmark-ykbt": { + "oil": 0.21, + "iron": 0.74, + "food": 0.89, + "industry": 0.65 + }, + "sylhet-iprt": { + "oil": 0.88, + "iron": 0.44, + "food": 0.44, + "industry": 0.43 + }, + "ta-izz-ctzr": { + "oil": 0.29, + "iron": 0.06, + "food": 0.8, + "industry": 0.87 + }, + "tabasco-hhvb": { + "oil": 1, + "iron": 0.21, + "food": 0.45, + "industry": 0.82 + }, + "tabora-wnvt": { + "oil": 0.53, + "iron": 0.97, + "food": 0.84, + "industry": 1 + }, + "tabuk-spql": { + "oil": 0.49, + "iron": 0.13, + "food": 0.84, + "industry": 0.16 + }, + "tachira-kuql": { + "oil": 0.74, + "iron": 0.65, + "food": 0.11, + "industry": 0.5 + }, + "tacna-uiaf": { + "oil": 0.27, + "iron": 1, + "food": 0.14, + "industry": 0.7 + }, + "tacuarembo-yekg": { + "oil": 0.52, + "iron": 0.44, + "food": 0.19, + "industry": 0.05 + }, + "tadjourah-jsgf": { + "oil": 0.99, + "iron": 0.36, + "food": 0.88, + "industry": 0.76 + }, + "tadla-azilal-idhz": { + "oil": 0.07, + "iron": 0.69, + "food": 0.93, + "industry": 0.17 + }, + "tadzhikistan-territories-uxcw": { + "oil": 0.46, + "iron": 0.92, + "food": 0.79, + "industry": 0.36 + }, + "tafea-wskq": { + "oil": 1, + "iron": 0.28, + "food": 0.03, + "industry": 0.91 + }, + "tagant-tjfm": { + "oil": 0.01, + "iron": 0.46, + "food": 0.46, + "industry": 0.59 + }, + "tahoua-gpff": { + "oil": 0.58, + "iron": 0.17, + "food": 0.25, + "industry": 0.42 + }, + "tak-ojvr": { + "oil": 1, + "iron": 1, + "food": 0.06, + "industry": 0.08 + }, + "takhar-tbah": { + "oil": 0.41, + "iron": 0.62, + "food": 0.97, + "industry": 0.57 + }, + "talas-orlv": { + "oil": 0.68, + "iron": 0.65, + "food": 0.66, + "industry": 0.68 + }, + "tamanghasset-mozx": { + "oil": 0.82, + "iron": 1, + "food": 0.44, + "industry": 0.75 + }, + "tamaulipas-apvq": { + "oil": 0.61, + "iron": 0.68, + "food": 0.44, + "industry": 0.98 + }, + "tambacounda-shqy": { + "oil": 0.53, + "iron": 0.19, + "food": 0.89, + "industry": 0.65 + }, + "tambov-evce": { + "oil": 0.71, + "iron": 0.2, + "food": 0.95, + "industry": 1 + }, + "tamil-nadu-sqvd": { + "oil": 0.93, + "iron": 0.19, + "food": 0.54, + "industry": 0.98 + }, + "tandjile-trlq": { + "oil": 0.16, + "iron": 0.2, + "food": 0.93, + "industry": 1 + }, + "tanga-oovu": { + "oil": 0.17, + "iron": 1, + "food": 0.72, + "industry": 0.51 + }, + "tanger-tetouan-eqeu": { + "oil": 0.49, + "iron": 0.52, + "food": 0.15, + "industry": 0.92 + }, + "tanintharyi-ydrp": { + "oil": 0.07, + "iron": 0.27, + "food": 0.28, + "industry": 0.29 + }, + "tapoa-gpat": { + "oil": 0.79, + "iron": 0.04, + "food": 0.2, + "industry": 0.4 + }, + "taraba-cqbj": { + "oil": 0.46, + "iron": 0.17, + "food": 0.64, + "industry": 0.75 + }, + "tarapaca-mrpq": { + "oil": 1, + "iron": 0.41, + "food": 0.17, + "industry": 0.79 + }, + "tarija-grth": { + "oil": 0.99, + "iron": 0.08, + "food": 0.76, + "industry": 1 + }, + "tartu-aymq": { + "oil": 0.18, + "iron": 0.32, + "food": 0.97, + "industry": 0.99 + }, + "tashauz-mmct": { + "oil": 0.74, + "iron": 0.98, + "food": 0.01, + "industry": 0.53 + }, + "tashkent-awvo": { + "oil": 0.43, + "iron": 0.87, + "food": 0.52, + "industry": 0.68 + }, + "tasmania-kptu": { + "oil": 0.06, + "iron": 0.05, + "food": 0.41, + "industry": 0.9 + }, + "tataouine-qrma": { + "oil": 0.92, + "iron": 0.86, + "food": 0.97, + "industry": 0.74 + }, + "tatarstan-aotw": { + "oil": 0.63, + "iron": 0.58, + "food": 0.03, + "industry": 0.14 + }, + "tawi-tawi-khxg": { + "oil": 0.07, + "iron": 0.61, + "food": 0.58, + "industry": 0.74 + }, + "taza-al-hoceima-taounate-otew": { + "oil": 0.62, + "iron": 0.61, + "food": 0.62, + "industry": 1 + }, + "tebessa-iqzy": { + "oil": 0.08, + "iron": 1, + "food": 0.07, + "industry": 0.85 + }, + "tehran-ytij": { + "oil": 0.21, + "iron": 0.42, + "food": 1, + "industry": 0.1 + }, + "telangana-mfvw": { + "oil": 0.1, + "iron": 0.78, + "food": 0.22, + "industry": 0.18 + }, + "telemark-ceyx": { + "oil": 0.93, + "iron": 0.51, + "food": 0.86, + "industry": 1 + }, + "teleorman-gcnr": { + "oil": 0.07, + "iron": 0.55, + "food": 1, + "industry": 0.61 + }, + "telimele-jadt": { + "oil": 1, + "iron": 0.74, + "food": 1, + "industry": 0.43 + }, + "temotu-wpdk": { + "oil": 0.61, + "iron": 0.3, + "food": 0.3, + "industry": 0.86 + }, + "tennessee-geup": { + "oil": 0.37, + "iron": 0.79, + "food": 0.7, + "industry": 0.75 + }, + "terengganu-smxz": { + "oil": 0.39, + "iron": 1, + "food": 0.28, + "industry": 0.04 + }, + "ternopil-whse": { + "oil": 0.64, + "iron": 0.27, + "food": 0.27, + "industry": 0.81 + }, + "teruel-ofof": { + "oil": 0.99, + "iron": 0.56, + "food": 0.81, + "industry": 0.18 + }, + "tete-kjfx": { + "oil": 0.31, + "iron": 0.91, + "food": 1, + "industry": 1 + }, + "texas-mguh": { + "oil": 0.47, + "iron": 0.78, + "food": 0.64, + "industry": 0.91 + }, + "thaba-tseka-wjua": { + "oil": 0.07, + "iron": 0.14, + "food": 0.48, + "industry": 0.6 + }, + "thanh-hoa-okef": { + "oil": 0.96, + "iron": 0.15, + "food": 0.84, + "industry": 0.07 + }, + "the-snares-mvou": { + "oil": 0.9, + "iron": 0.59, + "food": 0.68, + "industry": 0.47 + }, + "thessalia-yhyh": { + "oil": 1, + "iron": 0.41, + "food": 0.92, + "industry": 0.85 + }, + "thies-mpqd": { + "oil": 0.2, + "iron": 0.32, + "food": 0.43, + "industry": 0.78 + }, + "thimphu-agoq": { + "oil": 0.43, + "iron": 1, + "food": 0.68, + "industry": 0.15 + }, + "three-kings-islands-qafu": { + "oil": 0.06, + "iron": 0.57, + "food": 0.32, + "industry": 0.32 + }, + "thuringen-mxiz": { + "oil": 0.51, + "iron": 0.92, + "food": 0.93, + "industry": 0.12 + }, + "tianjin-krnw": { + "oil": 0.08, + "iron": 0.98, + "food": 0.02, + "industry": 0.6 + }, + "tiaret-stza": { + "oil": 0.59, + "iron": 0.84, + "food": 0.87, + "industry": 0.66 + }, + "tibesti-teli": { + "oil": 0.16, + "iron": 1, + "food": 0.79, + "industry": 0.09 + }, + "tierra-del-fuego-sqnb": { + "oil": 0.59, + "iron": 0.74, + "food": 0.7, + "industry": 1 + }, + "tigray-ucnt": { + "oil": 0.21, + "iron": 0.14, + "food": 0.8, + "industry": 0.71 + }, + "tillaberi-yrfg": { + "oil": 0.9, + "iron": 0.73, + "food": 0.35, + "industry": 1 + }, + "timbuktu-mrwf": { + "oil": 0.95, + "iron": 0.32, + "food": 0.48, + "industry": 0.36 + }, + "timis-seme": { + "oil": 0.72, + "iron": 0.36, + "food": 0.71, + "industry": 0.65 + }, + "tindouf-ewdf": { + "oil": 1, + "iron": 0.08, + "food": 0.19, + "industry": 0.91 + }, + "tiris-zemmour-xshf": { + "oil": 1, + "iron": 0.57, + "food": 0.93, + "industry": 0.66 + }, + "tirol-sgpt": { + "oil": 0.99, + "iron": 0.64, + "food": 0.32, + "industry": 0.69 + }, + "tocantins-kczu": { + "oil": 0.19, + "iron": 1, + "food": 1, + "industry": 0.21 + }, + "tochigi-kfff": { + "oil": 0.25, + "iron": 0.93, + "food": 1, + "industry": 0.54 + }, + "tokelau-cqiy": { + "oil": 0.31, + "iron": 0.49, + "food": 0.26, + "industry": 0.83 + }, + "toledo-yvoz": { + "oil": 0.08, + "iron": 0.8, + "food": 0.7, + "industry": 0.92 + }, + "tolima-gone": { + "oil": 0.49, + "iron": 1, + "food": 0.66, + "industry": 0.31 + }, + "tomsk-gews": { + "oil": 0.74, + "iron": 0, + "food": 1, + "industry": 0.25 + }, + "torba-ckkb": { + "oil": 0.94, + "iron": 0.72, + "food": 0.82, + "industry": 0.87 + }, + "tov-udnh": { + "oil": 0.77, + "iron": 0.2, + "food": 0.23, + "industry": 0.42 + }, + "transcarpathia-qncy": { + "oil": 0.9, + "iron": 1, + "food": 0.06, + "industry": 0.83 + }, + "trarza-mefd": { + "oil": 0.65, + "iron": 1, + "food": 0.74, + "industry": 0.81 + }, + "tripura-ylvj": { + "oil": 0.27, + "iron": 0.85, + "food": 0.4, + "industry": 0.15 + }, + "troms-ccap": { + "oil": 0.53, + "iron": 0.63, + "food": 0.7, + "industry": 0.52 + }, + "tucuman-ennz": { + "oil": 0.05, + "iron": 0.76, + "food": 0.78, + "industry": 0.37 + }, + "tukums-qtmk": { + "oil": 0.32, + "iron": 0.95, + "food": 0.02, + "industry": 0.85 + }, + "tula-cvuo": { + "oil": 0.13, + "iron": 1, + "food": 0.17, + "industry": 0.12 + }, + "tungurahua-ylux": { + "oil": 1, + "iron": 0.38, + "food": 0.24, + "industry": 0.51 + }, + "turin-yfaa": { + "oil": 1, + "iron": 0.36, + "food": 1, + "industry": 0.28 + }, + "tuva-ecty": { + "oil": 0.02, + "iron": 0.93, + "food": 0.66, + "industry": 0.14 + }, + "tuy-updk": { + "oil": 0.8, + "iron": 1, + "food": 0.91, + "industry": 0.46 + }, + "tuyen-quang-kpzr": { + "oil": 0.07, + "iron": 0.79, + "food": 0.96, + "industry": 1 + }, + "tver-qdaj": { + "oil": 0.5, + "iron": 0.28, + "food": 0.33, + "industry": 0.75 + }, + "tyumen-uppf": { + "oil": 0.88, + "iron": 0.32, + "food": 0.76, + "industry": 1 + }, + "ubon-ratchathani-mzil": { + "oil": 0.38, + "iron": 0.13, + "food": 0.74, + "industry": 0.36 + }, + "ucayali-hmry": { + "oil": 0.51, + "iron": 0.57, + "food": 0.93, + "industry": 0.47 + }, + "udmurt-cave": { + "oil": 0.88, + "iron": 0.87, + "food": 0.9, + "industry": 0.07 + }, + "udon-thani-iuqh": { + "oil": 0.07, + "iron": 0.85, + "food": 0.8, + "industry": 0.57 + }, + "uige-alyd": { + "oil": 0.96, + "iron": 0.45, + "food": 0.46, + "industry": 0.9 + }, + "ul-yanovsk-uovf": { + "oil": 0.35, + "iron": 0.41, + "food": 0.66, + "industry": 1 + }, + "unity-smuv": { + "oil": 1, + "iron": 1, + "food": 1, + "industry": 0.85 + }, + "upper-demerara-berbice-ynhw": { + "oil": 0.15, + "iron": 0.69, + "food": 0.79, + "industry": 0.28 + }, + "upper-nile-kxdz": { + "oil": 0.66, + "iron": 0.15, + "food": 0.51, + "industry": 0.45 + }, + "upper-takutu-upper-essequibo-cohg": { + "oil": 0.1, + "iron": 0.64, + "food": 0.67, + "industry": 0.95 + }, + "upper-west-avqy": { + "oil": 0.75, + "iron": 1, + "food": 0.05, + "industry": 0.8 + }, + "uppsala-aeug": { + "oil": 0.42, + "iron": 0.23, + "food": 0.58, + "industry": 0 + }, + "uruzgan-ebhn": { + "oil": 0.12, + "iron": 0.79, + "food": 0.27, + "industry": 0.96 + }, + "uruzgan-unxj": { + "oil": 0.38, + "iron": 1, + "food": 1, + "industry": 0.2 + }, + "usulutan-xbjc": { + "oil": 0.39, + "iron": 0.29, + "food": 0.67, + "industry": 0.19 + }, + "utah-whas": { + "oil": 0.92, + "iron": 0.96, + "food": 0.72, + "industry": 0.92 + }, + "uthai-thani-ymvt": { + "oil": 0.09, + "iron": 0.16, + "food": 0.94, + "industry": 0.2 + }, + "uttar-pradesh-aaxe": { + "oil": 0.04, + "iron": 0.29, + "food": 1, + "industry": 0.07 + }, + "uttaradit-swtq": { + "oil": 0.57, + "iron": 0.91, + "food": 1, + "industry": 0.5 + }, + "uttarakhand-ygxi": { + "oil": 0.44, + "iron": 0.77, + "food": 1, + "industry": 0.73 + }, + "uusimaa-gpng": { + "oil": 0.37, + "iron": 0.01, + "food": 0.88, + "industry": 0.9 + }, + "uvs-ccng": { + "oil": 0.22, + "iron": 0.7, + "food": 0.14, + "industry": 1 + }, + "vakaga-ahth": { + "oil": 0.29, + "iron": 0.46, + "food": 0.08, + "industry": 0.89 + }, + "vakinankaratra-dtjh": { + "oil": 0.76, + "iron": 0.27, + "food": 1, + "industry": 1 + }, + "valencia-ydbr": { + "oil": 0.85, + "iron": 0.07, + "food": 0.25, + "industry": 0.25 + }, + "valle-del-cauca-urfx": { + "oil": 0.86, + "iron": 0.23, + "food": 0.99, + "industry": 0.87 + }, + "vallee-du-bandama-oyqf": { + "oil": 0.93, + "iron": 0.28, + "food": 0.34, + "industry": 0.18 + }, + "valparaiso-mfuk": { + "oil": 0.18, + "iron": 0.06, + "food": 0.82, + "industry": 0.87 + }, + "van-ujcg": { + "oil": 0.36, + "iron": 0.27, + "food": 1, + "industry": 1 + }, + "varmland-aeuq": { + "oil": 1, + "iron": 0.11, + "food": 0.21, + "industry": 0.43 + }, + "vasterbotten-ykth": { + "oil": 1, + "iron": 0.26, + "food": 0.42, + "industry": 0.76 + }, + "vasternorrland-upug": { + "oil": 0.77, + "iron": 0.07, + "food": 0, + "industry": 0.18 + }, + "vastra-gotaland-yxuc": { + "oil": 0.57, + "iron": 0.55, + "food": 0.55, + "industry": 0.43 + }, + "vatovavy-fitovinany-abdm": { + "oil": 0.68, + "iron": 0.58, + "food": 0.61, + "industry": 1 + }, + "vaupes-ihfh": { + "oil": 0.39, + "iron": 0.05, + "food": 0.93, + "industry": 0.35 + }, + "veliko-tarnovo-zews": { + "oil": 0.19, + "iron": 0.02, + "food": 0.45, + "industry": 0.74 + }, + "vendee-lozh": { + "oil": 1, + "iron": 0.08, + "food": 0.01, + "industry": 0.33 + }, + "venezuela-oxzs": { + "oil": 0.9, + "iron": 0.95, + "food": 0.04, + "industry": 0.87 + }, + "ventspils-cuhk": { + "oil": 1, + "iron": 0.54, + "food": 0.02, + "industry": 0.02 + }, + "veracruz-kuoh": { + "oil": 0.66, + "iron": 0.8, + "food": 1, + "industry": 0.84 + }, + "veraguas-gsiv": { + "oil": 0.53, + "iron": 0.55, + "food": 0.98, + "industry": 0.54 + }, + "vermont-ujdo": { + "oil": 0.13, + "iron": 0.3, + "food": 0.99, + "industry": 1 + }, + "vesturland-ajfn": { + "oil": 0.93, + "iron": 0.44, + "food": 0.02, + "industry": 0.5 + }, + "veszprem-czmj": { + "oil": 0.82, + "iron": 0.26, + "food": 0.91, + "industry": 1 + }, + "vichada-oozm": { + "oil": 0.2, + "iron": 0.8, + "food": 0.98, + "industry": 0.16 + }, + "victoria-svnw": { + "oil": 0.74, + "iron": 1, + "food": 0.55, + "industry": 1 + }, + "vienne-cpzi": { + "oil": 0.25, + "iron": 0.39, + "food": 0.15, + "industry": 0.28 + }, + "vientiane-qhaq": { + "oil": 1, + "iron": 1, + "food": 0.67, + "industry": 0.02 + }, + "vila-real-ytjc": { + "oil": 0.38, + "iron": 0.45, + "food": 0.56, + "industry": 0.78 + }, + "villa-clara-cpbg": { + "oil": 0.61, + "iron": 0.99, + "food": 0.62, + "industry": 0.16 + }, + "vinnytsya-yoxi": { + "oil": 0.7, + "iron": 1, + "food": 0.31, + "industry": 0.84 + }, + "viqueque-wkyr": { + "oil": 0.45, + "iron": 0.73, + "food": 0.76, + "industry": 0.35 + }, + "virginia-oedb": { + "oil": 0.14, + "iron": 0.45, + "food": 0.62, + "industry": 0.31 + }, + "viseu-uvjd": { + "oil": 0.46, + "iron": 0.27, + "food": 0.24, + "industry": 0.27 + }, + "vitebsk-anmn": { + "oil": 0.1, + "iron": 0.54, + "food": 0.47, + "industry": 0.38 + }, + "vladimir-mqvt": { + "oil": 0.93, + "iron": 1, + "food": 1, + "industry": 0.26 + }, + "volgograd-omkg": { + "oil": 0.42, + "iron": 1, + "food": 0.78, + "industry": 0.23 + }, + "vologda-ynvr": { + "oil": 0.3, + "iron": 0.72, + "food": 0.05, + "industry": 0.14 + }, + "volta-ihni": { + "oil": 0.94, + "iron": 0.2, + "food": 0.88, + "industry": 0.92 + }, + "volyn-irxk": { + "oil": 0.56, + "iron": 0.84, + "food": 0.88, + "industry": 0.37 + }, + "voronezh-svdp": { + "oil": 0.61, + "iron": 0.56, + "food": 0.15, + "industry": 0.33 + }, + "vosges-oszk": { + "oil": 0.52, + "iron": 0.09, + "food": 0.74, + "industry": 0.35 + }, + "vratsa-lhwu": { + "oil": 0.19, + "iron": 0.9, + "food": 1, + "industry": 0.38 + }, + "vysocina-kamr": { + "oil": 0.81, + "iron": 1, + "food": 0.1, + "industry": 0.42 + }, + "wadi-al-hayaa-qrtp": { + "oil": 0.76, + "iron": 0.59, + "food": 0.74, + "industry": 0.12 + }, + "wadi-fira-wtem": { + "oil": 0.05, + "iron": 0.2, + "food": 0.66, + "industry": 0.08 + }, + "waikato-gxqe": { + "oil": 0.58, + "iron": 0.28, + "food": 0.11, + "industry": 0.81 + }, + "wangdi-phodrang-ipqp": { + "oil": 0.84, + "iron": 0.85, + "food": 1, + "industry": 0.2 + }, + "wardak-wpjg": { + "oil": 0.06, + "iron": 0.17, + "food": 0.52, + "industry": 0.68 + }, + "warmian-masurian-epsm": { + "oil": 0.89, + "iron": 0.56, + "food": 0.32, + "industry": 0.16 + }, + "warrap-kuzy": { + "oil": 0.95, + "iron": 0.85, + "food": 0.08, + "industry": 1 + }, + "washington-exgl": { + "oil": 0.8, + "iron": 1, + "food": 0.99, + "industry": 0.69 + }, + "wasit-vawa": { + "oil": 1, + "iron": 0, + "food": 0.6, + "industry": 0.65 + }, + "west-azarbaijan-eyim": { + "oil": 0.91, + "iron": 1, + "food": 0.12, + "industry": 0.18 + }, + "west-bank-cjlo": { + "oil": 0.32, + "iron": 0.35, + "food": 0.31, + "industry": 0.4 + }, + "west-bengal-isbk": { + "oil": 0.18, + "iron": 0.59, + "food": 0.81, + "industry": 0.95 + }, + "west-bosnia-ayyu": { + "oil": 0.82, + "iron": 0.28, + "food": 0.13, + "industry": 0.52 + }, + "west-coast-ucji": { + "oil": 0.81, + "iron": 0.66, + "food": 0.71, + "industry": 0.57 + }, + "west-kazakhstan-aqxa": { + "oil": 1, + "iron": 0.36, + "food": 0.93, + "industry": 0.89 + }, + "west-new-britain-qila": { + "oil": 0.61, + "iron": 1, + "food": 0.81, + "industry": 0.6 + }, + "west-pomeranian-mafy": { + "oil": 0.99, + "iron": 0.36, + "food": 0.51, + "industry": 0.19 + }, + "west-virginia-ivga": { + "oil": 0, + "iron": 0.15, + "food": 0.81, + "industry": 0.29 + }, + "western-adsp": { + "oil": 0.03, + "iron": 0.87, + "food": 0.52, + "industry": 0.03 + }, + "western-afoi": { + "oil": 0.89, + "iron": 0.21, + "food": 1, + "industry": 0.52 + }, + "western-alun": { + "oil": 0.62, + "iron": 0.61, + "food": 0.62, + "industry": 1 + }, + "western-australia-sxjw": { + "oil": 0.26, + "iron": 0.28, + "food": 1, + "industry": 1 + }, + "western-bahr-el-ghazal-uwvs": { + "oil": 0.7, + "iron": 0.69, + "food": 0.29, + "industry": 0.85 + }, + "western-cape-qngk": { + "oil": 0.34, + "iron": 0.56, + "food": 0.25, + "industry": 0.31 + }, + "western-cutu": { + "oil": 0.34, + "iron": 0.1, + "food": 0.71, + "industry": 0.05 + }, + "western-darfur-kvpq": { + "oil": 0.68, + "iron": 0.52, + "food": 0.11, + "industry": 0.4 + }, + "western-equatoria-yffx": { + "oil": 0.18, + "iron": 0.84, + "food": 0.92, + "industry": 0.02 + }, + "western-mygs": { + "oil": 1, + "iron": 0.57, + "food": 0.43, + "industry": 1 + }, + "western-qwvr": { + "oil": 0.41, + "iron": 0.26, + "food": 0.26, + "industry": 0.67 + }, + "western-sahara-gozf": { + "oil": 0.08, + "iron": 0.72, + "food": 0.83, + "industry": 1 + }, + "western-tobago-lmvd": { + "oil": 1, + "iron": 0.52, + "food": 0.38, + "industry": 1 + }, + "wexford-iasb": { + "oil": 0.91, + "iron": 0.65, + "food": 1, + "industry": 0.11 + }, + "white-nile-uwno": { + "oil": 0.98, + "iron": 0.26, + "food": 0.18, + "industry": 0.93 + }, + "wisconsin-ekgt": { + "oil": 0.63, + "iron": 1, + "food": 1, + "industry": 0.87 + }, + "worodougou-wiso": { + "oil": 0, + "iron": 0.29, + "food": 0.64, + "industry": 0.53 + }, + "wouleu-ntem-qnwu": { + "oil": 0.19, + "iron": 0.06, + "food": 0.11, + "industry": 0.39 + }, + "wyoming-ajgj": { + "oil": 0.18, + "iron": 0.88, + "food": 1, + "industry": 0.73 + }, + "xaignabouri-hdan": { + "oil": 1, + "iron": 1, + "food": 0.55, + "industry": 0.6 + }, + "xiangkhoang-hqaf": { + "oil": 0.11, + "iron": 0.67, + "food": 0.13, + "industry": 0.79 + }, + "xinjiang-oasq": { + "oil": 0.19, + "iron": 0.2, + "food": 0.21, + "industry": 0.08 + }, + "xizang-kzsk": { + "oil": 0.92, + "iron": 0.02, + "food": 0.18, + "industry": 0.23 + }, + "yala-ywjs": { + "oil": 0.42, + "iron": 0.8, + "food": 0.25, + "industry": 0.55 + }, + "yamagata-gofu": { + "oil": 0.36, + "iron": 0.9, + "food": 0.14, + "industry": 0.99 + }, + "yamal-gosw": { + "oil": 0.64, + "iron": 1, + "food": 1, + "industry": 0.49 + }, + "yamal-nenets-aqsx": { + "oil": 0.33, + "iron": 1, + "food": 0.11, + "industry": 0.48 + }, + "yamanashi-gwhj": { + "oil": 0.34, + "iron": 0.2, + "food": 0.58, + "industry": 0.72 + }, + "yaracuy-yxqn": { + "oil": 1, + "iron": 0.84, + "food": 0.68, + "industry": 0.02 + }, + "yaroslavl-cksd": { + "oil": 1, + "iron": 0.21, + "food": 0.56, + "industry": 0.17 + }, + "yatenga-ajue": { + "oil": 0.28, + "iron": 0.45, + "food": 0.13, + "industry": 0.77 + }, + "yazd-slnb": { + "oil": 0.31, + "iron": 0.8, + "food": 0.28, + "industry": 1 + }, + "yevrey-itcn": { + "oil": 0.27, + "iron": 0.96, + "food": 0.96, + "industry": 0.25 + }, + "yobe-sitq": { + "oil": 0.95, + "iron": 0.96, + "food": 0.04, + "industry": 0.71 + }, + "yomou-dhxs": { + "oil": 0.23, + "iron": 0.1, + "food": 0.1, + "industry": 0.47 + }, + "yonne-juzl": { + "oil": 0.4, + "iron": 0.54, + "food": 0.21, + "industry": 0.03 + }, + "yoro-chgi": { + "oil": 1, + "iron": 0.03, + "food": 0.79, + "industry": 0.46 + }, + "yozgat-oecd": { + "oil": 0.8, + "iron": 0.66, + "food": 0.71, + "industry": 0.57 + }, + "ysyk-kol-hqmi": { + "oil": 0.19, + "iron": 0.63, + "food": 0.08, + "industry": 0.94 + }, + "yucatan-mpkz": { + "oil": 0.49, + "iron": 0.94, + "food": 0.67, + "industry": 0.43 + }, + "yukon-hsje": { + "oil": 0.59, + "iron": 0.35, + "food": 1, + "industry": 0.06 + }, + "yunnan-mbuv": { + "oil": 1, + "iron": 0.58, + "food": 0.74, + "industry": 0.41 + }, + "zabul-ftpc": { + "oil": 0.59, + "iron": 0.16, + "food": 0.81, + "industry": 0.54 + }, + "zacatecas-pbpt": { + "oil": 0.93, + "iron": 0.28, + "food": 1, + "industry": 0.5 + }, + "zadarska-mglb": { + "oil": 0.11, + "iron": 0.35, + "food": 0.74, + "industry": 0.05 + }, + "zagrebacka-cijs": { + "oil": 0.41, + "iron": 0.59, + "food": 0.8, + "industry": 1 + }, + "zaire-ikgg": { + "oil": 0.91, + "iron": 0.39, + "food": 0.96, + "industry": 0.35 + }, + "zajecarski-lotj": { + "oil": 0.02, + "iron": 0.03, + "food": 0.25, + "industry": 0.02 + }, + "zambales-gjfs": { + "oil": 0.23, + "iron": 0.97, + "food": 0.04, + "industry": 0.57 + }, + "zambezia-eefu": { + "oil": 0.08, + "iron": 0.38, + "food": 0.74, + "industry": 0.96 + }, + "zamboanga-del-norte-qvgj": { + "oil": 0.73, + "iron": 0.38, + "food": 0.49, + "industry": 0.71 + }, + "zamfara-iavl": { + "oil": 0.28, + "iron": 0.02, + "food": 0.36, + "industry": 0.26 + }, + "zamora-chinchipe-qcur": { + "oil": 0.17, + "iron": 0.67, + "food": 0.37, + "industry": 0.03 + }, + "zamora-qhdj": { + "oil": 0.91, + "iron": 0.67, + "food": 0.78, + "industry": 0.17 + }, + "zanjan-qsks": { + "oil": 0.9, + "iron": 0.98, + "food": 0.43, + "industry": 0.32 + }, + "zanzan-qsqb": { + "oil": 0.94, + "iron": 0.38, + "food": 0.9, + "industry": 1 + }, + "zaporizhzhya-cjcw": { + "oil": 0, + "iron": 0.19, + "food": 0.85, + "industry": 1 + }, + "zaragoza-ajbv": { + "oil": 0.34, + "iron": 1, + "food": 0.69, + "industry": 0.85 + }, + "zenica-doboj-kqyp": { + "oil": 0.07, + "iron": 0.57, + "food": 0.22, + "industry": 0.72 + }, + "zhambyl-qhpv": { + "oil": 0.69, + "iron": 0.95, + "food": 0.95, + "industry": 0.94 + }, + "zhejiang-amww": { + "oil": 0.99, + "iron": 0.51, + "food": 0.71, + "industry": 0.82 + }, + "zhytomyr-iczk": { + "oil": 0.8, + "iron": 0.2, + "food": 0.36, + "industry": 0.98 + }, + "zinder-qsfh": { + "oil": 1, + "iron": 0.23, + "food": 0.66, + "industry": 0.12 + }, + "zlatiborski-gqtk": { + "oil": 0.92, + "iron": 0.62, + "food": 0.08, + "industry": 1 + }, + "zou-qmpu": { + "oil": 0.11, + "iron": 0.13, + "food": 0.37, + "industry": 0.6 + }, + "zulia-szqo": { + "oil": 0.86, + "iron": 0.9, + "food": 0.9, + "industry": 0.33 + }, + "zurich-kdpk": { + "oil": 0.56, + "iron": 0.35, + "food": 0.45, + "industry": 1 + } +} diff --git a/scripts/build-region-resources.mjs b/scripts/build-region-resources.mjs new file mode 100644 index 0000000..2b85d3e --- /dev/null +++ b/scripts/build-region-resources.mjs @@ -0,0 +1,149 @@ +/** + * scripts/build-region-resources.mjs — build the region **resources** manifest: + * `public/region-resources.json` = `{ "": { "oil": <0-1>, "iron": <0-1>, "food": <0-1>, "industry": <0-1> }, ... }`. + * + * Every sub-region (region key, see `public/region-keys.json`) gets a + * synthesized four-value resource profile. For each resource dimension a + * value in [0, 1] (2 decimal places) is derived from the FNV-1a 32-bit hash + * of the region key (salted per resource — the same tiny, stable, pure + * string hash the region keys themselves use), then scaled MODESTLY by the + * region's area (from the committed `public/region-geo.json`, when present): + * larger regions carry a slightly higher value (a log-scaled factor of at + * most ~1.2), so a big region reads as holding more of each resource. The + * geo file is OPTIONAL — without it (or for a zero-area region) the factor + * is exactly 1 and the profile is pure hash. + * + * This is the v0.36 (#59) "Resources & Industry" data source: the engine + * scales each region's per-turn industry boost by its `industry` value, and + * the LLM prompt carries each nation's aggregate profile (the + * area×population-weighted mean of the owned regions' profiles, see + * `deriveNationResources` in shared/protocol.ts). The profiles are + * synthesized (there is no real per-sub-region resource census) — they exist + * to give the model a stable, deterministic world fact to reason about. + * + * Output contract (asserted by scripts/build-region-resources.test.ts): + * - one entry for **every** region key, keyed identically to + * `public/region-keys.json` (same key set, 1,800 entries); + * - each entry is `{ oil, iron, food, industry }`, every value a finite + * number in [0, 1] with at most 2 decimal places; + * - keys are in sorted (deterministic) order. + * + * Deterministic + idempotent: fixed inputs (the key manifest, and the + * committed geo file when present), pure string hashing, fixed 2-dp + * rounding, and stable sorted key order → a re-run rewrites a byte-identical + * file (the test re-runs this script and compares bytes). + * + * Usage: `node scripts/build-region-resources.mjs` (or `npm run build:region-resources`). + */ +import { readFileSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const root = path.resolve(here, '..'); + +const round2 = (v) => Math.round(v * 100) / 100; + +/** FNV-1a 32-bit — the same tiny, stable, pure hash the region keys use. */ +function fnv1a32(str) { + let h = 0x811c9dc5; + for (let i = 0; i < str.length; i++) { + h ^= str.charCodeAt(i); + h = Math.imul(h, 0x01000193) >>> 0; + } + return h >>> 0; +} + +const RESOURCES = ['oil', 'iron', 'food', 'industry']; + +// --- load the inputs (plain parse) ------------------------------------------ +const keysPath = path.join(root, 'public', 'region-keys.json'); +const geoPath = path.join(root, 'public', 'region-geo.json'); + +let idToKey; +try { + idToKey = JSON.parse(readFileSync(keysPath, 'utf8')); +} catch (err) { + console.error(`[build-region-resources] could not load ${keysPath}.`); + throw err; +} + +// region-geo is OPTIONAL: a missing/broken file means "no area scaling" +// (factor 1 for every region) — the profile is then pure hash. +let areaByKey = {}; +try { + const parsed = JSON.parse(readFileSync(geoPath, 'utf8')); + for (const [k, v] of Object.entries(parsed)) { + if (v && typeof v.area === 'number' && Number.isFinite(v.area) && v.area >= 0) { + areaByKey[k] = v.area; + } + } +} catch { + areaByKey = {}; +} + +/** + * The base value in [0, 1) for one (region key, resource): the low 14 bits of + * the salted FNV-1a hash, normalized. Stable across runs and platforms; a + * uniform-enough spread for a synthesized profile. + */ +const base = (key, resource) => (fnv1a32(`${key}\u0000${resource}`) & 0x3fff) / 0x4000; + +/** + * The area scaling factor: 1.0 for a region with no geo entry (or zero area), + * rising on a log scale (clamped) to at most ~1.2 for the largest regions — + * bigger regions hold proportionally more of each resource. + */ +const areaScale = (key) => { + const a = areaByKey[key]; + if (!a || a <= 0) return 1; + // log10(1 + area) runs ~0.004 (tiny slivers) to ~5.5 (a 300k km² region); + // /8 + clamp keeps the factor in [1, 1.2]. + const t = Math.min(1, Math.log10(1 + a) / 8); + return 1 + 0.2 * t; +}; + +// --- assemble the manifest (sorted keys) ------------------------------------- +const expectedKeys = Object.values(idToKey); +const manifest = {}; +for (const k of [...expectedKeys].sort()) { + const scale = areaScale(k); + manifest[k] = { + oil: round2(Math.min(1, base(k, 'oil') * scale)), + iron: round2(Math.min(1, base(k, 'iron') * scale)), + food: round2(Math.min(1, base(k, 'food') * scale)), + industry: round2(Math.min(1, base(k, 'industry') * scale)), + }; +} + +// --- hard assertions (the test re-checks these against the committed file) ---- +if (Object.keys(manifest).length !== expectedKeys.length) { + throw new Error( + `expected ${expectedKeys.length} region-resources entries (one per region key), got ${Object.keys(manifest).length}`, + ); +} +let scaled = 0; +for (const [k, v] of Object.entries(manifest)) { + if (areaByKey[k]) scaled += 1; + for (const r of RESOURCES) { + const val = v[r]; + if (typeof val !== 'number' || !Number.isFinite(val) || val < 0 || val > 1) { + throw new Error(`bad ${r} value for ${k}: ${JSON.stringify(val)}`); + } + if (Math.round(val * 100) / 100 !== val) { + throw new Error(`${r} over 2dp for ${k}: ${val}`); + } + } +} + +// --- write idempotently (sorted keys, 2-space indent, trailing newline) ------ +writeFileSync( + path.join(root, 'public', 'region-resources.json'), + JSON.stringify(manifest, null, 2) + '\n', +); + +// --- summary ------------------------------------------------------------------ +console.log( + `[build-region-resources] wrote public/region-resources.json — ${Object.keys(manifest).length} region keys` + + ` (${scaled} area-scaled, ${Object.keys(manifest).length - scaled} pure-hash)`, +); diff --git a/scripts/build-region-resources.test.ts b/scripts/build-region-resources.test.ts new file mode 100644 index 0000000..79227de --- /dev/null +++ b/scripts/build-region-resources.test.ts @@ -0,0 +1,106 @@ +/** + * scripts/build-region-resources.test.ts — validation for the committed + * `public/region-resources.json` (built by `scripts/build-region-resources.mjs`). + * + * The manifest maps each region key to a synthesized four-value resource + * profile `{ oil, iron, food, industry }` — each a finite number in [0, 1] + * (2 decimal places). It is the v0.36 (#59) "Resources & Industry" data + * source: the engine scales each region's per-turn industry boost by its + * `industry` value, and the LLM prompt carries each nation's aggregate + * profile (the area×population-weighted mean of the owned regions' profiles, + * `deriveNationResources` in shared/protocol.ts). + * + * Like the region-geo manifest, this is a load-bearing data artifact — the + * test pins its contract. It is dependency-free: it reads the JSON with plain + * `fs`/`JSON.parse` (no `@turf`/geojson types, which would pull `@types/geojson` + * into the tsc program and break `WorldMap.tsx` — see the v0.17 note). The + * determinism test re-runs the (turf-free) `.mjs` builder and compares bytes, + * matching that the builder is idempotent. + */ +import { readFileSync } from 'node:fs'; +import { execFileSync } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const root = path.resolve(here, '..'); + +function readJson(rel: string): Record { + return JSON.parse(readFileSync(path.join(root, rel), 'utf8')); +} + +interface ResourceEntry { + oil: number; + iron: number; + food: number; + industry: number; +} + +const RESOURCES = ['oil', 'iron', 'food', 'industry'] as const; + +// feature id -> region key +const manifest = readJson('public/region-keys.json') as Record; +const resources = readJson('public/region-resources.json') as Record; +const keys = Object.values(manifest); + +describe('region-resources.json', () => { + it('has exactly one entry per region key (same key set as region-keys.json)', () => { + expect(new Set(Object.keys(resources))).toEqual(new Set(keys)); + expect(Object.keys(resources)).toHaveLength(1800); + }); + + it('is keyed in sorted (deterministic) order', () => { + const ks = Object.keys(resources); + expect(ks).toEqual([...ks].sort()); + }); + + it('every entry is a finite { oil, iron, food, industry } in [0,1] with ≤ 2 dp', () => { + for (const [k, v] of Object.entries(resources)) { + for (const r of RESOURCES) { + const val = v[r]; + expect(typeof val, `non-number ${r} for ${k}`).toBe('number'); + expect(Number.isFinite(val), `non-finite ${r} for ${k}`).toBe(true); + expect(val >= 0, `negative ${r} for ${k}: ${val}`).toBe(true); + expect(val <= 1, `${r} above 1 for ${k}: ${val}`).toBe(true); + expect( + Math.round(val * 100) / 100 === val, + `${r} over 2dp for ${k}: ${val}`, + ).toBe(true); + } + } + }); + + it('spot-checks well-known regions for exact profiles', () => { + const is = (k: string, oil: number, iron: number, food: number, industry: number) => { + const v = resources[k]; + expect(v, `missing resources for ${k}`).toBeDefined(); + expect(v!.oil, `oil for ${k}`).toBe(oil); + expect(v!.iron, `iron for ${k}`).toBe(iron); + expect(v!.food, `food for ${k}`).toBe(food); + expect(v!.industry, `industry for ${k}`).toBe(industry); + }; + is('california-kikh', 0.31, 0.1, 0.82, 0.97); // US-CA + is('arkhangel-sk-lhbk', 0.49, 0.52, 0.98, 0.82); // RU-ARK mainland core + is('pechora-qwhs', 0.11, 0.16, 1, 0.04); // RU-PEO (Arctic-coast band, #41) + is('yamal-gosw', 0.64, 1, 1, 0.49); // RU-YAM (Arctic-coast band, #41) + is('new-earth-eikt', 0.6, 0.56, 0.91, 0.66); // RU-ARK-NE (island group, #31) + is('severnaya-zemlya-awqp', 0.1, 0.48, 1, 0.3); // RU-ARK-SZ (island group, #31) + is('ain-lqtt', 0.94, 0.92, 0.51, 0.4); // FR-01 (Ain) + }); + + it('is deterministic: re-running the builder rewrites a byte-identical file', () => { + const file = path.join(root, 'public', 'region-resources.json'); + const before = readFileSync(file, 'utf8'); + // The builder is cwd-independent (it resolves the repo root from its own + // location) and idempotent: same input files (region-keys.json + the + // committed region-geo.json when present) + pure string hashing + fixed + // 2-dp rounding + stable (sorted) key order → identical bytes. + execFileSync(process.execPath, [path.join(root, 'scripts', 'build-region-resources.mjs')], { + cwd: root, + stdio: 'pipe', + }); + const after = readFileSync(file, 'utf8'); + expect(after).toBe(before); + }); +}); diff --git a/server/db.test.ts b/server/db.test.ts index 62d2c28..cfcbae0 100644 --- a/server/db.test.ts +++ b/server/db.test.ts @@ -36,6 +36,8 @@ function makeState(id: string): GameState { // (v0.35.0, #58) no active trades or embargoes. trades: [], embargoes: [], + // (v0.36.0, #59) no industry projects. + industry: [], }; } @@ -165,6 +167,17 @@ describe('openDb', () => { db.close(); }); + it('(v0.36.0 #59) a legacy row saved before the industry field existed loads with it defaulted to []', () => { + const db = openDb(':memory:'); + const legacy = makeState('legacy'); + delete (legacy as { industry?: unknown[] }).industry; // a pre-v0.36 save (field absent) + db.save(legacy); + const loaded = db.load('legacy'); + expect(loaded).not.toBeNull(); + expect(loaded!.industry).toEqual([]); + db.close(); + }); + it('delete removes a game by id and reports absence otherwise', () => { const db = openDb(':memory:'); db.save(makeState('a')); diff --git a/server/db.ts b/server/db.ts index 7d10f5f..1e1d086 100644 --- a/server/db.ts +++ b/server/db.ts @@ -57,6 +57,9 @@ export function openDb(filePath: string): Db { // legacy game has no active trades or embargoes. if (state.trades === undefined) state.trades = []; if (state.embargoes === undefined) state.embargoes = []; + // (v0.36, #59) Same for the industry layer: a legacy game has no + // active industry projects. + if (state.industry === undefined) state.industry = []; // (v0.28, #46) Rows saved before per-region stats existed are migrated // ONCE at load time (and never re-migrated afterwards — the field is // then present): each owned region is seeded with a copy of its owner's diff --git a/server/engine.test.ts b/server/engine.test.ts index 7ad1ab4..6528e19 100644 --- a/server/engine.test.ts +++ b/server/engine.test.ts @@ -16,6 +16,7 @@ import type { LlmClient, ToolDefinition, WireMessage } from './llm'; import { deterministicTurn, makeStubLlmClient } from './stub'; import { activeWarPairs, + applyIndustryEffects, applyNationOp, applyTurnResult, atWar, @@ -42,6 +43,7 @@ import { syncWarRelations, validateEconomyOps, validateHybridOps, + validateIndustryOps, validateMarkerOps, validateNationOps, validateRegionChanges, @@ -122,6 +124,8 @@ function baseState(): GameState { // (v0.35.0, #58) no active trades or embargoes on a fresh state. trades: [], embargoes: [], + // (v0.36.0, #59) no industry projects on a fresh state. + industry: [], }; } @@ -559,7 +563,7 @@ describe('validateNationOps (v0.23 #16 P4a)', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [{ kind: 'rename', nationRef: 'France', to: 'French Republic' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [{ kind: 'rename', nationRef: 'France', to: 'French Republic' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }); expect(withOps).not.toBeNull(); expect(withOps!.nationOps).toEqual([{ kind: 'rename', nationRef: 'France', to: 'French Republic' }]); @@ -581,7 +585,7 @@ describe('applyTurnResult (nation-op proposals, v0.23 #16 P4a)', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [{ kind: 'rename', nationRef: 'de', to: 'Reich' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [{ kind: 'rename', nationRef: 'de', to: 'Reich' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }); expect(next.nations.de.name).toBe('DE'); // still the old name expect(next.pendingNationOps).toEqual([{ kind: 'rename', nationRef: 'de', to: 'Reich' }]); @@ -602,7 +606,7 @@ describe('applyTurnResult (nation-op proposals, v0.23 #16 P4a)', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [{ kind: 'rename', nationRef: 'us', to: 'USA' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, // new proposal this turn + nationOps: [{ kind: 'rename', nationRef: 'us', to: 'USA' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, // new proposal this turn }); expect(next.pendingNationOps).toEqual([ { kind: 'rename', nationRef: 'de', to: 'Reich' }, // the old one survived @@ -621,7 +625,7 @@ describe('applyTurnResult (nation-op proposals, v0.23 #16 P4a)', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [{ kind: 'rename', nationRef: 'de', to: 'Reich' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [{ kind: 'rename', nationRef: 'de', to: 'Reich' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }); expect(next.pendingNationOps).toEqual([{ kind: 'rename', nationRef: 'de', to: 'Reich' }]); }); @@ -1078,7 +1082,7 @@ describe('applyTurnResult', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; applyTurnResult(state, result); expect(JSON.stringify(state)).toBe(snapshot); @@ -1095,7 +1099,7 @@ describe('applyTurnResult', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); expect(next.pending).toEqual([]); @@ -1118,7 +1122,7 @@ describe('applyTurnResult', () => { // is not a real key at all. Both are proposed as a gain by DE. territoryChanges: [{ nation: 'de', gain: ['wales-bbbb', 'not-a-region-xyz'], lose: [] }], unowned: [], - nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result, new Set(['wales-bbbb'])); // the valid key was gained (taken from its sole previous owner); the bogus one was ignored @@ -1144,7 +1148,7 @@ describe('applyTurnResult', () => { // released (not in state.unowned), so it does not enter GameState.unowned. territoryChanges: [{ nation: 'de', gain: ['POL', 'wales-bbbb'], lose: [] }], unowned: [], - nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); // no validKeys -> nothing filtered expect(next.nations.de.territory).toContain('wales-bbbb'); @@ -1162,7 +1166,7 @@ describe('applyTurnResult (sole-ownership invariants, v0.21 #16 P2)', () => { regionChanges: [], relations: [], unowned: [], - nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; it('a double claim (two different gainers, one key) is rejected: the key stays with its original owner', () => { @@ -1252,7 +1256,7 @@ describe('applyTurnResult (no man\'s land, v0.22 #16 P3)', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; it('a release removes the key from its sole owner and marks it in GameState.unowned', () => { @@ -1367,7 +1371,7 @@ describe('applyTurnResult (no man\'s land, v0.22 #16 P3)', () => { it('a lone release is meaningful (it survives the retry/nudge path)', () => { expect( - isMeaningful({ date: 'x', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], unowned: ['GBR'], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] } }), + isMeaningful({ date: 'x', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], unowned: ['GBR'], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] } }), ).toBe(true); }); @@ -1674,9 +1678,9 @@ describe('buildSystemPrompt (tool mode, v0.21 #16 P2)', () => { describe('isMeaningful', () => { it('is true with an event, false when everything is empty', () => { - expect(isMeaningful({ date: 'x', events: [{ nation: 'uk', type: 'military', title: 't', text: 'b', outcome: 'neutral' }], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] } })).toBe(true); - expect(isMeaningful({ date: 'x', events: [], stateChanges: [{ nation: 'uk', stat: 'military', op: 'set', value: 5 }], regionChanges: [], relations: [], territoryChanges: [], unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] } })).toBe(true); - expect(isMeaningful({ date: 'x', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] } })).toBe(false); + expect(isMeaningful({ date: 'x', events: [{ nation: 'uk', type: 'military', title: 't', text: 'b', outcome: 'neutral' }], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] } })).toBe(true); + expect(isMeaningful({ date: 'x', events: [], stateChanges: [{ nation: 'uk', stat: 'military', op: 'set', value: 5 }], regionChanges: [], relations: [], territoryChanges: [], unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] } })).toBe(true); + expect(isMeaningful({ date: 'x', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] } })).toBe(false); }); it('(v0.23 #16 P4a) a turn that only proposes a nation-op is meaningful (it survives the retry/nudge path)', () => { @@ -1689,7 +1693,7 @@ describe('isMeaningful', () => { relations: [], territoryChanges: [], unowned: [], - nationOps: [{ kind: 'rename', nationRef: 'de', to: 'Reich' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + nationOps: [{ kind: 'rename', nationRef: 'de', to: 'Reich' }], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }), ).toBe(true); }); @@ -1708,7 +1712,7 @@ describe('isMeaningful', () => { takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [{ type: 'city', name: 'Lyon', regionKey: 'rhone-rhne' }], remove: [] }, }), ).toBe(true); @@ -1728,7 +1732,7 @@ describe('isMeaningful', () => { takeovers: [{ nationRef: 'de', newRegimeName: 'The Reich' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }), ).toBe(true); @@ -1750,7 +1754,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'de', newRegimeName: 'The Reich' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1782,7 +1786,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'uk', newRegimeName: 'The Commonwealth' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1805,7 +1809,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'nonexistent', newRegimeName: 'New Name' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1831,7 +1835,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'UK', newRegimeName: 'The Empire' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1856,7 +1860,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'de', newRegimeName: ' ' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }); expect(validated!.takeovers).toEqual([]); @@ -1881,7 +1885,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { ], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1904,7 +1908,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'de', newRegimeName: 'The Reich' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1925,7 +1929,7 @@ describe('takeovers (regime change, v0.32.0 #54)', () => { takeovers: [{ nationRef: 'De', newRegimeName: 'The Reich' }], // 'De' → resolves to 'de' by name wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }; const next = applyTurnResult(state, result); @@ -1958,7 +1962,7 @@ describe('markers (point placement, v0.27 #44)', () => { takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [mk('city', 'Strasbourg', 'moselle-rygy')], remove: [] }, }; const next = applyTurnResult(state, result, undefined, centroidOf); @@ -1983,13 +1987,13 @@ describe('markers (point placement, v0.27 #44)', () => { const add = [mk('city', 'Strasbourg', 'moselle-rygy')]; const first = applyTurnResult(state, { date: '1939-09-03', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], - unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add, remove: [] }, + unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add, remove: [] }, }, undefined, centroidOf); expect(first.markers).toHaveLength(1); // a second turn proposes the exact same marker again const second = applyTurnResult(first, { date: '1939-09-05', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], - unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add, remove: [] }, + unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add, remove: [] }, }, undefined, centroidOf); expect(second.markers).toHaveLength(1); expect(second.markers[0].id).toBe(first.markers[0].id); // stable id, no second copy @@ -2014,7 +2018,7 @@ describe('markers (point placement, v0.27 #44)', () => { takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [ { type: 'city', name: 'Good', regionKey: 'moselle-rygy' }, // valid + centroid → kept @@ -2060,7 +2064,7 @@ describe('markers (point placement, v0.27 #44)', () => { takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [ { type: 'city', name: 'NewA', regionKey: 'new-a' }, @@ -2086,7 +2090,7 @@ describe('markers (point placement, v0.27 #44)', () => { ]; const next = applyTurnResult(state, { date: '1939-09-03', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], - unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [idA, 'zzzz-not-there'] }, + unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [idA, 'zzzz-not-there'] }, }, undefined, centroidOf); expect(next.markers).toHaveLength(1); expect(next.markers[0].id).toBe(idB); // only A removed; the bogus id was a no-op @@ -2102,14 +2106,14 @@ describe('markers (point placement, v0.27 #44)', () => { // 1) uk releases the region → the marker becomes ownerless const released = applyTurnResult(state, { date: '1939-09-03', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [], - unowned: ['moselle-rygy'], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + unowned: ['moselle-rygy'], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }, undefined, centroidOf); expect(released.markers[0].ownerNationId).toBeNull(); // 2) de re-claims the region → the marker's owner follows to de const reclaimed = applyTurnResult(released, { date: '1939-09-05', events: [], stateChanges: [], regionChanges: [], relations: [], territoryChanges: [{ nation: 'de', gain: ['moselle-rygy'], lose: [] }], - unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, markers: { add: [], remove: [] }, + unowned: [], nationOps: [], takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }, undefined, centroidOf); expect(reclaimed.markers[0].ownerNationId).toBe('de'); }); @@ -2177,7 +2181,7 @@ describe('markers (point placement, v0.27 #44)', () => { nationOps: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [{ type: 'city', name: 'Strasbourg', regionKey: 'moselle-rygy' }], remove: [] }, }); const { state } = await runTurn({ @@ -2251,6 +2255,8 @@ function mkTurnState( // (v0.35.0, #58) no active trades or embargoes on a fresh state. trades: [], embargoes: [], + // (v0.36.0, #59) no industry projects on a fresh state. + industry: [], }; } @@ -2268,6 +2274,7 @@ function mkTurnResult(partial: Partial): TurnResult { wars: partial.wars ?? { declare: [], end: [] }, hybrid: partial.hybrid ?? { ops: [] }, economy: partial.economy ?? { trade: [], embargo: [] }, + industry: partial.industry ?? { projects: [] }, markers: partial.markers ?? { add: [], remove: [] }, }; } @@ -2991,7 +2998,7 @@ describe('validateTakeovers (v0.32.0 #54)', () => { takeovers: [{ nationRef: 'de', newRegimeName: 'The Reich' }, { nationRef: 'bad', newRegimeName: '' }], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }); expect(withTakeovers).not.toBeNull(); @@ -3378,7 +3385,7 @@ describe('isMeaningful — wars (v0.33.0 #56)', () => { takeovers: [], wars: { declare: [{ sides: ['a', 'b'] }], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }), ).toBe(true); @@ -3398,7 +3405,7 @@ describe('isMeaningful — wars (v0.33.0 #56)', () => { takeovers: [], wars: { declare: [], end: [{ id: 'w1', outcome: 'armistice' }] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }), ).toBe(true); @@ -3418,7 +3425,7 @@ describe('isMeaningful — wars (v0.33.0 #56)', () => { takeovers: [], wars: { declare: [], end: [] }, hybrid: { ops: [] }, - economy: { trade: [], embargo: [] }, + economy: { trade: [], embargo: [] }, industry: { projects: [] }, markers: { add: [], remove: [] }, }), ).toBe(false); @@ -4128,5 +4135,217 @@ describe('stub — economy (v0.35.0 #58)', () => { }; const result = deterministicTurn(payload); expect(result.economy).toEqual({ trade: [], embargo: [] }); + expect(result.industry).toEqual({ projects: [] }); + }); +}); + +// --- Industry projects (v0.36.0, #59) ---------------------------------------- + +describe('validateIndustryOps (v0.36.0 #59)', () => { + it('accepts well-formed project ops', () => { + const out = validateIndustryOps({ projects: [{ regionKey: 'moselle-rygy', type: 'oil' }] }); + expect(out).toEqual({ projects: [{ regionKey: 'moselle-rygy', type: 'oil' }] }); + }); + + it('drops ops with a missing regionKey, an unknown type, or a non-object entry', () => { + const out = validateIndustryOps({ + projects: [ + { type: 'oil' }, // no regionKey + { regionKey: 'k1', type: 'coal' }, // unknown type + { regionKey: '', type: 'iron' }, // empty key + 'not-an-object', + null, + { regionKey: 'k2', type: 'food' }, // valid + ], + }); + expect(out).toEqual({ projects: [{ regionKey: 'k2', type: 'food' }] }); + }); + + it('a missing / malformed top-level object yields { projects: [] }', () => { + expect(validateIndustryOps(undefined)).toEqual({ projects: [] }); + expect(validateIndustryOps(null)).toEqual({ projects: [] }); + expect(validateIndustryOps('nope')).toEqual({ projects: [] }); + expect(validateIndustryOps({})).toEqual({ projects: [] }); + expect(validateIndustryOps({ projects: 'x' })).toEqual({ projects: [] }); + }); +}); + +describe('applyTurnResult — industry ops (v0.36.0 #59)', () => { + const state = () => + mkTurnState( + { + uk: mkNation('uk', NS(50, 50, 50, 50), ['g1', 'g2']), + de: mkNation('de', NS(50, 50, 50, 50), ['d1']), + }, + { g1: RS(50, 50, 50, 50), g2: RS(50, 50, 50, 50), d1: RS(50, 50, 50, 50) }, + ); + + it('declares a project on each valid region (per-region set)', () => { + const next = applyTurnResult(state(), mkTurnResult({ + industry: { projects: [{ regionKey: 'g1', type: 'oil' }, { regionKey: 'd1', type: 'industry' }] }, + })); + expect(next.industry).toEqual([ + { regionKey: 'g1', type: 'oil' }, + { regionKey: 'd1', type: 'industry' }, + ]); + }); + + it('re-declaring on a region that already hosts a project is a no-op (first type wins)', () => { + const s = state(); + s.industry = [{ regionKey: 'g1', type: 'oil' }]; + const next = applyTurnResult(s, mkTurnResult({ + industry: { projects: [{ regionKey: 'g1', type: 'iron' }, { regionKey: 'g2', type: 'food' }] }, + })); + expect(next.industry).toEqual([ + { regionKey: 'g1', type: 'oil' }, // the existing type is never replaced + { regionKey: 'g2', type: 'food' }, + ]); + }); + + it('drops a project whose region key is not in the valid-keys manifest', () => { + const next = applyTurnResult( + state(), + mkTurnResult({ industry: { projects: [{ regionKey: 'not-a-real-key-xyz', type: 'oil' }] } }), + new Set(['g1', 'g2', 'd1']), + ); + expect(next.industry).toEqual([]); + }); + + it('active projects persist across turns (the set is never cleared on commit)', () => { + const s = state(); + s.industry = [{ regionKey: 'g1', type: 'oil' }]; + const next = applyTurnResult(s, mkTurnResult({})); + expect(next.industry).toEqual([{ regionKey: 'g1', type: 'oil' }]); + }); +}); + +describe('applyIndustryEffects (v0.36.0 #59)', () => { + const mk = () => + mkTurnState( + { + uk: mkNation('uk', NS(50, 50, 50, 50), ['g1']), + de: mkNation('de', NS(50, 50, 50, 50), ['d1']), + }, + { g1: RS(50, 50, 50, 50), d1: RS(50, 50, 50, 50) }, + ); + + it('boosts the region\'s SOLE owner by the base value (no resource manifest)', () => { + const s = mk(); + s.industry = [{ regionKey: 'g1', type: 'oil' }]; + applyIndustryEffects(s); + expect(s.nations.uk.stats.economy).toBe(51); // 50 + 1 + expect(s.nations.de.stats.economy).toBe(50); // d1 hosts no project + // the boost is mirrored to every region the owner holds + expect(s.regionStats.g1.economy).toBe(51); + expect(s.regionStats.d1.economy).toBe(50); + }); + + it('adds one extra point when the region\'s industry value is >= 0.5 (and not below)', () => { + const s = mk(); + s.industry = [{ regionKey: 'g1', type: 'oil' }, { regionKey: 'd1', type: 'iron' }]; + applyIndustryEffects( + s, + (k) => (k === 'g1' + ? { oil: 0, iron: 0, food: 0, industry: 0.5 } // 0.5 >= 0.5 → boosted + : { oil: 0, iron: 0, food: 0, industry: 0.4 }), // 0.4 < 0.5 → base + ); + expect(s.nations.uk.stats.economy).toBe(52); // 1 + 1 + expect(s.nations.de.stats.economy).toBe(51); // 1 + 0 + }); + + it('a nation owning several project regions gets each of their boosts', () => { + const s = mk(); + s.nations.uk.territory = ['g1', 'd1']; + s.nations.de.territory = []; + s.industry = [{ regionKey: 'g1', type: 'oil' }, { regionKey: 'd1', type: 'iron' }]; + applyIndustryEffects(s); + expect(s.nations.uk.stats.economy).toBe(52); // 2 projects × base 1 + }); + + it('a project on an ownerless (released) region yields no boost but is kept', () => { + const s = mk(); + s.nations.uk.territory = []; // g1 is no man's land + s.industry = [{ regionKey: 'g1', type: 'oil' }]; + applyIndustryEffects(s); + expect(s.industry).toEqual([{ regionKey: 'g1', type: 'oil' }]); // kept, not removed + expect(s.nations.de.stats.economy).toBe(50); // nobody was boosted + }); + + it('a project on a region with 2+ owners (corrupt) yields no boost but is kept', () => { + const s = mk(); + s.nations.de.territory = ['d1', 'g1']; // corrupt: g1 has two owners + s.industry = [{ regionKey: 'g1', type: 'oil' }]; + applyIndustryEffects(s); + expect(s.industry).toEqual([{ regionKey: 'g1', type: 'oil' }]); // kept + expect(s.nations.uk.stats.economy).toBe(50); + expect(s.nations.de.stats.economy).toBe(50); + }); + + it('is a no-op when there are no active projects', () => { + const s = mk(); + applyIndustryEffects(s); + expect(s.nations.uk.stats.economy).toBe(50); + expect(s.nations.de.stats.economy).toBe(50); + }); +}); + +describe('isMeaningful — industry (v0.36.0 #59)', () => { + it('a project-only turn is meaningful; an empty industry is not', () => { + expect(isMeaningful(mkTurnResult({ industry: { projects: [{ regionKey: 'k', type: 'oil' }] } }))).toBe(true); + expect(isMeaningful(mkTurnResult({}))).toBe(false); + }); +}); + +describe('buildSystemPrompt — industry contract (v0.36.0 #59)', () => { + it('documents the industry field and its constraints in both modes', () => { + for (const withTools of [false, true]) { + const p = buildSystemPrompt(preset, withTools); + expect(p).toContain('"industry": {"projects":'); + expect(p).toContain('Industry ("industry") is the per-resource development lever'); + expect(p).toContain('do not re-declare one on a region that already has one'); + } + }); +}); + +describe('buildUserPrompt — industry (v0.36.0 #59)', () => { + const state = mkTurnState( + { a: mkNation('a', NS(50, 50, 50, 50), ['ra1']), b: mkNation('b', NS(50, 50, 50, 50), ['rb1']) }, + { ra1: RS(50, 50, 50, 50), rb1: RS(50, 50, 50, 50) }, + ); + + it('carries the resource aggregate and active projects when provided', () => { + const out = JSON.parse( + buildUserPrompt( + state, + [], + undefined, + undefined, + [], + [], + undefined, + undefined, + undefined, + undefined, + { a: { oil: 0.9, iron: 0.1, food: 0.5, industry: 0.2 } }, + [{ regionKey: 'ra1', type: 'oil' }], + ), + ); + expect(out.resources).toEqual({ a: { oil: 0.9, iron: 0.1, food: 0.5, industry: 0.2 } }); + expect(out.industry).toEqual([{ regionKey: 'ra1', type: 'oil' }]); + }); + + it('omits the resources/industry fields entirely when undefined', () => { + const out = JSON.parse(buildUserPrompt(state, [], undefined, undefined, [], [], undefined, undefined)); + expect(out).not.toHaveProperty('resources'); + expect(out).not.toHaveProperty('industry'); + }); +}); + +describe('runTurn — industry (v0.36.0 #59)', () => { + it('a result without an industry field leaves state.industry = [] (defensive init)', async () => { + const s = baseState(); + delete (s as { industry?: unknown[] }).industry; // simulate a pre-v0.36 row + const { state } = await runTurn({ llm: fakeLlm([validResult]), preset, state: s, items: [] }); + expect(state.industry).toEqual([]); }); }); diff --git a/server/engine.ts b/server/engine.ts index 68e8f4f..8e6dcbf 100644 --- a/server/engine.ts +++ b/server/engine.ts @@ -8,22 +8,26 @@ import type { EventOutcome, EventType, GameState, + IndustryProject, + IndustryType, MapMarker, Nation, NationStats, Preset, RelationStatus, + RegionResources, RegionStats, RoundItem, StatKey, TradeAgreement, War, } from '../shared/types'; -import { EVENT_TYPES, RELATION_STATUSES } from '../shared/types'; +import { EVENT_TYPES, INDUSTRY_TYPES, RELATION_STATUSES } from '../shared/types'; import { addDays, canConquer, clampStat, + deriveNationResources, deriveNationStats, fnv1a32, HYBRID_OP_TYPES, @@ -38,6 +42,7 @@ import { type EconomyTradeOp, type HybridOp, type HybridOpType, + type IndustryOps, type MarkerInfo, type MarkerSpec, type NationOp, @@ -70,6 +75,13 @@ export function isHybridOpType(t: unknown): t is HybridOpType { return typeof t === 'string' && VALID_HYBRID_TYPES.has(t); } +const VALID_INDUSTRY_TYPES = new Set(INDUSTRY_TYPES); + +/** True when `t` is one of the four known industry project types (v0.36, #59). */ +export function isIndustryType(t: unknown): t is IndustryType { + return typeof t === 'string' && VALID_INDUSTRY_TYPES.has(t); +} + // --- The LLM's getNeighbours tool (v0.21, #16 P2: contiguous region transfers) --- /** @@ -224,6 +236,7 @@ export function buildSystemPrompt(preset: Preset, withNeighboursTool = false): s ' "wars": {"declare":[{"sides":["",""],"aims":[""]}],"end":[{"id":"","outcome":"","terms":""}]},', ' "hybrid": {"ops":[{"type":"","from":"","target":"","detail":"","outcome":""}]},', ' "economy": {"trade":[{"a":"","b":"","lift":}],"embargo":[{"from":"","target":"","lift":}]},', + ' "industry": {"projects":[{"regionKey":"","type":""}]},', ' "markers": {"add":[{"type":"","name":"","regionKey":""}],"remove":[""]}', '}', '', @@ -245,6 +258,7 @@ export function buildSystemPrompt(preset: Preset, withNeighboursTool = false): s '- Wars ("wars") are named conflicts, each with a stable id. To DECLARE one, add {"declare":[{"sides":["",""],"aims":[...]}]} with at least 2 distinct belligerents: while it is active the engine AUTOMATICALLY sets both directions of every warring pair\'s relation to "war" and drags in the mutual-defense allies of each belligerent, so do NOT also emit a "war" relation for those pairs (you can never "make peace" between them without ending the war). To END an active war, add {"end":[{"id":"","outcome":""}]} — only active wars can be ended, and when one ends its belligerent pairs fall back to "hostile". Propose at most 1-2 declarations per turn and narrate each declaration and each ending in "events".', '- Covert / hybrid ops ("hybrid.ops") are non-kinetic operations — spies, sabotage, assassination attempts, cyberattacks, economic pressure, disinformation, and proxy support. Unlike territory they NEVER move borders: a successful op applies a small, deterministic effect (a small dip in the target\'s economy / stability / military for sabotage / assassinate / cyber / economic, or a relation nudge toward hostile for information / proxy), while an "exposed" op backfires (no effect, and the actor\'s relation with the target sours by one step toward hostile). "target" may be a nation id / name or a region key (a region key hits that region\'s sole owner). Keep each detail short, propose at most a few per turn, and narrate each op in "events".', '- Economy ("economy") is the trade & embargo layer: a bilateral trade (trade: {"a":"..","b":".."}) gives BOTH parties a small, deterministic economy gain every turn, while a unilateral embargo (embargo: {"from":"..","target":".."}) lowers only the TARGET\'s economy every turn. Omit "lift" to declare / impose, and set "lift":true to end or lift an existing one (the user message\'s "trades"/"embargoes" fields list what is currently active). Propose at most 1-2 operations per turn and narrate each one in "events". Trades and embargoes between nations at war are suspended automatically by the engine.', + '- Industry ("industry") is the per-resource development lever: each project is a building in one region you (or a nation) controls — {"regionKey":"","type":""} (an oil facility, an iron mine, a food operation, or a factory). Every committed turn each active project gives its region\'s owner a small, deterministic economy gain, the bigger the region\'s industry profile (see the "resources" field). A region holds at most one project — do not re-declare one on a region that already has one (the user message\'s "industry" field lists what is already built). Propose at most 1-2 new projects per turn and narrate each one in "events".', '- Prefer 1-4 events per turn; keep each text 1-3 sentences.', '- Keep your internal reasoning brief (a few sentences) and go straight to the JSON result; do not over-deliberate or re-derive facts already present in the state.', '- Keep every stat value between 0 and 100.', @@ -321,6 +335,22 @@ export function buildUserPrompt( * with `economy.embargo` + `lift: true`. Omitted entirely when undefined. */ embargoes?: Embargo[], + /** + * (v0.36, #59) Each nation's AGGREGATE resource profile (nation id -> the + * area×population-weighted mean of the resource profiles of the regions it + * owns, via `deriveNationResources`). Emitted verbatim (even when empty) so + * the model can reason about which nations are rich in which resource and + * where to build industry projects. Omitted entirely when undefined (no + * resource manifest loaded). + */ + nationResources?: Record, + /** + * (v0.36, #59) The game's currently ACTIVE industry projects (each a region + * key + project type). Emitted verbatim (even when empty) so the model knows + * which regions already host a project (and should not be re-declared) and + * can reference them. Omitted entirely when undefined. + */ + industryProjects?: IndustryProject[], ): string { const player = state.nations[state.playerNationId]; const playerName = player?.name ?? state.playerNationId; @@ -437,6 +467,8 @@ export function buildUserPrompt( if (relations !== undefined) payload.relations = relations; if (trades !== undefined) payload.trades = trades; if (embargoes !== undefined) payload.embargoes = embargoes; + if (nationResources !== undefined) payload.resources = nationResources; + if (industryProjects !== undefined) payload.industry = industryProjects; return JSON.stringify(payload, null, 2); } @@ -578,6 +610,7 @@ export function validateTurnResult( wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, + industry: { projects: [] }, markers: { add: [], remove: [] }, }; @@ -688,6 +721,14 @@ export function validateTurnResult( // ambiguous / self-pairing ops are dropped there, never thrown. result.economy = validateEconomyOps(o.economy); + // (v0.36, #59) Industry projects: the LLM names a region key + one of the + // four project types. Each project becomes an active entry in + // `GameState.industry` (a per-region SET). The region key is validated as a + // non-empty string here; whether the key is real and owned is checked at + // apply time (a project on a region with no sole owner yields no boost but + // is kept). Refs stay raw and the effect is deterministic at apply time. + result.industry = validateIndustryOps(o.industry); + // (v0.27, #44) Map-marker ops: new placements (validated here) and // removals by stable id. Applied by applyTurnResult after the territory // moves (a new marker's owner is the region's post-turn owner). @@ -962,6 +1003,34 @@ export function validateEconomyOps(raw: unknown): EconomyOps { return out; } +/** + * (v0.36, #59) Validate the raw `industry` object of a turn into a safe + * {@link IndustryOps}. Defensive like the rest of the parser — never throws. + * `projects`: each op needs a non-empty `regionKey` (capped at 120 chars) and a + * known project {@link IndustryType} (one of INDUSTRY_TYPES); ops with a + * missing/malformed field are dropped. The region key is kept raw here (like + * the hybrid / economy refs) — whether it is a *valid* region key, and whether + * its region ends the turn with a sole owner, is checked at apply time against + * the manifest and the final ownership (a project on a region with no sole + * owner yields no boost but is kept). A missing / malformed top-level object + * yields `{ projects: [] }`. + */ +export function validateIndustryOps(raw: unknown): IndustryOps { + const out: IndustryOps = { projects: [] }; + if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return out; + const o = raw as Record; + if (Array.isArray(o.projects)) { + for (const e of o.projects) { + if (!e || typeof e !== 'object') continue; + const p = e as Record; + const regionKey = str(p.regionKey, 120); + if (!regionKey || !isIndustryType(p.type)) continue; + out.projects.push({ regionKey, type: p.type }); + } + } + return out; +} + /** * (v0.33.0, #56) The UNORDERED pairs of belligerents of a set of ACTIVE * wars: a war with sides [a, b, c] contributes the pairs {a,b}, {a,c}, @@ -1368,8 +1437,127 @@ function suspendEconomyOnWar(next: GameState): void { next.embargoes = next.embargoes.filter((e) => !atWarNow(e.from, e.target)); } +// --- Industry projects: the per-region economy-boost lever (v0.36, #59) ------ + /** - * A turn is "meaningful" if it produced at least an event, a stat change, a + * (v0.36, #59) The BASE per-turn economy boost one industry project grants its + * region's sole owner. A project's actual boost is this base plus one extra + * point when the region's `industry` resource value is at least 0.5 (a region + * with a strong industry profile yields a bigger return). The base value is + * deliberately the same magnitude as {@link TRADE_ECONOMY_BONUS} / + * {@link EMBARGO_ECONOMY_PENALTY}. + */ +const INDUSTRY_ECONOMY_BONUS = 1; + +/** + * (v0.36, #59) The per-turn economy boost for ONE industry project sitting in + * `regionKey`: {@link INDUSTRY_ECONOMY_BONUS} plus one extra point when the + * region's `industry` resource value (from `resourceOf`) is at least 0.5. + * Without the resource manifest (or for a region with no profile) the boost is + * the base value. Pure + deterministic. + */ +function industryBoost( + regionKey: string, + resourceOf?: (key: string) => RegionResources | undefined, +): number { + const r = resourceOf?.(regionKey); + return INDUSTRY_ECONOMY_BONUS + (r && r.industry >= 0.5 ? 1 : 0); +} + +/** + * (v0.36, #59) Apply the turn's industry ops to `GameState.industry` as a + * PER-REGION SET: each op names a region key + a project type. A region key + * that is not a valid manifest key (`validKeys`, when supplied) is dropped; a + * region that already hosts a project is untouched (the first declared type + * wins — re-declaring on the same region is a no-op, the type is never + * replaced). Otherwise the project is appended. Mutates `next` in place. + * Nothing here throws. + */ +function applyIndustryOps( + next: GameState, + ops: IndustryOps, + validKeys?: ReadonlySet, +): void { + if (ops.projects.length === 0) return; + const has = (key: string) => next.industry.some((p) => p.regionKey === key); + for (const p of ops.projects) { + if (validKeys && !validKeys.has(p.regionKey)) continue; // unknown region key: drop + if (has(p.regionKey)) continue; // a region hosts at most one project + next.industry.push({ regionKey: p.regionKey, type: p.type }); + } +} + +/** + * (v0.36, #59) The per-turn economic effect of the industry layer, applied + * EVERY committed turn (not just to this turn's adds): each active project + * grants its region's SOLE owner a small, deterministic economy boost (see + * {@link industryBoost}) — clamped to 0–100, mirrored to every region the + * owner holds (`regionStats`), and each affected nation's derived stats are + * re-derived afterwards (the same 0-region / no-entry guards as + * `applyEconomyEffects`). A project whose region ends the turn with NO owner, + * or 2+ owners (released to no man's land / corrupt), yields no boost but is + * kept in the list. Sole ownership is untouched. No-op when there are no + * active projects. Never throws. + */ +export function applyIndustryEffects( + next: GameState, + resourceOf?: (key: string) => RegionResources | undefined, + geoOf?: (key: string) => { area: number; population: number } | undefined, +): void { + if (next.industry.length === 0) return; + + // Map each region key to its SOLE owner (a key with 0 or 2+ owners maps to + // nothing and yields no boost). + const ownerOf = new Map(); + { + const owners = new Map(); + for (const n of Object.values(next.nations)) { + for (const key of n.territory) { + const list = owners.get(key); + if (list) list.push(n.id); + else owners.set(key, [n.id]); + } + } + for (const [key, list] of owners) { + if (list.length === 1) ownerOf.set(key, list[0]); + } + } + + // nation id -> accumulated economy boost (a nation owning several project + // regions gets each of their boosts). + const delta = new Map(); + for (const p of next.industry) { + const owner = ownerOf.get(p.regionKey); + if (!owner) continue; // 0 or 2+ owners: no boost (the project is kept) + const n = next.nations[owner]; + if (!n) continue; // a nation removed this turn (a merge): the boost is dropped + delta.set(owner, (delta.get(owner) ?? 0) + industryBoost(p.regionKey, resourceOf)); + } + + const affected = new Set(); + for (const [id, d] of delta) { + const n = next.nations[id]; + if (!n) continue; + n.stats.economy = clampStat(n.stats.economy + d); + for (const key of n.territory) { + const rs = next.regionStats[key]; + if (rs) rs.economy = clampStat(rs.economy + d); + } + affected.add(id); + } + + if (affected.size > 0) { + for (const id of affected) { + const n = next.nations[id]; + if (n && n.territory.length > 0 && n.territory.some((k) => next.regionStats[k])) { + n.stats = deriveNationStats(n.territory, next.regionStats, geoOf); + } + } + } +} + +/** + * A turn is "meaningful" if it produced at least an event, a stat change, a stat change, a * no-man's-land release (v0.22 #16 P3: a release is a real world change even * when the model under-narrates it), a nation-op proposal (v0.23 #16 P4a: * a proposal is a real pending-world change the player will resolve, so it @@ -1397,6 +1585,9 @@ export function isMeaningful(result: TurnResult): boolean { // turn is a real world change (the active economy lists moved). result.economy.trade.length > 0 || result.economy.embargo.length > 0 || + // (v0.36, #59) an industry project built this turn is a real world change + // (the active project list moved). + result.industry.projects.length > 0 || // (v0.27, #44) a marker placed or removed this turn is a real world change. result.markers.add.length > 0 || result.markers.remove.length > 0 @@ -1441,6 +1632,13 @@ function genericUnclearEvent(state: GameState): TurnEventSpec { * (from the geo `properties.name`, via server/regions.ts) for the text of the * engine-emitted "invasion repelled" event; without it the event falls back to * the raw key. Pure either way. + * + * `resourceOf` (v0.36, #59) resolves a region key to its synthesized resource + * profile (`{ oil, iron, food, industry }`, from public/region-resources.json + * via server/regions.ts). It is used to scale each industry project's per-turn + * economy boost by the region's `industry` value (a region with a strong + * industry profile yields a bigger return). Without it the boost is the + * unscaled base value — the engine stays pure and deterministic either way. */ export function applyTurnResult( state: GameState, @@ -1449,12 +1647,16 @@ export function applyTurnResult( centroidOf?: (key: string) => { lat: number; lon: number; spread: number } | undefined, geoOf?: (key: string) => { area: number; population: number } | undefined, regionNameOf?: (key: string) => string | undefined, + resourceOf?: (key: string) => RegionResources | undefined, ): GameState { const next: GameState = JSON.parse(JSON.stringify(state)); next.version = (state.version ?? 0) + 1; // every mutation is a new revision // (v0.28, #46) per-region stats table; a legacy/corrupt clone without the // field starts empty (the turn then re-inits claimed regions as it goes). next.regionStats = next.regionStats ?? {}; + // (v0.36, #59) active industry projects; a legacy/corrupt clone without the + // field starts empty (the turn then only ever adds to it). + next.industry = next.industry ?? []; const actingTurn = state.turn; // this action resolves the current turn next.turn = state.turn + 1; // then we advance to the next turn to play next.date = isDateLike(result.date) ? result.date : addDays(state.date, 2); @@ -1779,6 +1981,27 @@ export function applyTurnResult( suspendEconomyOnWar(next); applyEconomyEffects(next, geoOf); + // --- Industry projects (v0.36, #59): per-region economy-boost lever --- + // + // Placed AFTER the economy block (both move stats, and the industry boost + // should compose with the trade/embargo effects of the same turn) and + // before markers / nationOps. Order: + // (1) APPLY OPS: this turn's `industry.projects` are added to + // `GameState.industry` as a per-region SET — a region key that is not + // a valid manifest key is dropped, and a region that already hosts a + // project is untouched (the first declared type wins; re-declaring is + // a no-op). + // (2) PER-TURN EFFECT: the FULL active project list (not just this + // turn's adds) each grants their region's SOLE owner a small, + // deterministic economy boost scaled by the region's `industry` + // resource value — clamped, mirrored to every region the owner holds, + // and re-derived like the economy/hybrid effects. A project whose + // region ends the turn with no owner (or 2+ owners) yields no boost + // but is KEPT (the region may be re-claimed later). Sole ownership is + // untouched (the layer moves stats, never territory). + applyIndustryOps(next, result.industry, validKeys); + applyIndustryEffects(next, resourceOf, geoOf); + // --- Map markers (v0.27, #44) --- // // Markers are anchored to a region key and are processed against the FINAL @@ -2250,8 +2473,17 @@ export async function runTurn(opts: { * it falls back to the raw region key. Pure either way. */ regionNameOf?: (key: string) => string | undefined; + /** + * (v0.36, #59) Region-key -> synthesized resource profile resolver (from + * public/region-resources.json via server/regions.ts). Present, each + * industry project's per-turn economy boost is scaled by its region's + * `industry` value, and each nation's aggregate resource profile is carried + * in the user prompt; absent, industry boosts use the unscaled base value + * and the profile is omitted. + */ + resourceOf?: (key: string) => RegionResources | undefined; }): Promise<{ state: GameState; result: TurnResult }> { - const { llm, preset, state, items, regionReference, validRegionKeys, getNeighbours, centroidOf, geoOf, regionKeyResolver, regionNameOf } = opts; + const { llm, preset, state, items, regionReference, validRegionKeys, getNeighbours, centroidOf, geoOf, regionKeyResolver, regionNameOf, resourceOf } = opts; const chatWithTools = llm.chatWithTools; const useTools = getNeighbours !== undefined && chatWithTools !== undefined; const system = buildSystemPrompt(preset, useTools); @@ -2282,6 +2514,20 @@ export async function runTurn(opts: { // starting point before an `exposed` backfire). Always emitted ({} when the // player has no relations yet). const relations = state.nations[state.playerNationId]?.relations ?? {}; + // (v0.36, #59) each nation's AGGREGATE resource profile (the area×population- + // weighted mean of the resource profiles of the regions it owns). Carried in + // the user prompt ONLY when the resource manifest is loaded (resourceOf + // present); otherwise omitted (undefined) so the prompt — and the stub — + // stay identical to the no-manifest case. + const nationResources = + resourceOf === undefined + ? undefined + : Object.fromEntries( + Object.values(state.nations).map((n) => [ + n.id, + deriveNationResources(n.territory, resourceOf, geoOf), + ]), + ); const user = buildUserPrompt( state, items, @@ -2295,6 +2541,12 @@ export async function runTurn(opts: { // reference — and `lift` — what is currently in force. state.trades, state.embargoes, + // (v0.36, #59) the aggregate resource profiles (undefined without the + // manifest) + the active industry projects, so the model knows which + // regions already host a project and which nations are rich in which + // resource. + nationResources, + state.industry ?? [], ); const nudge = 'Your previous output was invalid. Respond with ONLY the JSON object described above for this batch — no prose, no fences.'; @@ -2351,12 +2603,13 @@ export async function runTurn(opts: { wars: { declare: [], end: [] }, hybrid: { ops: [] }, economy: { trade: [], embargo: [] }, + industry: { projects: [] }, markers: { add: [], remove: [] }, }; } return { - state: applyTurnResult(state, result, validRegionKeys, centroidOf, geoOf, regionNameOf), + state: applyTurnResult(state, result, validRegionKeys, centroidOf, geoOf, regionNameOf, resourceOf), result, }; } diff --git a/server/index.ts b/server/index.ts index be39b39..4afe09f 100644 --- a/server/index.ts +++ b/server/index.ts @@ -25,7 +25,7 @@ import { makeScenarioStubLlmClient } from './stubScenario'; import { finalizeWorld, generateDraft } from './scenario'; import { askAdvisor, confirmNationOp, queueRoundItem, rejectNationOp, removeRoundItem, resolveRegionKey, runTurn } from './engine'; import { buildRegionMap } from './map'; -import { allTerritoryKeys, centroidOf, expandCountriesToKeys, geoOf, hasAdjacency, hasCentroids, hasGeo, loadRegions, neighboursOf, referenceForKeys, regionName, validCountryCodes, validKeys } from './regions'; +import { allTerritoryKeys, centroidOf, expandCountriesToKeys, geoOf, hasAdjacency, hasCentroids, hasGeo, hasResources, loadRegions, neighboursOf, referenceForKeys, regionName, resourceOf, validCountryCodes, validKeys } from './regions'; import { createPresetStore } from './presets'; import { createTemplateStore } from './templates'; import { openDb, type Db } from './db'; @@ -186,6 +186,10 @@ app.post('/api/games', (req: Request, res) => { // declares (and lifts) them over time via TurnResult.economy. trades: [], embargoes: [], + // (v0.36.0, #59) No active industry projects on a fresh game; the LLM + // declares them over time via TurnResult.industry (one per region, a + // per-region SET). + industry: [], }; // v0.19 (#16 P1): expand each nation's ISO_A3 country list to the region keys // of all its sub-regions, so ownership (and the choropleth) is at region @@ -370,6 +374,12 @@ app.post('/api/games/:id/jump', async (req, res) => { // event (geo properties.name, else the raw key). Always on — the // resolver is pure and degrades to the key when the manifest is absent. regionNameOf: (k) => regionName(k), + // (v0.36.0, #59) when the region-resources manifest (the synthesized + // per-region resource profiles) loaded, hand the engine the resolver — + // the industry boost is then scaled by each region's `industry` value + // (without it boosts use the unscaled base value) and each nation's + // aggregate resource profile is carried in the user prompt. + resourceOf: hasResources() ? (key) => resourceOf(key) : undefined, }); db.save(state); broadcast(id, 'turn', { state, result }); diff --git a/server/map.test.ts b/server/map.test.ts index 2ea5a9a..87c4993 100644 --- a/server/map.test.ts +++ b/server/map.test.ts @@ -57,6 +57,8 @@ const state: GameState = { // (v0.35.0, #58) the map is ownership-only; trades/embargoes are unused here. trades: [], embargoes: [], + // (v0.36.0, #59) the map is ownership-only; industry is unused here. + industry: [], }; // The RegionMap built from the fixture: the authoritative region key → owner source. diff --git a/server/protocol.test.ts b/server/protocol.test.ts index 38d00f2..cfa86a1 100644 --- a/server/protocol.test.ts +++ b/server/protocol.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'; import { canConquer, CONQUEST_MILITARY_MARGIN, + deriveNationResources, deriveNationStats, migrateRegionStats, seedRegionStats, @@ -44,6 +45,7 @@ function mkState( wars: [], trades: [], embargoes: [], + industry: [], }; if (regionStats !== undefined) base.regionStats = regionStats as GameState['regionStats']; else delete (base as { regionStats?: unknown }).regionStats; // simulate a legacy row @@ -139,6 +141,81 @@ describe('deriveNationStats', () => { }); }); +// --- deriveNationResources --------------------------------------------------- + +describe('deriveNationResources (v0.36.0 #59)', () => { + const prof: Record = { + a: { oil: 0.2, iron: 0.2, food: 0.2, industry: 0.2 }, + b: { oil: 0.8, iron: 0.8, food: 0.8, industry: 0.8 }, + }; + const geo: Record = { + a: { area: 100, population: 1000 }, + b: { area: 1000, population: 1000 }, + }; + + it('weights by area×population: the larger region dominates the average', () => { + // a: weight 100×1000=100000, b: weight 1000×1000=1000000 + // → (0.2×1e5 + 0.8×1e6)/1.1e6 = 82/110 = 0.7454… → 0.75 on every axis + expect(deriveNationResources(['a', 'b'], (k) => prof[k], (k) => geo[k])).toEqual({ + oil: 0.75, iron: 0.75, food: 0.75, industry: 0.75, + }); + }); + + it('degrades to a uniform (unweighted) average without geo: equal weights', () => { + // equal weights 1,1 → the true mean 0.5 on every axis + expect(deriveNationResources(['a', 'b'], (k) => prof[k])).toEqual({ + oil: 0.5, iron: 0.5, food: 0.5, industry: 0.5, + }); + // same when geoOf is provided but returns undefined for the keys (missing geo) + expect(deriveNationResources(['a', 'b'], (k) => prof[k], () => undefined)).toEqual({ + oil: 0.5, iron: 0.5, food: 0.5, industry: 0.5, + }); + }); + + it('skips a region key that has no resource-profile entry', () => { + // b has no profile → only a is counted → a's values + const out = deriveNationResources(['a', 'b'], (k) => (k === 'a' ? prof.a : undefined), (k) => geo[k]); + expect(out).toEqual(prof.a); + }); + + it('returns the zero profile when none of the owned regions has a profile', () => { + expect(deriveNationResources(['a', 'b'], () => undefined)).toEqual({ + oil: 0, iron: 0, food: 0, industry: 0, + }); + }); + + it('a single region yields exactly that region\'s profile', () => { + expect(deriveNationResources(['a'], (k) => prof[k], (k) => geo[k])).toEqual(prof.a); + }); + + it('treats zero/negative area or population as a fallback weight of 1', () => { + // a: area 0 → weight 1×1000=1000; b: full weight 1e6 → b dominates + const g: Record = { + a: { area: 0, population: 1000 }, + b: { area: 1000, population: 1000 }, + }; + expect(deriveNationResources(['a', 'b'], (k) => prof[k], (k) => g[k])).toEqual({ + oil: 0.8, iron: 0.8, food: 0.8, industry: 0.8, + }); + }); + + it('rounds each axis to 2 decimal places', () => { + // a=0.2 (w=1×1=1) + b=0.4 (w=2×1=2) → (0.2×1 + 0.4×2)/(1+2) = 1.0/3 = 0.3333… → 0.33 + const g: Record = { + a: { area: 1, population: 1 }, + b: { area: 2, population: 1 }, + }; + const out = deriveNationResources( + ['a', 'b'], + (k) => k === 'a' + ? { oil: 0.2, iron: 0.2, food: 0.2, industry: 0.2 } + : { oil: 0.4, iron: 0.4, food: 0.4, industry: 0.4 }, + (k) => g[k], + ); + expect(out).toEqual({ oil: 0.33, iron: 0.33, food: 0.33, industry: 0.33 }); + }); +}); + // --- seedRegionStats --------------------------------------------------------- describe('seedRegionStats', () => { diff --git a/server/regions.test.ts b/server/regions.test.ts index 28c8ae9..0e816c9 100644 --- a/server/regions.test.ts +++ b/server/regions.test.ts @@ -12,11 +12,13 @@ import { hasCentroids, hasGeo, hasRegionData, + hasResources, loadRegions, neighboursOf, referenceForKeys, regionName, resetRegions, + resourceOf, validKeys, } from './regions'; import type { GameState } from '../shared/types'; @@ -114,6 +116,8 @@ describe('regions (region-key loader, v0.19 #16 P1)', () => { // (v0.35.0, #58) unused here (allTerritoryKeys is ownership-only). trades: [], embargoes: [], + // (v0.36.0, #59) unused here (allTerritoryKeys is ownership-only). + industry: [], }; // 16 GBR sub-regions + 42 FRA sub-regions, no overlap between the two. expect(allTerritoryKeys(state).size).toBe(58); @@ -172,6 +176,16 @@ describe('regions (region-key loader, v0.19 #16 P1)', () => { expect(geoOf('not-a-real-key-xyz')).toBeUndefined(); }); + it('(v0.36 #59) hasResources() is true and resourceOf resolves a real key to a 4-value profile', () => { + expect(hasResources()).toBe(true); + // exact spot-check values pinned from the committed manifest (Ain, FRA) + expect(resourceOf('ain-lqtt')).toEqual({ oil: 0.94, iron: 0.92, food: 0.51, industry: 0.4 }); + }); + + it('(v0.36 #59) resourceOf returns undefined for an unknown key', () => { + expect(resourceOf('not-a-real-key-xyz')).toBeUndefined(); + }); + describe('graceful degradation with no region data', () => { beforeEach(() => resetRegions()); @@ -191,6 +205,9 @@ describe('regions (region-key loader, v0.19 #16 P1)', () => { // and no region-geo: the per-region stats weighting degrades to uniform expect(hasGeo()).toBe(false); expect(geoOf('ain-lqtt')).toBeUndefined(); + // and no region-resources: industry boosts use the unscaled base value + expect(hasResources()).toBe(false); + expect(resourceOf('ain-lqtt')).toBeUndefined(); }); }); @@ -248,6 +265,19 @@ describe('loadRegions resolves the manifest per environment (dev public/ vs prod // and no region-geo (not copied into this dist/) -> stats weighting is uniform expect(hasGeo()).toBe(false); expect(geoOf('ain-lqtt')).toBeUndefined(); + // and no region-resources (not copied into this dist/) -> boosts unscaled + expect(hasResources()).toBe(false); + expect(resourceOf('ain-lqtt')).toBeUndefined(); + }); + + it('(v0.36 #59) a dist/ WITH the region-resources manifest loads it (prod layout)', () => { + copyFileSync( + path.join(realRoot, 'public', 'region-resources.json'), + path.join(prodRoot, 'dist', 'region-resources.json'), + ); + expect(loadRegions(prodRoot)).toBe(true); + expect(hasResources()).toBe(true); + expect(resourceOf('ain-lqtt')).toEqual({ oil: 0.94, iron: 0.92, food: 0.51, industry: 0.4 }); }); it('(v0.27 #44) a dist/ WITH the centroids manifest loads them (prod layout)', () => { diff --git a/server/regions.ts b/server/regions.ts index 27ec3cd..c0c6fad 100644 --- a/server/regions.ts +++ b/server/regions.ts @@ -19,6 +19,9 @@ // — the data behind LLM-placed map markers (v0.27, #44) // - geoOf(): a region key's area (km²) + population (from region-geo.json) // — the weighting source for the per-region stats model (v0.28, #46) +// - resourceOf(): a region key's synthesized resource profile (from +// region-resources.json) — the data behind the LLM's industry lever +// (v0.36, #59) // // Deliberately turf-free: it reads the JSON files with plain JSON.parse and // never imports @turf/@types/geojson (importing one pulls @types/geojson into @@ -26,7 +29,7 @@ // Loaded once at boot; the accessors below are pure data reads thereafter. import { existsSync, readFileSync } from 'node:fs'; import path from 'node:path'; -import type { GameState } from '../shared/types'; +import type { GameState, RegionResources } from '../shared/types'; /** { name, parent } for one sub-region, where parent is the ISO_A3 country. */ interface RegionInfo { @@ -49,6 +52,8 @@ interface RegionData { centroids: Record; /** region key -> { area (km²), population } (from public/region-geo.json, v0.28 #46). */ geo: Record; + /** region key -> resource profile (from public/region-resources.json, v0.36 #59). */ + resources: Record; } let data: RegionData | null = null; @@ -77,6 +82,7 @@ export function loadRegions(root: string): boolean { const adjacencyFile = 'region-adjacency.json'; const centroidsFile = 'region-centroids.json'; const regionGeoFile = 'region-geo.json'; + const regionResourcesFile = 'region-resources.json'; const base = [ path.join(root, 'public'), // dev: Vite serves public/ at / path.join(root, 'dist'), // prod: Vite copies public/* -> dist/ (== clientDir) @@ -185,7 +191,40 @@ export function loadRegions(root: string): boolean { } } - data = { idToKey, keyToInfo, keysByCountry, validKeys, adjacency, centroids, geo }; + // The region-resources manifest (v0.36, #59): a synthesized four-value + // resource profile per region key — the data behind the LLM's industry + // lever. OPTIONAL like the others: a missing/broken file means "no + // resource data" — industry boosts degrade to the unscaled base value and + // the prompt omits the aggregate profile — while everything else keeps + // working. + let resources: Record = {}; + const resourcesPath = path.join(base, regionResourcesFile); + if (existsSync(resourcesPath)) { + try { + const raw = JSON.parse(readFileSync(resourcesPath, 'utf8')) as Record< + string, + { oil?: unknown; iron?: unknown; food?: unknown; industry?: unknown } + >; + // Keep only well-formed entries (all four values finite numbers in + // [0, 1]); a corrupt file degrades to "none". + for (const [k, v] of Object.entries(raw)) { + if ( + v && + typeof v.oil === 'number' && Number.isFinite(v.oil) && v.oil >= 0 && v.oil <= 1 && + typeof v.iron === 'number' && Number.isFinite(v.iron) && v.iron >= 0 && v.iron <= 1 && + typeof v.food === 'number' && Number.isFinite(v.food) && v.food >= 0 && v.food <= 1 && + typeof v.industry === 'number' && Number.isFinite(v.industry) && v.industry >= 0 && v.industry <= 1 + ) { + resources[k] = { oil: v.oil, iron: v.iron, food: v.food, industry: v.industry }; + } + } + } catch (err) { + console.error('[regions] failed to load region-resources.json, continuing without it', err); + resources = {}; + } + } + + data = { idToKey, keyToInfo, keysByCountry, validKeys, adjacency, centroids, geo, resources }; return validKeys.size > 0; } catch (err) { console.error('[regions] failed to load region data', err); @@ -322,6 +361,29 @@ export function geoOf(key: string): { area: number; population: number } | undef return data?.geo[key]; } +/** + * True when the region-resources manifest loaded with at least one entry + * (v0.36, #59). The server's jump route uses this to decide whether to hand + * the engine a resource resolver (which lets a turn scale industry boosts by a + * region's `industry` value and carry each nation's aggregate resource profile + * in the LLM prompt) or skip both (industry boosts fall back to the unscaled + * base value). + */ +export function hasResources(): boolean { + return data !== null && Object.keys(data.resources).length > 0; +} + +/** + * The synthesized resource profile for a region key (v0.36, #59): the + * four-value `{ oil, iron, food, industry }` from the committed + * `public/region-resources.json`. `undefined` for an unknown key or when no + * resource data is loaded (industry boosts then use the unscaled base value, + * and the aggregate profile is simply omitted from the prompt). + */ +export function resourceOf(key: string): RegionResources | undefined { + return data?.resources[key]; +} + /** * The union of the region keys that share a land border with any of the given * keys — deduplicated, the queried keys themselves excluded, and sorted for diff --git a/server/stub.ts b/server/stub.ts index fd791d6..7ccb9a7 100644 --- a/server/stub.ts +++ b/server/stub.ts @@ -67,6 +67,20 @@ export interface StubPayload { * covered by unit tests only. */ embargoes?: Array<{ from: string; target: string }>; + /** + * (v0.36.0, #59) Each nation's aggregate resource profile + * (`{ oil, iron, food, industry }`), emitted by the engine's user prompt. + * The stub ignores this field — it never declares an industry project (see + * deterministicTurn), so the industry path is covered by unit tests only. + */ + resources?: Record; + /** + * (v0.36.0, #59) The currently active industry projects + * (`{ regionKey, type }`), emitted by the engine's user prompt. The stub + * ignores this field — it never declares an industry project (see + * deterministicTurn), so the industry path is covered by unit tests only. + */ + industry?: Array<{ regionKey: string; type: string }>; } function truncate(s: string, n: number): string { @@ -123,6 +137,10 @@ function truncate(s: string, n: number): string { * or an embargo (it always returns `economy: { trade: [], embargo: [] }`) — * the trade & embargo economy path is covered by unit tests only, keeping * the e2e assertions untouched. + * + * (v0.36.0, #59) The stub likewise NEVER declares an industry project (it + * always returns `industry: { projects: [] }`) — the per-region industry + * path is covered by unit tests only, keeping the e2e assertions untouched. */ export function deterministicTurn(p: StubPayload): TurnResult { const state = p.state; @@ -193,6 +211,7 @@ export function deterministicTurn(p: StubPayload): TurnResult { wars: { declare: [], end: [] }, // the stub never declares/ends wars (see doc comment) hybrid: { ops: [] }, // the stub never runs hybrid/covert ops (see doc comment) economy: { trade: [], embargo: [] }, // the stub never touches trades/embargoes (see doc comment) + industry: { projects: [] }, // the stub never declares industry projects (see doc comment) markers: { add: [], remove: [] }, // the stub never touches markers (see doc comment) }; } diff --git a/shared/protocol.ts b/shared/protocol.ts index 06964e9..edc8489 100644 --- a/shared/protocol.ts +++ b/shared/protocol.ts @@ -6,10 +6,12 @@ import type { EventOutcome, EventType, GameState, + IndustryProject, MarkerType, Nation, NationStats, RelationStatus, + RegionResources, RegionStats, StatKey, } from './types'; @@ -416,6 +418,21 @@ export interface EconomyOps { embargo: EconomyEmbargoOp[]; } +/** + * (v0.36, #59) The turn's INDUSTRY operations, nested under + * `TurnResult.industry`. `projects` lists the industry projects the LLM builds + * this turn: each names a **region key** (the region must be valid, and — for + * the boost to take effect — will need a sole owner at apply time) and one of + * the four project {@link IndustryType}s. The engine applies each project to + * `GameState.industry` (a per-region SET — a region already hosting a project + * keeps the first one declared; a region key not in the valid manifest is + * dropped, never thrown). Required; default `{ projects: [] }`. + */ +export interface IndustryOps { + /** The industry projects built this turn (region key + type). */ + projects: IndustryProject[]; +} + /** The exact JSON object the world-simulator LLM must return for a turn. */ export interface TurnResult { date: string; @@ -506,6 +523,20 @@ export interface TurnResult { * suspended automatically. */ economy: EconomyOps; + /** + * (v0.36, #59) Industry projects built this turn — the LLM's "industry" + * lever. `projects` lists `{ regionKey, type }` pairs: the model names a + * region it (believes it) controls and one of the four project types + * (`oil` / `iron` / `food` / `industry`). Applied directly by + * `applyTurnResult`: each project is added to `GameState.industry` (a + * per-region SET — re-declaring on a region that already has a project is a + * no-op), and on every committed turn each active project gives its region's + * SOLE owner a small, deterministic economy boost scaled by that region's + * `industry` resource value (a region with no owner, or 2+ owners, yields no + * boost but keeps its project). They never move borders — sole ownership is + * untouched. Required; default `{ projects: [] }`. + */ + industry: IndustryOps; /** * (v0.27, #44) Map-marker ops this turn. `add` places new named markers * (the engine positions each at its region's centroid + a small @@ -954,3 +985,49 @@ export function migrateRegionStats( } return next; } + +/** + * (v0.36, #59) Derive a nation's aggregate {@link RegionResources} from the + * resource profiles of the regions it owns: each of the four resource values is + * the **area×population-weighted AVERAGE** (an average — not a median — is the + * meaningful aggregation for an abundance profile) over the nation's owned + * region keys. A region's weight is the same + * `(area > 0 ? area : 1) × (population > 0 ? population : 1)` as + * {@link deriveNationStats} — both factors fall back to 1 when the region has + * no geo entry (`geoOf` returns `undefined` for it), so every region carries + * weight ≥ 1 and a missing geo degrades gracefully to a uniform (unweighted) + * average. A region key with no resource-profile entry (`resourceOf` returns + * `undefined` for it — the manifest is not loaded, or the key is absent) is + * skipped. Returns the zero profile when the nation owns no region with a + * profile. Pure + shared. + */ +export function deriveNationResources( + regionKeys: string[], + resourceOf?: (key: string) => RegionResources | undefined, + geoOf?: (key: string) => { area: number; population: number } | undefined, +): RegionResources { + const zero: RegionResources = { oil: 0, iron: 0, food: 0, industry: 0 }; + const sums: Record = { oil: 0, iron: 0, food: 0, industry: 0 }; + let totalW = 0; + for (const key of regionKeys) { + const r = resourceOf?.(key); + if (!r) continue; // a key with no resource profile is skipped + const g = geoOf?.(key); + const a = g && g.area > 0 ? g.area : 1; + const p = g && g.population > 0 ? g.population : 1; + const w = a * p; + totalW += w; + sums.oil += r.oil * w; + sums.iron += r.iron * w; + sums.food += r.food * w; + sums.industry += r.industry * w; + } + if (totalW <= 0) return zero; + const round2 = (v: number) => Math.round(v * 100) / 100; + return { + oil: round2(sums.oil / totalW), + iron: round2(sums.iron / totalW), + food: round2(sums.food / totalW), + industry: round2(sums.industry / totalW), + }; +} diff --git a/shared/scenario.ts b/shared/scenario.ts index facc4db..2245023 100644 --- a/shared/scenario.ts +++ b/shared/scenario.ts @@ -459,6 +459,8 @@ export function worldDraftToGameState( // (v0.35.0, #58) No trades/embargoes on a fresh (dynamic) game. trades: [], embargoes: [], + // (v0.36, #59) No industry projects on a fresh (dynamic) game. + industry: [], }; return state; } diff --git a/shared/types.ts b/shared/types.ts index 1e41991..3f95900 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -26,6 +26,23 @@ export interface RegionStats { population: number; } +/** + * (v0.36, #59) A region's synthesized four-value resource profile — each value + * a finite fraction in [0, 1]. Built once per region key by + * `scripts/build-region-resources.mjs` into the committed + * `public/region-resources.json` (the engine reads it via `regions.resourceOf`). + * The engine scales a region's per-turn industry boost by its `industry` value, + * and a nation's aggregate profile (the area×population-weighted mean of its + * owned regions' profiles, see `protocol.deriveNationResources`) is what the + * LLM prompt carries so the model can reason about where to build. + */ +export interface RegionResources { + oil: number; + iron: number; + food: number; + industry: number; +} + export const STAT_KEYS = ['military', 'economy', 'stability', 'population'] as const; export type StatKey = (typeof STAT_KEYS)[number]; @@ -174,6 +191,36 @@ export interface Embargo { target: string; } +// --- Resources & industry (v0.36, #59) --------------------------------------- +// +// The LLM can build per-region INDUSTRY PROJECTS (an oil facility, an iron +// mine, a food operation, or a factory) on regions it controls; each active +// project gives that region's sole owner a small, deterministic economy boost +// every committed turn, scaled by the region's `industry` resource value from +// the committed resource manifest. The active projects live in +// `GameState.industry` — the LLM's "industry" lever. + +/** The four industry project types a region can host (v0.36, #59). */ +export type IndustryType = 'oil' | 'iron' | 'food' | 'industry'; + +/** All industry project types, in canonical order (the LLM contract + validator). */ +export const INDUSTRY_TYPES: IndustryType[] = ['oil', 'iron', 'food', 'industry']; + +/** + * (v0.36, #59) One active industry project: a building of a given + * {@link IndustryType} in a specific region. The engine keys the per-turn + * economy boost by the region's SOLE owner (a region with no owner or 2+ + * owners yields no boost) and scales it by the region's `industry` resource + * value. A region hosts at most ONE project — re-declaring on a region that + * already has one is a no-op (the first declared type wins). + */ +export interface IndustryProject { + /** The region key the project sits in (see `public/region-keys.json`). */ + regionKey: string; + /** The kind of project built there (see {@link IndustryType}). */ + type: IndustryType; +} + /** * (v0.33.0, #56) A first-class **war** — a named, ongoing armed conflict * between two or more nations. Unlike the boolean `war` relation (which a @@ -356,6 +403,18 @@ export interface GameState { * no data wipe. */ embargoes: Embargo[]; + /** + * (v0.36, #59) Active industry projects (see {@link IndustryProject}): built + * by a turn's `industry.projects` ops (the LLM names a region key + a + * project type). Each region hosts at most one project — re-declaring on a + * region that already has one is a no-op. Every committed turn the engine + * gives each project's region's SOLE owner a small, deterministic economy + * boost scaled by that region's `industry` resource value. A project on a + * region that ends a turn with no owner (or 2+ owners) yields no boost but + * is NOT removed. Always `[]` on a fresh game; rows saved before v0.36 load + * with this defaulted to `[]` (see server/db.ts) — additive, no data wipe. + */ + industry: IndustryProject[]; } /**