-- Functions to access Wikidata for Module:Convert.
local Collection = Collection.__index = Collectiondo function Collection:add(item) if item ~= nil then self.n = self.n + 1 self[self.n] = item end end function Collection:join(sep) return table.concat(self, sep) end function Collection:remove(pos) if self.n > 0 and (pos
local function strip_to_nil(text) -- If text is a non-empty string, return its trimmed content, -- otherwise return nothing (empty string or not a string). if type(text)
local function frequency_unit(value, unit_table) -- For use when converting m to Hz. -- Return true, s where s = name of unit's default output unit, -- or return false, t where t is an error message table. -- However, for simplicity a valid result is always returned. local unit if unit_table._symbol
0, f = math.huge which works here if f >= 1e12 then unit = 'THz' elseif f >= 1e9 then unit = 'GHz' elseif f >= 1e6 then unit = 'MHz' elseif f >= 1e3 then unit = 'kHz' else unit = 'Hz' end end return true, unit or 'Hz'end
local function wavelength_unit(value, unit_table) -- Like frequency_unit but for use when converting Hz to m. local unit if unit_table._symbol
local specials =
local function make_unit(units, parms, uid) -- Return a unit code for convert or nil if unit unknown. -- If necessary, add a dummy unit to parms so convert will use it -- for the input without attempting a conversion since nothing -- useful is available (for example, with unit volt). local unit = units[uid] if type(unit) ~= 'table' then return nil end local ucode = unit.ucode if ucode and not unit.si then return ucode -- a unit known to convert end parms.opt_ignore_error = true ucode = ucode or unit._ucode -- must be a non-empty string local ukey, utable if unit.si then local base = units[unit.si] ukey = base.symbol -- must be a non-empty string local n1 = base.name1 local n2 = base.name2 if not n1 then n1 = ukey n2 = n2 or n1 -- do not append 's' end utable = else ukey = ucode utable = end utable.scale = 1 utable.default = utable.defkey = utable.linkey = utable.bad_mcode = parms.unittable = return ucodeend
local function matches_qualifier(statement, qual) -- Return: -- false, nil : if statement does not match specification -- true, nil : if matches, and statement has no qualifier -- true, sq : if matches, where sq is the statement's qualifier -- A match means that no qualifier was specified (qual
'table' then for _, q in ipairs(target) do if type(q)
nil or qual
nil then return true, nil -- only occurs if statement has no qualifier end return false, nil -- statement's qualifier is not relevant because statement will be skippedend
local function get_statements(parms, pid) -- Get specified item and return a list of tables with each statement for property pid. -- Each table is of form where sq = statement qualifier (nil if none). -- Statements are in Wikidata's order except that those with preferred rank -- are first, then normal rank. Any other rank is ignored. local stored = -- qualifiers of statements that are first for the qualifier, and will be returned local qid = strip_to_nil(parms.qid) -- nil for current page's item, or an item id (expensive) local qual = strip_to_nil(parms.qual) -- nil or id of wanted P518 (applies to part) item in qualifiers local result = Collection.new local entity = mw.wikibase.getEntity(qid) if type(entity)
'table' then for _, rank in ipairs do for _, statement in ipairs(statements) do if type(statement)
statement.rank then local is_match, statqual = matches_qualifier(statement, qual) if is_match then result:add end end end end end end return resultend
local function input_from_property(tdata, parms, pid) -- Given that pid is a Wikidata property identifier like 'P123', -- return a collection of pairs (two strings) -- for each matching item/property, or return nothing. -------------------------------------------------------------------------------- -- There appear to be few restrictions on how Wikidata is organized so it is -- very likely that any decision a module makes about how to handle data -- will be wrong for some cases at some time. This meets current requirements. -- For each qualifier (or if no qualifier), if there are any preferred -- statements, use them and ignore any normal statements. -- For each qualifier, for the preferred statements if any, or for -- the normal statements (but not both): -- * Accept each statement if it has no qualifier (this will not occur -- if qual=x is specified because other code already ensures that in that -- case, only statements with a qualifier matching x are considered). -- * Ignore any statements after the first if it has a qualifier. -- The rationale is that for the diameter at South Pole Telescope, want -- convert to show the diameters for both the primary and secondary mirrors -- if the convert does not specify which diameter is wanted. -- However, if convert is given the wanted qualifier, only one value -- (_the_ diameter) is wanted. For simplicity/consistency, that is also done -- even if no qual=x is specified. Unclear what should happen. -- For the wavelength at Nançay Radio Telescope, want to show all three -- values, and the values have no qualifiers. -------------------------------------------------------------------------------- local result = Collection.new local done = local skip_normal for _, t in ipairs(get_statements(parms, pid)) do local statement = t.stmt if statement.mainsnak and statement.mainsnak.datatype
'+' then amount = amount:sub(2) end local unit = value.unit if type(unit)
'preferred' then skip_normal = true elseif skip_normal then skip = true end end if not skip then result:add end end end end end end end return resultend
local function input_from_text(tdata, parms, text, insert2) -- Given string should be of form "
' in' then -- Special case for enwiki to allow insert2(uid:sub(4, -4), 'in') insert2(value, 'ft') else insert2(value, make_unit(tdata.wikidata_units, parms, uid) or uid) end return true endend
local function adjustparameters(tdata, parms, index) -- For Module:Convert, adjust parms (a table of parameters). -- Return true if successful or return false, t where t is an error message table. -- This is intended mainly for use in infoboxes where the input might be --
1 then ucode = t[2] elseif ucode ~= t[2] then return quit end end local item = ucode if item
----------------------------------------------------------------------------------- List units and check syntax of definitions -----------------------------------------------------------------------------------------------------------------local specifications =
local function listunits(tdata, ulookup) -- For Module:Convert, make wikitext to list the built-in Wikidata units. -- Return true, wikitext if successful or return false, t where t is an -- error message table. Currently, an error return never occurs. -- The syntax of each unit definition is checked and a note is added if -- a problem is detected. local function safe_cells(t) -- This is not currently needed, but in case definitions ever use wikitext -- like 'kg', escape the text so it works in a table cell. local result = for i, v in ipairs(t) do if v:find('|', 1, true) then v = v:gsub('(%[%[[^%[%]]-)|(.-%]%])', '%1\0%2') -- replace pipe in piped link with a zero byte v = v:gsub('|', '|') -- escape '|' v = v:gsub('%z', '|') -- restore pipe in piped link end result[i] = v:gsub('