require ('strict'); -- alarm when global variables etc are used
local nts = require ('Module:Canada NTS'); -- for extents_from_grid, nts_series_validate, nts_are_validate, nts_sheet_validatelocal data = mw.loadData ('Module:Canada NTS/data'); -- load the ~/data module
----------------------------< W I K I D A T A _ L A T _ L O N G _ G E T >------------------------------------
returns latitude and longitude from wikidata for
local function wikidata_lat_lon_get (qid) if qid then local value_t = mw.wikibase.getBestStatements (qid, 'P625')[1]; -- attempt to get P625; nil when article does not have P625 if value_t then value_t = value_t.mainsnak.datavalue.value; -- point to the value table return value_t.latitude, -1.0 * value_t.longitude; -- return coordinates from value_t; longitude normalized end endend
----------------------------< T A B B I N G >----------------------------------------------------------------
return the number of tabs necessary to more-or-less position comments at column 80 (the right-side margin linein the wiki code editor)
local function tabbing (str) return math.ceil ((80 - 4 - str:len) / 4); -- the -4 because every line begins with a tab characterend
----------------------------< S O R T >----------------------------------------------------------------------
sort by keys; ascending order numerically by series then by area (alpha sort) then numerically by sheet
local function sort (a, b) local a_key_series, a_key_area, a_key_sheet = a:match ('(%d+)(%u)(%d*)'); -- extract series, area, sheet NTS id parts from local b_key_series, b_key_area, b_key_sheet = b:match ('(%d+)(%u)(%d*)'); -- extract series, area, sheet NTS id parts from a_key_series = tonumber (a_key_series); -- convert numerical parts of key from to numbers for comparison a_key_sheet = tonumber (a_key_sheet); -- nil when
if a_key_series ~= b_key_series then -- do the comparisons; by series first return a_key_series < b_key_series; elseif a_key_area ~= b_key_area then -- then by area return a_key_area < b_key_area; else return a_key_sheet < b_key_sheet; -- and lastly by sheet endend
----------------------------< L A T _ B O U N D S _ C H E C K >----------------------------------------------
is
returns direction 'north' or 'south' when
local function lat_bounds_check (lat, north, south) if lat < south then return 'south'; -- out of bounds south of
----------------------------< L O N _ B O U N D S _ C H E C K >----------------------------------------------
is
returns direction 'east' or 'west' when
local function lon_bounds_check (lon, west, east) if lon < east then return 'east'; -- out of bounds east of
--
local function is_in_bounds (series, area, sheet, lat, lon) local extents_t = nts.extents_from_grid (tonumber(series), area, tonumber(sheet)); -- fetch extents for this nts key
local lat_fail, lon_fail; -- flags local north, west, south, east; -- map extents
if
if lat_fail or lon_fail then -- build error message if 'north'
lat_fail then return string.format ('P625 %s latitude out of bounds: WD lat/lon: <%s>,%s (NW: %s,%s / SE: <%s>,%s)', lat_fail, lat, lon, north, west, south, east); elseif 'west'
lon_fail then return string.format ('P625 %s longitude out of bounds: WD lat/lon: %s,<%s> (NW: %s,%s / SE: %s,<%s>)', lon_fail, lat, lon, north, west, south, east); end end return ; -- in bounds so return empty string message for concatenationend
--main|94}}
local function main (frame) local map_series; -- number of the series that we are operating on; for invokes, this is only number or start of a range local map_series_end; -- for invokes only; end of a range of map series local invoked;
if 'table'
local temp_t = -- output goes in this sequence table until rendering for k, v in pairs (data) do -- for each entry in the data mofule local series, area, sheet = k:match ('^(%d+)(%u)(%d*)'); -- fetch series, area, sheet from the entry's key if tonumber(series) >= tonumber(map_series) and tonumber(series) <= tonumber(map_series_end or map_series) then -- when this map is one of the map series we're looking for local map_title_parts = mw.text.split (v, '|'); -- extract an article title local qid = mw.wikibase.getEntityIdForTitle (map_title_parts[1]); -- does this article title have a wikidata entry local lat, lon = wikidata_lat_lon_get (qid); -- attempt to get P625 lat/lon from wikidata's entry for the article title local bounds_msg = ; -- gets an error message if lat/lon from wikidata not within bounds of NTS map
if qid and lat then -- when article title has wikidata entry an wikidata has P625 (latitude/longitude) bounds_msg = is_in_bounds (series, area, sheet, lat, lon); -- empty string when in bounds; message else elseif qid then -- lat can be nil when qid points to dab page or article does not have P625 bounds_msg = string.format ('%s missing P625', qid); -- no lat/lon so no P625 end local str; if not qid then -- when article title doesn't have a wikidata entry str = string.format ('\t["%s"] = "%s",', k, v); -- mimic the original elseif not lat then -- has qid but does not have P625 str = string.format ('["%s"] = "%s",', k, v); -- mimic the original + bounds_msg str = string.format ('\t%s%s-- %s', str, string.rep ('\t', tabbing (str)), bounds_msg); elseif map_title_parts[2] then -- for piped article links str = string.format ('["%s"] = "%s|%s",', k, qid, map_title_parts[2]); str = string.format ('\t%s%s-- %s; %s', str, string.rep ('\t', tabbing (str)), map_title_parts[1], bounds_msg); else -- map name same as en.wiki article title str = string.format ('["%s"] = "%s",', k, qid, map_title_parts[1]); str = string.format ('\t%s%s-- %s; %s', str, string.rep ('\t', tabbing (str)), map_title_parts[1], bounds_msg); end
if invoked then -- when this function called through an invoke str = str:gsub ('\t', ' ') -- replace plain-text tabs with html numeric entities end
table.insert (temp_t, str); -- save end end
table.sort (temp_t, sort); -- ascending numerical sort by key (NTS id) for i=#temp_t, 1, -1 do -- working backwards through the table if temp_t[i]:match ('%d+%u"%]') then -- if this key is an area key (no sheet) table.insert (temp_t, i, ); -- insert an empty string to separate area-from-area elseif i > 1 and temp_t[i]:match ('%["(%d+)') ~= temp_t[i-1]:match ('%["(%d+)') then -- because some series list don't begin with area maps (15 for example) table.insert (temp_t, i, ''); -- insert an empty string to separate area-from-area end end if invoked then -- when this function called through an invoke return table.concat ({'<pre>', table.concat (temp_t, '<br />'),'</pre>'}); -- concatenate into a big string using <br /> tags and wrapped in <pre>...</pre> tagsand done else return table.concat (temp_t, '\n'); -- concatenate into a big string using plain-text newlines and done end end --[[--------------------------< N T S _ K E Y _ V A L I D A T E >---------------------------------------------- debug console function to makes sure that all keys in Module:Canada NTS/data have the correct form =p.nts_key_validate ]]
local function nts_key_validate for k, _ in pairs (data) do local series, area, sheet = k:match ('^(%d+)(%u)(%d*)$'); if not series then return '
invalid key: ' .. k .. ''; end if not nts.nts_series_validate (tonumber(series)) then return 'invalid series: ' .. k .. ''; end if not nts.nts_area_validate (tonumber(series), area) then return 'invalid area: ' .. k .. ''; end if ~= sheet and not nts.nts_sheet_validate (tonumber(sheet)) then return 'invalid sheet: ' .. k .. ''; end end return 'keys are valid';end----------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
return