From 07644ffdbe93ac871be8c8c622a8be66962f7e1f Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Sat, 26 Sep 2026 08:37:10 +0000 Subject: [PATCH] India by state, from India's own states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The province table and the map's province layer both read gb-IND-ADM1.geojson, which is the UPG-100 list's curated 34-unit partition — not a country's states. Eleven groups came out with no province because they were standing in states that partition does not draw. Both now read the complete ADM1 that landed with the internet work (36 states, geoBoundaries via DataMeet India): 998 assigned becomes 1,005, 44 province rows become 46, and the rows name Indian states. Four groups are still unassigned and each one is legible: Great Andamanese and the Sentinelese sit on islands whose simplified coastline their point falls just outside, and Jing and Pana are on China's Vietnam and Laos borders, outside its twelve-province subset. They are listed with their coordinates, not dropped. The staged-assets gate now also asserts the map and the table read the SAME geometry. Staging could never catch this: both files were staged. --- data/tables/gospel-by-province.json | 91 +++++++------------ internal/check-gospel-tables-staged.mjs | 18 ++++ .../gospel-resources/resources-map.vue | 2 +- .../scripts/build-gospel-by-province.mjs | 19 +++- .../assets/tables/gospel-by-province.json | 91 +++++++------------ public/dx-maps/doxa-maps-spa/manifest.json | 12 +-- .../gospel-resources/charts/index.html | 2 +- .../gospel-resources/data-tables/index.html | 2 +- .../gospel-dashboard/index.html | 2 +- .../gospel-resources/gospel-resources.js | 2 +- .../resources-list/index.html | 2 +- .../gospel-resources/resources-map/index.html | 2 +- public/dx-maps/manifest.json | 12 +-- 13 files changed, 123 insertions(+), 134 deletions(-) diff --git a/data/tables/gospel-by-province.json b/data/tables/gospel-by-province.json index fcb7c5def..1dc9237d8 100644 --- a/data/tables/gospel-by-province.json +++ b/data/tables/gospel-by-province.json @@ -3,10 +3,12 @@ "title": "Gospel access by province — India and China", "why": "These two countries hold 47.9% of Doxa's roster (855 + 154 of 2,107). No other country is close; the third is Sudan at 105. A national fill cannot answer \"where would a team go\" for half the map.", "generated": "2026-09-26", - "provinces_with_groups": 44, - "provinces_available": 46, - "groups_assigned": 998, - "groups_unassigned": 11, + "provinces_with_groups": 46, + "provinces_available": 48, + "groups_assigned": 1005, + "groups_unassigned": 4, + "india_note": "India is read from the COMPLETE ADM1 (36 states, geoBoundaries via DataMeet India, CC BY 2.5 IN). The first build of this table read gb-IND-ADM1.geojson, which is the UPG-100 list's curated 34-unit partition, and eleven groups came out with no province because they stood in states that partition does not draw. Switching the file moved 998 assigned to 1,005 and 44 province rows to 46, and turned the province names into India's own states.", + "unassigned_note": "Four remain, each one legible rather than lost. Great Andamanese and the Sentinelese sit on small islands whose simplified coastline the point falls just outside — Andaman and Nicobar IS in the file, so this is geometry precision, not a missing province. Jing and Pana are on China's Vietnam and Laos borders, outside the twelve-province subset. They are listed in `unassigned` with their coordinates.", "china_note": "China's ADM1 file carries 12 provinces, not 31+. Measured rather than assumed: 152 of 154 Chinese groups fall inside them and all twelve are used, so the file is cut to the provinces where the unreached peoples are.", "ways_in_are_country_level": "The ways in are chosen for the COUNTRY, and going below the border is what exposes the cost of that. Arunachal Pradesh, in the far north-east, is offered TELUGU — a South Indian language — because the curated bridge table names it for those groups and a curated bridge outranks the computed one. India's computed default is Hindi (41%, official), which is defensible nationally and still wrong for much of the north-east. This table does not fix that: it makes it visible. Until a bridge can be chosen per province, read the ways-in column as \"a language with Scripture and film somewhere in this country\", not as a recommendation for this place.", "approximate": "A province is assigned by point-in-polygon on the group's coordinate, and that coordinate marks where a PEOPLE is found, not a settlement — 108 groups across the roster even share a coordinate with another group. Near a border the point can fall on the wrong side. Every row is flagged approximate and the unassigned are counted, never dropped. No surface may present a province as a fact about a group." @@ -279,8 +281,8 @@ "country": "India", "iso3": "IND", "province": "Mahārāshtra", - "groups": 53, - "people": 2858050, + "groups": 54, + "people": 2860150, "zero_access_groups": 0, "zero_access_people": 0, "zero_access_examples": "", @@ -467,6 +469,18 @@ "ways_in": "", "approximate": true }, + { + "country": "India", + "iso3": "IND", + "province": "Puducherry", + "groups": 5, + "people": 41625, + "zero_access_groups": 0, + "zero_access_people": 0, + "zero_access_examples": "", + "ways_in": "", + "approximate": true + }, { "country": "India", "iso3": "IND", @@ -566,9 +580,21 @@ { "country": "India", "iso3": "IND", - "province": "Puducherry", + "province": "Lakshadweep", "groups": 1, - "people": 20500, + "people": 74500, + "zero_access_groups": 0, + "zero_access_people": 0, + "zero_access_examples": "", + "ways_in": "", + "approximate": true + }, + { + "country": "India", + "iso3": "IND", + "province": "Dādra and Nagar Haveli and Damān and Diu", + "groups": 1, + "people": 125, "zero_access_groups": 0, "zero_access_people": 0, "zero_access_examples": "", @@ -589,13 +615,6 @@ } ], "unassigned": [ - { - "country": "India", - "iso3": "IND", - "people_group": "Bharwad", - "lat": 20.322175, - "lng": 72.968458 - }, { "country": "India", "iso3": "IND", @@ -603,34 +622,6 @@ "lat": 12.211728, "lng": 92.833491 }, - { - "country": "India", - "iso3": "IND", - "people_group": "Indo-French", - "lat": 11.930182, - "lng": 79.797144 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Indo-Vietnamese", - "lat": 11.912456, - "lng": 79.815389 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Laccadive", - "lat": 10.0675, - "lng": 73.6422 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Sagharias", - "lat": 20.71815, - "lng": 70.988939 - }, { "country": "India", "iso3": "IND", @@ -638,20 +629,6 @@ "lat": 11.557662, "lng": 92.267154 }, - { - "country": "India", - "iso3": "IND", - "people_group": "Vettalaikarans", - "lat": 11.916308, - "lng": 79.807019 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Vettiyan", - "lat": 11.91386, - "lng": 79.814472 - }, { "country": "China", "iso3": "CHN", diff --git a/internal/check-gospel-tables-staged.mjs b/internal/check-gospel-tables-staged.mjs index cfc4a5513..d5625685d 100644 --- a/internal/check-gospel-tables-staged.mjs +++ b/internal/check-gospel-tables-staged.mjs @@ -81,6 +81,24 @@ for (const rel of wanted) { console.log(` ok ${rel.padEnd(42)} ${String(bytes).padStart(9)} bytes`) } +/* ★ THE MAP AND THE TABLE MUST READ THE SAME GEOMETRY (2026-09-26). The province layer is + coloured in the leaf and counted by scripts/build-gospel-by-province.mjs, from two independent + mentions of the same filenames — so a change to one silently draws provinces that disagree with + the rows describing them. It already happened in the other direction: both read + gb-IND-ADM1.geojson, the UPG-100 list's curated 34-unit partition, when what this table means + by "province" is a state. Staging alone cannot catch it; both files are staged. */ +const boundaryMentions = (src, re) => [...src.matchAll(re)].map((m) => m[m.length - 1]).sort() +try { + const leafSrc = readFileSync(LEAF, 'utf8') + const buildSrc = readFileSync(resolve(ROOT, 'plugin-designs/gospel-resources/scripts/build-gospel-by-province.mjs'), 'utf8') + const inLeaf = boundaryMentions(leafSrc, /(?:IND|CHN): '(gb-[A-Z]{3}-ADM1[^']*\.geojson)'/g) + const inBuild = boundaryMentions(buildSrc, /file: '(gb-[A-Z]{3}-ADM1[^']*\.geojson)'/g) + if (!inLeaf.length || !inBuild.length) missing.push('province boundary filenames not found in the leaf or the builder — this arm would pass vacuously') + else if (JSON.stringify(inLeaf) !== JSON.stringify(inBuild)) { + missing.push(`the map draws provinces from [${inLeaf.join(', ')}] while the table counts them from [${inBuild.join(', ')}]`) + } else console.log(` ok province geometry agrees ${inLeaf.join(', ')}`) +} catch (e) { missing.push(`could not compare province geometry: ${e.message}`) } + if (missing.length) { console.error(`GOSPEL-TABLES-STAGED: FAIL — ${missing.length} of ${wanted.length} asset(s) the map fetches are not in the tree:`) for (const m of missing) console.error(` ${m}`) diff --git a/plugin-designs/gospel-resources/resources-map.vue b/plugin-designs/gospel-resources/resources-map.vue index 1b5fa1ac0..eee1f67e7 100644 --- a/plugin-designs/gospel-resources/resources-map.vue +++ b/plugin-designs/gospel-resources/resources-map.vue @@ -1141,7 +1141,7 @@ async function ensureProvinceTable() { return provinceRows.value } -const PROVINCE_FILE = { IND: 'gb-IND-ADM1.geojson', CHN: 'gb-CHN-ADM1.geojson' } +const PROVINCE_FILE = { IND: 'gb-IND-ADM1-full.geojson', CHN: 'gb-CHN-ADM1.geojson' } async function ensureProvinces(iso3) { const map = mapRef.value diff --git a/plugin-designs/gospel-resources/scripts/build-gospel-by-province.mjs b/plugin-designs/gospel-resources/scripts/build-gospel-by-province.mjs index ae18978b0..0abfcbc41 100644 --- a/plugin-designs/gospel-resources/scripts/build-gospel-by-province.mjs +++ b/plugin-designs/gospel-resources/scripts/build-gospel-by-province.mjs @@ -82,8 +82,14 @@ const wayIn = (code, iso3, name) => { return b ? b.l : '' } +/* ⚠ INDIA READS THE -full FILE, NOT gb-IND-ADM1.geojson. The unsuffixed file is the UPG-100 + list's own curated partition — 34 listId-tagged units — and this table was built on it for one + build, which is why eleven groups had no province: they were standing in states the partition + does not draw. gb-IND-ADM1-full.geojson is the complete ADM1 (36 states, geoBoundaries via + DataMeet India, CC BY 2.5 IN). A partition of somebody else's list is not a country's states, + even when the filename looks like it is. */ const COUNTRIES = [ - { iso3: 'IND', file: 'gb-IND-ADM1.geojson', country: 'India' }, + { iso3: 'IND', file: 'gb-IND-ADM1-full.geojson', country: 'India' }, { iso3: 'CHN', file: 'gb-CHN-ADM1.geojson', country: 'China' }, ] @@ -146,6 +152,17 @@ if (!assigned || assigned < 900) { provinces_available: provincesAvailable, groups_assigned: assigned, groups_unassigned: unassigned.length, + india_note: 'India is read from the COMPLETE ADM1 (36 states, geoBoundaries via DataMeet ' + + 'India, CC BY 2.5 IN). The first build of this table read gb-IND-ADM1.geojson, which is ' + + 'the UPG-100 list\'s curated 34-unit partition, and eleven groups came out with no ' + + 'province because they stood in states that partition does not draw. Switching the file ' + + 'moved 998 assigned to 1,005 and 44 province rows to 46, and turned the province names ' + + 'into India\'s own states.', + unassigned_note: 'Four remain, each one legible rather than lost. Great Andamanese and ' + + 'the Sentinelese sit on small islands whose simplified coastline the point falls just ' + + 'outside — Andaman and Nicobar IS in the file, so this is geometry precision, not a ' + + 'missing province. Jing and Pana are on China\'s Vietnam and Laos borders, outside the ' + + 'twelve-province subset. They are listed in `unassigned` with their coordinates.', china_note: 'China\'s ADM1 file carries 12 provinces, not 31+. Measured rather than ' + 'assumed: 152 of 154 Chinese groups fall inside them and all twelve are used, so the ' + 'file is cut to the provinces where the unreached peoples are.', diff --git a/public/dx-maps/assets/tables/gospel-by-province.json b/public/dx-maps/assets/tables/gospel-by-province.json index fcb7c5def..1dc9237d8 100644 --- a/public/dx-maps/assets/tables/gospel-by-province.json +++ b/public/dx-maps/assets/tables/gospel-by-province.json @@ -3,10 +3,12 @@ "title": "Gospel access by province — India and China", "why": "These two countries hold 47.9% of Doxa's roster (855 + 154 of 2,107). No other country is close; the third is Sudan at 105. A national fill cannot answer \"where would a team go\" for half the map.", "generated": "2026-09-26", - "provinces_with_groups": 44, - "provinces_available": 46, - "groups_assigned": 998, - "groups_unassigned": 11, + "provinces_with_groups": 46, + "provinces_available": 48, + "groups_assigned": 1005, + "groups_unassigned": 4, + "india_note": "India is read from the COMPLETE ADM1 (36 states, geoBoundaries via DataMeet India, CC BY 2.5 IN). The first build of this table read gb-IND-ADM1.geojson, which is the UPG-100 list's curated 34-unit partition, and eleven groups came out with no province because they stood in states that partition does not draw. Switching the file moved 998 assigned to 1,005 and 44 province rows to 46, and turned the province names into India's own states.", + "unassigned_note": "Four remain, each one legible rather than lost. Great Andamanese and the Sentinelese sit on small islands whose simplified coastline the point falls just outside — Andaman and Nicobar IS in the file, so this is geometry precision, not a missing province. Jing and Pana are on China's Vietnam and Laos borders, outside the twelve-province subset. They are listed in `unassigned` with their coordinates.", "china_note": "China's ADM1 file carries 12 provinces, not 31+. Measured rather than assumed: 152 of 154 Chinese groups fall inside them and all twelve are used, so the file is cut to the provinces where the unreached peoples are.", "ways_in_are_country_level": "The ways in are chosen for the COUNTRY, and going below the border is what exposes the cost of that. Arunachal Pradesh, in the far north-east, is offered TELUGU — a South Indian language — because the curated bridge table names it for those groups and a curated bridge outranks the computed one. India's computed default is Hindi (41%, official), which is defensible nationally and still wrong for much of the north-east. This table does not fix that: it makes it visible. Until a bridge can be chosen per province, read the ways-in column as \"a language with Scripture and film somewhere in this country\", not as a recommendation for this place.", "approximate": "A province is assigned by point-in-polygon on the group's coordinate, and that coordinate marks where a PEOPLE is found, not a settlement — 108 groups across the roster even share a coordinate with another group. Near a border the point can fall on the wrong side. Every row is flagged approximate and the unassigned are counted, never dropped. No surface may present a province as a fact about a group." @@ -279,8 +281,8 @@ "country": "India", "iso3": "IND", "province": "Mahārāshtra", - "groups": 53, - "people": 2858050, + "groups": 54, + "people": 2860150, "zero_access_groups": 0, "zero_access_people": 0, "zero_access_examples": "", @@ -467,6 +469,18 @@ "ways_in": "", "approximate": true }, + { + "country": "India", + "iso3": "IND", + "province": "Puducherry", + "groups": 5, + "people": 41625, + "zero_access_groups": 0, + "zero_access_people": 0, + "zero_access_examples": "", + "ways_in": "", + "approximate": true + }, { "country": "India", "iso3": "IND", @@ -566,9 +580,21 @@ { "country": "India", "iso3": "IND", - "province": "Puducherry", + "province": "Lakshadweep", "groups": 1, - "people": 20500, + "people": 74500, + "zero_access_groups": 0, + "zero_access_people": 0, + "zero_access_examples": "", + "ways_in": "", + "approximate": true + }, + { + "country": "India", + "iso3": "IND", + "province": "Dādra and Nagar Haveli and Damān and Diu", + "groups": 1, + "people": 125, "zero_access_groups": 0, "zero_access_people": 0, "zero_access_examples": "", @@ -589,13 +615,6 @@ } ], "unassigned": [ - { - "country": "India", - "iso3": "IND", - "people_group": "Bharwad", - "lat": 20.322175, - "lng": 72.968458 - }, { "country": "India", "iso3": "IND", @@ -603,34 +622,6 @@ "lat": 12.211728, "lng": 92.833491 }, - { - "country": "India", - "iso3": "IND", - "people_group": "Indo-French", - "lat": 11.930182, - "lng": 79.797144 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Indo-Vietnamese", - "lat": 11.912456, - "lng": 79.815389 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Laccadive", - "lat": 10.0675, - "lng": 73.6422 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Sagharias", - "lat": 20.71815, - "lng": 70.988939 - }, { "country": "India", "iso3": "IND", @@ -638,20 +629,6 @@ "lat": 11.557662, "lng": 92.267154 }, - { - "country": "India", - "iso3": "IND", - "people_group": "Vettalaikarans", - "lat": 11.916308, - "lng": 79.807019 - }, - { - "country": "India", - "iso3": "IND", - "people_group": "Vettiyan", - "lat": 11.91386, - "lng": 79.814472 - }, { "country": "China", "iso3": "CHN", diff --git a/public/dx-maps/doxa-maps-spa/manifest.json b/public/dx-maps/doxa-maps-spa/manifest.json index 5a24e897d..a2c76e5cd 100644 --- a/public/dx-maps/doxa-maps-spa/manifest.json +++ b/public/dx-maps/doxa-maps-spa/manifest.json @@ -578,7 +578,7 @@ "bundle": "gospel-resources", "scriptUrl": "./gospel-resources/gospel-resources.js", "output": "dx-maps/gospel-resources/gospel-resources.js", - "integrity": "sha384-/kP2Wn3eSeZFXN8zFIMOLDfqyaBcX94JUMEI2SUMDkIhWIcXOd3DzrDSRYTUQcAp", + "integrity": "sha384-KO46bbH9Ci8gF3mQ8xKYXeUgWdbIRjRGwroS5UvbkJ/iI56xuOtfhttJ5ko5tFob", "elements": [ "gospel-resources-map" ], @@ -598,7 +598,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -612,7 +612,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -626,7 +626,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } }, { @@ -640,7 +640,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -654,7 +654,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } } ] diff --git a/public/dx-maps/gospel-resources/charts/index.html b/public/dx-maps/gospel-resources/charts/index.html index 74f2aa212..00decdac2 100644 --- a/public/dx-maps/gospel-resources/charts/index.html +++ b/public/dx-maps/gospel-resources/charts/index.html @@ -32,7 +32,7 @@ - + - + - + - + - + \n\n" + "script": "\n\n" } }, { @@ -612,7 +612,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -626,7 +626,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } }, { @@ -640,7 +640,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n" + "script": "\n\n" } }, { @@ -654,7 +654,7 @@ "scriptUrl": "./gospel-resources/gospel-resources.js", "embed": { "iframe": "", - "script": "\n\n\n\n" + "script": "\n\n\n\n" } } ]