Oceania is 51% unreached by group, and nothing on this map said so
region was empty on all 242 country rows, so the map had no way to answer "what share of this part of the world is unreached" — only how many groups a country holds and how many people live in them. The source carries UNm49Region, and it was verified before being trusted: only 2, 9, 19, 142 and 150 appear — exactly the five UN M49 top-level regions — every country maps to exactly ONE of them with 0 conflicts, and the five sum to 12,379, the whole corpus. So the code resolves to a real name. It is backfilled on every row, not just the new ones, and all 242 now carry a region with none blank. The rate is a genuinely different answer from the two already on offer: Oceania 51.2% of its 1,325 groups have nothing — 679 groups — 3.1M people Africa 30.0% of 3,074 — 923 — 68.2M Asia 19.3% of 5,073 — 978 — 198.7M Americas 11.4% of 2,117 — 241 — 6.1M Europe 10.1% of 790 — 80 — 11.6M Oceania is half unreached by group and the smallest population of the five; Asia is the reverse on both. Ranked by rate, because count and population are what the other two tabs already say and a third copy of either would be noise. All three are offered rather than one picked for the reader. The rows are plain divs, not buttons: a region is not somewhere this map can fly to, and a control that looks clickable and does nothing is worse than a row that does not pretend. Verified against an offline computation over the same index: all five regions match exactly on rate, group count and population. The sheet header is now three-way rather than showing the country prose in region mode. All five profiles still mount clean.
This commit is contained in:
parent
cde152bde7
commit
c0a1cec24a
12 changed files with 572 additions and 523 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -307,6 +307,29 @@ const gapList = computed(() => {
|
|||
// Papua New Guinea has 469 groups with nothing but only 2.2M people, China has 125 groups
|
||||
// and 150.3M. Ranking by either one alone hides the other question.
|
||||
const gapBy = ref('groups')
|
||||
// A THIRD AXIS: the RATE. The country tab ranks by how many groups a country holds and
|
||||
// shows population beside it; neither answers "what share of this place is unreached".
|
||||
// Measured, the three disagree completely and each is somebody's question:
|
||||
// Oceania 51.2% of its groups have nothing — the worst rate anywhere — but 3.1M people
|
||||
// Asia 19.3%, and 198.7M people with nothing — by far the largest population
|
||||
// Africa 30.0%, 923 groups — the most after Asia
|
||||
// Ranked by rate here, because count and population are already answered by the other two
|
||||
// tabs and a third copy of either would be noise.
|
||||
const gapRegions = computed(() => {
|
||||
if (!showGapList.value) return []
|
||||
const by = {}
|
||||
for (const r of pinRows.value) {
|
||||
const reg = byIso.value[r[3]]?.region || ''
|
||||
if (!reg) continue
|
||||
const e = (by[reg] = by[reg] || { region: reg, groups: 0, none: 0, pop: 0 })
|
||||
e.groups++
|
||||
if (r[6] === 0) { e.none++; e.pop += r[5] || 0 }
|
||||
}
|
||||
return Object.values(by)
|
||||
.map((e) => ({ ...e, pct: e.groups ? Math.round((1000 * e.none) / e.groups) / 10 : 0 }))
|
||||
.sort((a, b) => b.pct - a.pct)
|
||||
})
|
||||
|
||||
const gapCountries = computed(() => {
|
||||
if (!showGapList.value) return []
|
||||
const by = {}
|
||||
|
|
@ -1016,13 +1039,19 @@ useShadowStyles(
|
|||
<!-- ITEM 0 — the ranked gap: the largest groups with nothing found anywhere. -->
|
||||
<template v-if="showGapList && !selected">
|
||||
<div class="gm-sh-head">
|
||||
<span class="gm-sh-name">{{ gapBy === 'countries' ? 'Where the gap concentrates' : 'Largest groups with nothing found' }}</span>
|
||||
<span class="gm-sh-name">{{ gapBy === 'groups' ? 'Largest groups with nothing found' : 'Where the gap concentrates' }}</span>
|
||||
<button type="button" class="gm-x" @click="closeGapList">Close</button>
|
||||
</div>
|
||||
<p class="gm-note" style="margin-top:0">
|
||||
{{ fmt(pinTally.none) }} people groups have no Scripture, audio, film, Bible video or
|
||||
Door43 resource in the pools checked — {{ fmt(gapPeople) }} people.
|
||||
<template v-if="gapBy === 'countries'">
|
||||
<template v-if="gapBy === 'regions'">
|
||||
The five UN regions, ranked by the SHARE of their groups with nothing — the one
|
||||
question the other two tabs cannot answer. Oceania is half unreached by group
|
||||
and small by population; Asia is the reverse. Rate, count and population each
|
||||
point somewhere different, and all three are here rather than one chosen for you.
|
||||
</template>
|
||||
<template v-else-if="gapBy === 'countries'">
|
||||
The top 40 countries by how many of those groups they hold; tap one to open it.
|
||||
The two columns disagree on purpose — Papua New Guinea has the most groups and
|
||||
few people, China the reverse — and which one matters depends on whether you are
|
||||
|
|
@ -1045,9 +1074,21 @@ useShadowStyles(
|
|||
@click="gapBy = 'groups'">Largest groups</button>
|
||||
<button type="button" class="gm-gtab" :class="{ on: gapBy === 'countries' }"
|
||||
@click="gapBy = 'countries'">By country</button>
|
||||
<button type="button" class="gm-gtab" :class="{ on: gapBy === 'regions' }"
|
||||
@click="gapBy = 'regions'">By region</button>
|
||||
</div>
|
||||
|
||||
<template v-if="gapBy === 'countries'">
|
||||
<!-- Not buttons: a region is not a place this map can fly to, and a control that
|
||||
looks clickable and does nothing is worse than a plain row. -->
|
||||
<template v-if="gapBy === 'regions'">
|
||||
<div v-for="r in gapRegions" :key="r.region" class="gm-pg">
|
||||
<span class="gm-pg-n">{{ r.region }}</span>
|
||||
<span class="gm-pg-l"><b>{{ r.pct }}%</b> of its {{ fmt(r.groups) }} groups have nothing
|
||||
· {{ fmt(r.none) }} groups · {{ fmt(r.pop) }} people</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="gapBy === 'countries'">
|
||||
<button v-for="c in gapCountries" :key="c.iso3" type="button" class="gm-pg gm-pg-btn"
|
||||
@click="closeGapList(); openCountry(c.iso3)">
|
||||
<span class="gm-pg-n">{{ c.country }}</span>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ const j = JSON.parse(readFileSync(OUT, 'utf8'))
|
|||
// Real names, from the same source the pins are built from. A row labelled "CAN" would
|
||||
// render "CAN" as the country sheet's title; people-groups-slim carries CountryName and
|
||||
// UNm49Region per group, so there is no reason to show a code.
|
||||
const M49 = { 2: 'Africa', 9: 'Oceania', 19: 'Americas', 142: 'Asia', 150: 'Europe' }
|
||||
const nameOf = {}
|
||||
const regionOf = {}
|
||||
try {
|
||||
const raw = JSON.parse(readFileSync(resolve(REPO, 'data/people-groups/people-groups-slim.json'), 'utf8'))
|
||||
const rows = Array.isArray(raw) ? raw : Object.values(raw).find(Array.isArray)
|
||||
|
|
@ -47,8 +49,12 @@ try {
|
|||
const i = r.ISOAlpha3
|
||||
if (!i) continue
|
||||
if (!nameOf[i] && r.CountryName) nameOf[i] = String(r.CountryName).trim()
|
||||
// UNm49Region is a NUMERIC region code (19, 142, ...), not a name. Rendering "19" as a
|
||||
// region is worse than rendering nothing, and every existing row carries region: ''.
|
||||
// UNm49Region is a NUMERIC code, and the five that appear are exactly the UN M49
|
||||
// top-level regions. Verified before trusting it: only 2/9/19/142/150 occur, every
|
||||
// country maps to exactly ONE of them (0 conflicts across 12,379 groups), and the five
|
||||
// sum to 12,379 — the whole corpus. So the code is resolvable to a real name, and "19"
|
||||
// on its own is not.
|
||||
if (!regionOf[i] && r.UNm49Region) regionOf[i] = M49[String(r.UNm49Region).trim()] || ''
|
||||
}
|
||||
} catch { /* names are a nicety; the bands are the point */ }
|
||||
|
||||
|
|
@ -80,7 +86,7 @@ for (const [iso3, e] of Object.entries(agg)) {
|
|||
j.countries.push({
|
||||
iso3,
|
||||
country: nameOf[iso3] || iso3,
|
||||
region: '',
|
||||
region: regionOf[iso3] || '',
|
||||
groups: 0, no_resource: 0, pop_no_resource: 0, scripture: 0, film: 0,
|
||||
growing_unreached: null, deaths_day: null, growth: null,
|
||||
pct_no_resource: 0, band: 'covered',
|
||||
|
|
@ -103,6 +109,8 @@ for (const c of j.countries) {
|
|||
c.film = e.film
|
||||
c.pct_no_resource = pct
|
||||
c.band = b
|
||||
// Backfilled on every row, not only new ones: region was empty on all 170 originals.
|
||||
if (!c.region && regionOf[c.iso3]) c.region = regionOf[c.iso3]
|
||||
}
|
||||
|
||||
j.stats = {
|
||||
|
|
|
|||
484
public/doxa-maps/assets/tables/gospel-by-country.json
generated
484
public/doxa-maps/assets/tables/gospel-by-country.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
2
public/doxa-maps/index.html
generated
2
public/doxa-maps/index.html
generated
File diff suppressed because one or more lines are too long
12
public/doxa-maps/manifest.json
generated
12
public/doxa-maps/manifest.json
generated
|
|
@ -591,7 +591,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "doxa-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT",
|
||||
"integrity": "sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk",
|
||||
"elements": [
|
||||
"gospel-resources-map"
|
||||
],
|
||||
|
|
@ -611,7 +611,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -625,7 +625,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -639,7 +639,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -653,7 +653,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -667,7 +667,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-9ouuqJx7txluDdcQQCm7xvtmSGJh25LsGgNo7kBB63YtXQNYKrg5hkOoHOJsl5PT\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-WZSlVBydYxeLPK42l4lhgBPjrSOBIIyw33bAuh5kD7c6uKgWMramyveBq5Z9G5Zk\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in a new issue