モジュール:Sizeのソースを表示
←
モジュール:Size
ナビゲーションに移動
検索に移動
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループに属する利用者のみが実行できます:
登録利用者
。
このページのソースの閲覧やコピーができます。
--[[ __ __ _ _ ____ _ | \/ | ___ __| |_ _| | ___ _/ ___|(_)_______ | |\/| |/ _ \ / _` | | | | |/ _ (_)___ \| |_ / _ \ | | | | (_) | (_| | |_| | | __/_ ___) | |/ / __/ |_| |_|\___/ \__,_|\__,_|_|\___(_)____/|_/___\___| Authors and maintainers: * User:Zolo - original draft * User:Jarekt - original version ]] local formatnum = require "Module:Formatnum".formatNum local wdLabel = require "Module:Wikidata label"._getLabel -- ================================================== -- === global parameters =========================== -- ================================================== -- arrays for unit conversion 3 4 5 6 7 8 9 10 11 12 13 14 15 local unitMult = {1e-9, 1e-6, 1e-3, 1e-2, 1 , 1e3 , 0.0254, 0.3048, 0.9144, 1609.344, 1, 1e3, 1e6, 28.3495, 453.592, 1} -- conversion to meters local unitList = {'nm', 'um', 'mm', "cm", "m" , "km", "in" , "ft" , "yd" , "mi", "g", "kg", "t", "oz", "lb", "ct" } -- units handled by this module local unitType = {'m' , 'm' , 'm' , 'm' , 'm' , 'm' , 'i' , 'i' , 'i' , 'i' , 'm', 'm' , 'm', 'i' , 'i', '' } -- m for metric and i for imperial local unitItem = {nm='Q178674', um='Q175821', mm='Q174789', cm='Q174728', m='Q11573', km='Q828224', -- used for unit abbreviation translation ['in']='Q218593', ft='Q3710', yd='Q482798', mi='Q253276', kg='Q11570', g='Q41803', t='Q191118', oz='Q48013', lb="Q100995", ct="Q261247" } -- properties used for harvesting the wikidata and item IDs are used for translating dimension's name local dimProp = { length='P2043' , height='P2048' , width='P2049' , depthH='P5524', depthV='P4511' , thickness='P2610' , diameter='P2386' , radius='P2120' , perimeter='P2547' , weight='P2067'} local dimName = { length='Q36253', height='Q208826', width='Q35059', depthH='Q3250078', depthV='Q930412', thickness='Q3589038', diameter='Q37221', radius='Q173817', perimeter='Q28474', weight='Q11423'} local aliases = { -- aliases for units used to unify Q178674="nm", nm="nm", nanometer="nm", nanometers= "nm", nanometre="nm", nanometres="nm", Q175821="um", um="um", ["µm"]="um", micrometer="um", micrometers="um", micrometre="um", micrometres="um", Q200323="dm", dm="dm", decimeter="dm", decimeters="dm", decimetre="dm", decimetres="dm", Q174789="mm", mm="mm", millimeter="mm", millimeters="mm", millimetre="mm", millimetres="mm", Q174728="cm", cm="cm", centimeter="cm", centimeters="cm", centimetre="cm", centimetres="cm", Q11573="m", m="m", meter="m", meters="m", metre="m", metres="m", Q828224="km", km="km", kilometer="km", kilometers="km", kilometre="km", kilometres="km", Q218593="in", ["in"]="in", inch="in", inches="in", Q3710="ft", ft="ft", foot="ft", feet="ft", Q482798="yd", yd="yd", yard="yd", yards="yd", Q253276="mi", mi="mi", mile="mi", miles="mi", Q93318="nmi", nmi="nmi", ["nautic mile"]="nmi", ["nautic miles"]="nmi", Q11570="kg", kilogram="kg", kilograms="kg", kg="kg", Q41803="g", gram="g", grams="g", g="g", Q191118="t", tonne="t", tonnes="t", ton="t", tons="t", ["metric ton"]="t", t="t", Q48013="oz", ounce="oz", oz="oz", Q100995="lb", pound="lb", pounds="lb", lb="lb", Q261247="ct", carat="ct", ct="ct" } -- ================================================== -- === Internal functions =========================== -- ================================================== local function langSwitch(list,lang) local langList = mw.language.getFallbacksFor(lang) table.insert(langList,1,lang) for i,language in ipairs(langList) do if list[language] then return list[language] end end return nil end local function getProperty(itemID, prop, lang) local n, title = 0, {} local entity = mw.wikibase.getEntity(itemID) for _, statement in pairs( entity:getBestStatements(prop)) do if (statement.mainsnak.snaktype == "value") then local val = statement.mainsnak.datavalue.value title[val.language] = val.text -- look for multiple values each with a language code n = n+1; end end if n>0 then return langSwitch(title, lang) end --return '' end local function normalize_input_args(input_args, output_args) for name, value in pairs( input_args ) do if value ~= '' then -- nuke empty strings if type(name)=='string' then name = string.lower(name) end output_args[name] = string.gsub(value, "^%s*(.-)%s*$", "%1") -- trim whitespaces from the beggining and the end of the string end end return output_args end local function findInArray(str, list) for k, v in ipairs(list) do if v==str then -- match units with the list return k; end end return nil end local function formatNum( value, lang, precision ) assert(value, "Input value is nil") assert(precision, "Input precision is nil") local str = formatnum( value, lang, precision ) str = mw.ustring.gsub(str, "%.0+$", "") -- remove trailing zeros return str end --[[ INPUTS: * v - size in meters * unitMult - array used to convert meters to other units * iMin, iMax - min and max index of unitMult array to use ]] local function niceNumber(v, iMin, iMax) local s = 10; -- scaling parameter. Means that "nice" numbers are in units that give the smallest number bigger than s if v<s*unitMult[iMin] then return iMin -- will show as fractions of the smallest unit end for k = iMin,iMax-1 do if v>=s*unitMult[k] and v<s*unitMult[k+1] then return k end end return iMax -- will use the largest unit end local function pickUnit(val, unit, lang) local k1, k2, unit1, unit2 unit1 = aliases[unit] -- convert unit item ID to standard units assert(unit1, "Unit name is not recognized: " .. unit) k1 = findInArray(unit1, unitList) unit1 = getProperty(unitItem[unit1], 'P5061', lang) -- gets the abbreviated form of the name of the unit local valInM = val*unitMult[k1] -- find value in metres if (k1<=6) then -- input units are metric length k2 = niceNumber(valInM, 7, 10) -- find best imperial units elseif (k1<=10) then -- input units are imperial length k2 = niceNumber(valInM, 1, 6) -- find best metric units elseif (k1<=13) then -- input units are metric weight k2 = niceNumber(valInM, 14, 15)-- find best imperial units else -- input units are imperial weight k2 = niceNumber(valInM, 11, 13)-- find best metric units end local factor = unitMult[k1]/unitMult[k2] unit2 = getProperty(unitItem[unitList[k2]], 'P5061', lang) -- gets the abbreviated form of the name of the unit return unit1 or unit, unit2 or unitItem[unitList[k2]], factor, unitType[k1] end local function unit_conversion(val, unit, prec, lang, wordsep) local factor, unit1, unit2, numStr1, numStr2, system unit1, unit2, factor, system = pickUnit(val, unit, lang) -- based on val magnitude and unit, translate unit and provide coversion factor to convert to other type of units numStr1 = formatNum( val, lang, prec) .. wordsep .. unit1 if (lang~='en' and lang~='en-US' and system=='m') or (system=='') then -- if input is in metric units and output language is not English then show only metric output return numStr1 -- just show metric values end -- final string in imperial and metric units numStr2 = formatNum( val*factor, lang, prec) return mw.ustring.format("%s%s(%s%s%s)", numStr1, wordsep, numStr2, wordsep, unit2) end local function disambiguate_dimensions(args) -- compare painting dimensions to image dimensions if args[2] and args[3] and not args[4] then local title = mw.title.getCurrentTitle() if title.namespace==6 then -- this is a file local width, height, ratio, R, dr1, dr2, dr width = title.file.width height = title.file.height ratio = 1.0*height/width -- file size ratio R = 1.0*args[2]/args[3] -- painting size ratio dr1 = math.abs( R-ratio)/ratio -- compare ratios dr2 = math.abs(1/R-ratio)/ratio dr = math.min(dr1, dr2) args.debug = string.format('width=%f; height=%f; ratio=%f; R=%f; dr=%f', width, height, ratio, R, dr) if dr<0.1 and (ratio>1.15 or ratio<0.85) then -- ratios are within 10% from each other and image is not square if dr1<dr2 then args.height, args.width = args[2], args[3] else args.height, args.width = args[3], args[2] end args[2], args[3] = nil, nil end end end return args end -- ================================================== -- === External functions =========================== -- ================================================== local p = {} function p._size_old(args, unit, prec, lang) --This function mimics the functionality of the original {{Size|unit|dim1|dim2|dim3}} template if not prec then prec = 1; if unit == 'mm' then prec=2; end end -- process values local val, mean = {}, 0 for i = 2,4 do v = args[i] if v then v = string.gsub(v, ',', '.') v = tonumber(v) if type(v)=='number' and v>0 then table.insert(val, v) mean = mean + v end end end mean = mean / #val -- find mean of 3 dimensions assert(#val>0, "No numeric dimensions found.") --if n==0 then return '' end -- pick metric and imperial units local factor, unit1, unit2, system unit1, unit2, factor, system = pickUnit(mean, unit, lang) -- convert numbers to localized strings local numStr1, numStr2 = {}, {} for _, v in ipairs(val) do table.insert(numStr1, formatNum( v , lang, prec)) table.insert(numStr2, formatNum( v*factor, lang, prec)) end -- final string in the same units as input local wordsep = mw.message.new( "Word-separator" ):inLanguage(lang):plain() local x = wordsep .. '×'.. wordsep numStr1 = table.concat( numStr1, x) .. wordsep .. unit1 if (lang~='en' and lang~='en-US' and system=='m') or (system=='') then -- if input is in metric units and output language is not English then show only metric output return numStr1 -- just show metric values end -- final string in imperial and metric units numStr2 = table.concat( numStr2, x) .. wordsep .. unit2 return mw.ustring.format("%s%s(%s)", numStr1, wordsep, numStr2) end -- ================================================== function p._size(args, unit, prec, lang) --This function mimics the functionality of the latter {{Size|unit|width=...|height=...|...}} template local unit1 = aliases[unit] -- disambiguate units assert(unit1 or args.wikidata or args.entity, "Unit name is not recognized") if not prec then prec = 1; if unit == 'mm' then prec=2; end end args.depthH = args.depth -- assume that "depth" defined by {{Size}} meant "horizontal dimension away from the observer" -- harvest wikidata -- each property stores a single dimension. Notice that P4511 is for vertical depth only, while Size template parameter "depth" was mostly used for horizontal depth local entity, units = nil, {} if args.wikidata then entity = mw.wikibase.getEntity(args.wikidata) elseif args.entity then entity = args.entity end if entity then for field, prop in pairs(dimProp) do if entity.claims and entity.claims[prop] then -- if we have wikidata item and item has the property for _, statement in pairs( entity:getBestStatements( prop )) do if (statement.mainsnak.snaktype == "value") then local v = statement.mainsnak.datavalue.value args [field] = v.amount units[field] = string.gsub(v.unit, "http:%/%/www%.wikidata%.org%/entity%/", "") -- strip URL and keep the item ID end end end end end -- create non-visible encoding with untranslated dimensions local mata_str = '' local fields = { 'length', 'height', 'width', 'depthH', 'depthV', 'thickness', 'diameter'} local meta = {} for _, field in ipairs( fields ) do if args[field] then local uStr = units[field] or unitItem[unit] -- get item ID of the unit table.insert(meta, dimProp[field] .. ',' .. args[field] .. "U" .. string.sub(uStr, 2, -1) )-- replace Q with U on the beginning of the string end end if #meta>0 then mata_str = ' <div style="display: none;">dimensions QS:' .. table.concat(meta, ";") .. '</div>' end -- create the final string local colon = mw.message.new( "Colon-separator" ):inLanguage(lang):plain() local semicolon = mw.message.new( "Semicolon-separator" ):inLanguage(lang):plain() local wordsep = mw.message.new( "Word-separator" ):inLanguage(lang):plain() local dimOrder = { 'length', 'height', 'width', 'depthH', 'depthV', 'thickness', 'diameter', 'radius', 'perimeter', 'weight'} -- array with order of fields to display local results = {} for _, field in ipairs(dimOrder) do -- values with named dimensions like "depth: 2 cm" local val = args[field] if val then val = string.gsub(val, ',', '.') val = tonumber(val) if type(val)=='number' then local dimStr = wdLabel(dimName[field], lang, '-', "ucfirst") local valStr = unit_conversion(val, units[field] or unit, prec, lang, wordsep) table.insert(results, dimStr .. colon .. valStr) end end end return table.concat(results, semicolon) .. mata_str end -- ================================================== function p.size(frame) local args = {} args = normalize_input_args(frame:getParent().args, args) args = normalize_input_args(frame.args, args) if not args.lang or not mw.language.isSupportedLanguage(args.lang) then args.lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language end local unit = args[1] or args.unit or args.units unit = aliases[unit] if not unit and not args.wikidata then return '' end -- see if we can deduce which dimension is which local cat = '' if args[2] and args[3] then args = disambiguate_dimensions(args) if not args[2] then cat = '\n[[Category:Size templates with unnamed dimensions]]' end --cat = cat .. args.debug end -- call either a function for named and for unnamed dimensions if args[2] or args[3] or args[4] then return p._size_old(args, unit, args.prec, args.lang) .. cat -- old style of display for unnamed dimensions else return p._size(args, unit, args.prec, args.lang) .. cat -- dimensions are named end end return p
このページで使用されているテンプレート:
モジュール:Size/doc
(
ソースを閲覧
)
モジュール:Size
に戻る。
ナビゲーション メニュー
個人用ツール
ログイン
名前空間
モジュール
議論
English
表示
閲覧
履歴表示
その他
検索
案内
索引
脳科学辞典について
最近完成した項目
編集履歴
執筆にあたって
引用の仕方
著作権について
免責事項
問い合わせ
各学会編集のオンライン用語辞典
About us (in English)
Twitter (BrainScienceBot)
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
他のプロジェクト