mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-11 05:42:22 +00:00
fix(shipwrecks): an end-of-service date (P576) keeps its precision, so a year-only one is not shown as 1 January
The query read P576 through wdt:, which carries no precision, and a missing precision counted as a day. It now reads the best-rank statement's value with wikibase:timePrecision, and a value without a precision is trusted to the year only. Against the live query service the new query takes 23 s and dates 16 more wrecks while every date the old one gave is unchanged.
This commit is contained in:
1 parent
0da3a28d76
commit
a1200efba6
2 files changed
+53
-8
No files matched your search
@@ -16,16 +16,16 @@ export const SHIPWRECK_SOURCES = Object.freeze(['emodnet', 'wikidata']);
|
||||
* Wikidata (CC0): shipwreck items that have at least one Wikipedia article,
|
||||
* so the worldwide set stays to notable wrecks and skips bulk register
|
||||
* imports, plus sinking events ("sinking of the RMS Titanic"), which are where
|
||||
* Wikidata keeps the death toll. Dates come with their precision so a
|
||||
* month-precise date is not shown as the 1st. Only ship and event facts are
|
||||
* read: no items about people.
|
||||
* Wikidata keeps the death toll. Dates, the end of service (P576) included,
|
||||
* come with their precision so a month-precise date is not shown as the 1st.
|
||||
* Only ship and event facts are read: no items about people.
|
||||
*/
|
||||
export const WIKIDATA_QUERY = `SELECT ?item ?itemLabel ?itemDescription ?coord ?sunk ?sunkPrecision ?end ?deaths ?survivors ?typeLabel ?enwiki ?ptwiki ?event WHERE {
|
||||
export const WIKIDATA_QUERY = `SELECT ?item ?itemLabel ?itemDescription ?coord ?sunk ?sunkPrecision ?end ?endPrecision ?deaths ?survivors ?typeLabel ?enwiki ?ptwiki ?event WHERE {
|
||||
{
|
||||
?item wdt:P31/wdt:P279* wd:Q852190 ; wdt:P625 ?coord ; wikibase:sitelinks ?links .
|
||||
FILTER(?links > 0)
|
||||
OPTIONAL { ?item p:P793 ?wreck . ?wreck ps:P793 wd:Q906512 ; pqv:P585 [ wikibase:timeValue ?sunk ; wikibase:timePrecision ?sunkPrecision ] }
|
||||
OPTIONAL { ?item wdt:P576 ?end }
|
||||
OPTIONAL { ?item p:P576 [ a wikibase:BestRank ; psv:P576 [ wikibase:timeValue ?end ; wikibase:timePrecision ?endPrecision ] ] }
|
||||
OPTIONAL { ?item wdt:P31 ?type . FILTER(?type != wd:Q852190) }
|
||||
} UNION {
|
||||
?item wdt:P31/wdt:P279* wd:Q906512 ; wdt:P625 ?coord .
|
||||
@@ -203,8 +203,8 @@ function wikidataTime(value, precision) {
|
||||
const none = { date: null, year: null, dating: null };
|
||||
const match = /^([+-]?)(\d{4,})-(\d{2})-(\d{2})T/.exec(value || '');
|
||||
if (!match) return none;
|
||||
// A missing precision (P576 is read without one) counts as a day.
|
||||
const p = precision == null ? 11 : Number(precision);
|
||||
// A value without a precision is only trusted to the year.
|
||||
const p = precision == null ? 9 : Number(precision);
|
||||
// 11 = day; 10 = month; 9 = year; below 9 is a decade or coarser.
|
||||
if (!Number.isFinite(p) || p < 9) return none;
|
||||
const signed = Number(`${match[1] === '-' ? '-' : ''}${match[2]}`);
|
||||
@@ -253,7 +253,7 @@ export function normalizeWikidataResults(payload) {
|
||||
const qid = /\/entity\/(Q\d{1,12})$/.exec(value('item') || '')?.[1];
|
||||
if (!qid) continue;
|
||||
const sunk = wikidataTime(value('sunk'), value('sunkPrecision'));
|
||||
const ended = wikidataTime(value('end'), null);
|
||||
const ended = wikidataTime(value('end'), value('endPrecision'));
|
||||
const known = byItem.get(qid);
|
||||
if (known) {
|
||||
// Extra rows only add what the first one lacked.
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
normalizeShipwreckSnapshot,
|
||||
normalizeWikidataResults,
|
||||
parseYear,
|
||||
WIKIDATA_QUERY,
|
||||
} from './records.js';
|
||||
|
||||
function feature(id, properties, coordinates = [-4.35, 54.13]) {
|
||||
@@ -86,6 +87,7 @@ test('Wikidata rows fold into one record per item', () => {
|
||||
itemDescription: { value: '1939 G and H-class destroyer' },
|
||||
coord: { value: 'Point(2.26 51.13)' },
|
||||
sunk: { value: '1940-06-01T00:00:00Z' },
|
||||
sunkPrecision: { value: '11' },
|
||||
enwiki: { value: 'https://en.wikipedia.org/wiki/HMS_Havant_(H32)' },
|
||||
},
|
||||
{
|
||||
@@ -262,3 +264,46 @@ test('a date before AD 100 is kept as ancient text, never read as an AD year', (
|
||||
assert.equal(roman.year, 300);
|
||||
assert.equal(roman.dating, null);
|
||||
});
|
||||
|
||||
test('an end-of-service date keeps its precision: a year-only one is no day', () => {
|
||||
const entity = (q) => ({ value: `http://www.wikidata.org/entity/${q}` });
|
||||
const [yearOnly, dayPrecise, unknown] = normalizeWikidataResults({
|
||||
results: {
|
||||
bindings: [
|
||||
{
|
||||
item: entity('Q11'),
|
||||
itemLabel: { value: 'Year only' },
|
||||
coord: { value: 'Point(1 50)' },
|
||||
end: { value: '1917-01-01T00:00:00Z' },
|
||||
endPrecision: { value: '9' },
|
||||
},
|
||||
{
|
||||
item: entity('Q12'),
|
||||
itemLabel: { value: 'Day precise' },
|
||||
coord: { value: 'Point(2 50)' },
|
||||
end: { value: '1917-03-04T00:00:00Z' },
|
||||
endPrecision: { value: '11' },
|
||||
},
|
||||
{
|
||||
item: entity('Q13'),
|
||||
itemLabel: { value: 'No precision' },
|
||||
coord: { value: 'Point(3 50)' },
|
||||
end: { value: '1917-01-01T00:00:00Z' },
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
assert.equal(yearOnly.date, null, 'not shown as 1 Jan 1917');
|
||||
assert.equal(yearOnly.year, 1917);
|
||||
assert.equal(dayPrecise.date, '1917-03-04');
|
||||
assert.equal(unknown.date, null, 'an unknown precision is a year only');
|
||||
assert.equal(unknown.year, 1917);
|
||||
});
|
||||
|
||||
test('the query reads the end of service with its precision', () => {
|
||||
assert.match(
|
||||
WIKIDATA_QUERY,
|
||||
/psv:P576 \[ wikibase:timeValue \?end ; wikibase:timePrecision \?endPrecision \]/,
|
||||
);
|
||||
assert.doesNotMatch(WIKIDATA_QUERY, /wdt:P576/);
|
||||
});
|
||||
Reference in new issue
Block a user