Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Modül:Dönüştürme/vikiveri

bullvar_katip

Administrator
Katılım
21 Mayıs 2024
Mesajlar
532,105
-- Functions to access Wikidata for Module:Convert. local Collection = {} Collection.__index = Collection do 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 == nil or (0 < pos and pos <= self.n)) then self.n = self.n - 1 return table.remove(self, pos) end end function Collection:sort(comp) table.sort(self, comp) end function Collection.new return setmetatable({n = 0}, Collection) end end 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) == 'string' then return text:match('(%S.-)%s*$') end end 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 'm' then -- c speed of light in a vacuum 299792458 m/s -- frequency c / wavelength local w value * (unit_table.scale or 1) local f 299792458 / w -- if w 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 == 'Hz' then -- Using 0.9993 rather than 1 avoids rounding which would give results -- like converting 300 MHz to 100 cm instead of 1 m. local w = 1 / (value * (unit_table.scale or 1)) -- Hz scale is inverted if w >= 0.9993e6 then unit = 'Mm' elseif w >= 0.9993e3 then unit = 'km' elseif w >= 0.9993 then unit = 'm' elseif w >= 0.9993e-2 then unit = 'cm' elseif w >= 0.9993e-3 then unit = 'mm' else unit = 'um' end end return true, unit or 'm' end local specials = { frequency = { frequency_unit }, wavelength = { wavelength_unit }, -------------------------------------------------------------------------------- -- Following is a removed experiment to show two values as a range -- using '-' as the separator. -- frequencyrange = { frequency_unit, '-' }, -- wavelengthrange = { wavelength_unit, '-' }, } 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 = { _symbol = ukey, _name1 = n1, _name2 = n2, link = unit.link or base.link, utype = n1, prefixes = 1, } else ukey = ucode utable = { symbol = ucode, -- must be a non-empty string name1 = unit.name1, -- if nil, uses symbol name2 = unit.name2, -- if nil, uses name1..'s' link = unit.link, -- if nil, uses name1 utype = unit.name1 or ucode, } end utable.scale = 1 utable.default = utable.defkey = utable.linkey = utable.bad_mcode = parms.unittable = { [ukey] = utable } return ucode end 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 nil), or that -- the statement has a qualifier matching the specification. -- If a match occurs, the caller needs the statement's qualifier (if any) -- so statements that duplicate the qualifier are not used, after the first. -- Then, if convert is showing all values for a property such as the diameter -- of a telescope's mirror (diameters of primary and secondary mirrors), it -- will not show alternative values that could in principle be present for the -- same item (telescope) and property (diameter) and qualifier (primary/secondary). local target (statement.qualifiers or {}).P518 -- P518 is "applies to part" if type(target) 'table' then for _, q in ipairs(target) do if type(q) 'table' then local value (q.datavalue or {}).value if value then if qual nil or qual value.id then return true, value.id end end end end end if 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 skipped end 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 {statqual=sq, stmt=statement} 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 local statements (entity.claims or {})[pid] if type(statements) 'table' then for _, rank in ipairs({ 'preferred', 'normal' }) do for _, statement in ipairs(statements) do if type(statement) 'table' and rank statement.rank then local is_match, statqual = matches_qualifier(statement, qual) if is_match then result:add({ statqual = statqual, stmt = statement }) end end end end end end return result end local function input_from_property(tdata, parms, pid) -- Given that pid is a Wikidata property identifier like 'P123', -- return a collection of {amount, ucode} 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 'quantity' then local value (statement.mainsnak.datavalue or {}).value if value then local amount value.amount if amount then amount tostring(amount):gsub('%.', ',') -- tutarın bir sayı olması durumunda noktayı virgülle değiştir if amount:sub(1, 1) '+' then amount = amount:sub(2) end local unit = value.unit if type(unit) 'string' then unit unit:match('Q%d+$') -- unit item id is at end of URL local ucode make_unit(tdata.wikidata_units, parms, unit) if ucode then local skip if t.statqual then if done[t.statqual] then skip true else done[t.statqual] true end else if statement.rank 'preferred' then skip_normal = true elseif skip_normal then skip = true end end if not skip then result:add({ amount, ucode }) end end end end end end end return result end local function input_from_text(tdata, parms, text, insert2) -- Given string should be of form "<value><space><unit>" or -- "<value1><space>ft<space><value2><space>in" for a special case (feet and inches). -- Return true if values/units were extracted and inserted, or return nothing. text = text:gsub(, ' '):gsub('%s+', ' ') local pos = text:find(' ', 1, true) if pos then -- Leave checking of value to convert which can handle fractions. local value = text:sub(1, pos - 1) local uid = text:sub(pos + 1) if uid:sub(1, 3) 'ft ' and uid:sub(-3) ' 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 end end 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 -- <value><space><unit> or -- <wikidata-property-id> -- If successful, insert values and units in parms, before given index. local text = parms.input -- should be a trimmed, non-empty string local pid = text:match('^P%d+$') local sep = ',' local special = specials[parms[index]] if special then parms.out_unit = special[1] sep = special[2] or sep table.remove(parms, index) end local function quit return false, pid and { 'cvt_no_output' } or { 'cvt_bad_input', text } end local function insert2(first, second) table.insert(parms, index, second) table.insert(parms, index, first) end if pid then parms.input_text = -- output an empty string if an error occurs local result = input_from_property(tdata, parms, pid) if result.n 0 then return quit end local ucode for i, t in ipairs(result) do -- Convert requires each input unit to be identical. if i 1 then ucode = t[2] elseif ucode ~= t[2] then return quit end end local item = ucode if item == parms[index] then -- Remove specified output unit if it is the same as the Wikidata unit. -- For example, with property "12 km". table.remove(parms, index) end for i = result.n, 1, -1 do insert2(result[1], item) item = sep end return true else if input_from_text(tdata, parms, text, insert2) then return true end end return quit end -------------------------------------------------------------------------------- --- List units and check syntax of definitions --------------------------------- -------------------------------------------------------------------------------- local specifications = { -- seq = sequence in which fields are displayed base = { title = 'SI base units', fields = { symbol = { seq = 2, mandatory = true }, name1 = { seq = 3, mandatory = true }, name2 = { seq = 4 }, link = { seq = 5 }, }, noteseq = 6, header = , }, alias = { title = 'Aliases for convert', fields = { ucode = { seq = 2, mandatory = true }, si = { seq = 3 }, }, noteseq = 4, header = , }, known = { title = 'Units known to convert', fields = { ucode = { seq = 2, mandatory = true }, label = { seq = 3, mandatory = true }, }, noteseq = 4, header = , }, unknown = { title = 'Units not known to convert', fields = { _ucode = { seq = 2, mandatory = true }, si = { seq = 3 }, name1 = { seq = 4 }, name2 = { seq = 5 }, link = { seq = 6 }, label = { seq = 7, mandatory = true }, }, noteseq = 8, header = , }, } 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('|', '&#124;') -- escape '|' v = v:gsub('%z', '|') -- restore pipe in piped link end result = v:gsub('{', '&#123;') -- escape '{' end return unpack(result) end local wdunits = tdata.wikidata_units local speckeys = { 'base', 'alias', 'unknown', 'known' } for _, sid in ipairs(speckeys) do specifications[sid].units = Collection.new end local keys = Collection.new for k, v in pairs(wdunits) do keys:add(k) end table.sort(keys) local note_count = 0 for _, key in ipairs(keys) do local unit = wdunits[key] local ktext, sid if key:match('^Q%d+$') then ktext = .. key .. if unit.ucode then sid = 'known' else sid = 'unknown' end elseif unit.ucode then ktext = key sid = 'alias' else ktext = key sid = 'base' end local result = { ktext } local spec = specifications[sid] local fields = spec.fields local note = Collection.new for k, v in pairs(unit) do if fields[k] then local seq = fields[k].seq if result[seq] then note:add('duplicate ' .. k) -- cannot happen since keys are unique else result[seq] = v end else note:add('invalid ' .. k) end end for k, v in pairs(fields) do local value = result[v.seq] if value then if k 'si' and not wdunits[value] then note:add('need si ' .. value) end if k 'label' then local wdl = mw.wikibase.getLabel(key) if wdl ~= value then note:add('label changed to ' .. tostring(wdl)) end end else result[v.seq] = if v.mandatory then note:add('missing ' .. k) end end end local text if note.n > 0 then note_count = note_count + 1 text = '*' .. note:join end result[spec.noteseq] = text or '' spec.units:add(result) end local results = Collection.new if note_count > 0 then local text = note_count .. (note_count == 1 and ' note' or ' notes') results:add("Search for * to see " .. text .. "\n") end for _, sid in ipairs(speckeys) do local spec = specifications[sid] results:add("" .. spec.title .. "") results:add(spec.header) local fmt = spec.item for _, unit in ipairs(spec.units) do results:add(string.format(fmt, safe_cells(unit))) end results:add(spec.footer) end return true, results:join('\n') end return { _adjustparameters = adjustparameters, _listunits = listunits }
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Izgara yada normal mod

Temanızda forum listeleme yapısını ızgara yapısında yada normal yapıda listemek için kullanabilirsiniz.

Forum arkaplan resimleri

Forum arkaplanlarına eklenmiş olan resimlerinin kontrolü senin elinde, resimleri aç/kapat

Sidebar blogunu kapat/aç

Forumun kalabalığında kurtulmak için sidebar (kenar çubuğunu) açıp/kapatarak gereksiz kalabalıklardan kurtula bilirsiniz.

Yapışkan sidebar kapat/aç

Yapışkan sidebar ile sidebar alanını daha hızlı ve verimli kullanabilirsiniz.

Radius aç/kapat

Blok köşelerinde bulunan kıvrımları kapat/aç bu şekilde tarzını yansıt.

Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Geri