Changes

MyWikiBiz, Author Your Legacy — Monday May 13, 2024
Jump to navigationJump to search
83,433 bytes added ,  08:01, 16 July 2021
Pywikibot 6.4.0
local mf = require('Module:Formatnum')

local yesno = require('Module:Yesno')

local p = {} -- Holds functions to be returned from #invoke, and functions to make available to other Lua modules.

--[[
Helper functions used to avoid redundant code.
]]

local function err(msg)
-- Generates wikitext error messages.
return mw.ustring.format('<strong class="error">Formatting error: %s</strong>', msg)
end

local function getArgs(frame)
local args = {}
for key, value in pairs(frame:getParent().args) do
args[key] = value
end
for key, value in pairs(frame.args) do
args[key] = value
end
return args
end

local function getCurrentLanguage()
local result = mw.title.getCurrentTitle().pageLanguage
if not result then
result = mw.language.getContentLanguage():getCode()
end
return result
end

local function _round(value, precision)
local rescale = math.pow(10, precision or 0);
return math.floor(value * rescale + 0.5) / rescale;
end

--[[
------------------------------------------------------------------------------------
-- tableLength
--
-- This function returns the number of keys in a table.
------------------------------------------------------------------------------------
--]]
local function tableLength(t)
local count = 0
for _ in pairs(t) do count = count + 1 end
return count
end

--[[
------------------------------------------------------------------------------------
-- singleEntry
--
-- If a table contains a single entry, it returns the key and value, otherwise nil.
------------------------------------------------------------------------------------
--]]
local function singleEntry(t)
local count = 0
local resultk, resultv
for k, v in pairs(t) do
if count > 0 then
return nil
else
count = count + 1
resultk = k
resultv = v
end
end

if count == 1 then
return resultk, resultv
else
return nil
end
end

--[[
------------------------------------------------------------------------------------
-- isPositiveInteger
--
-- This function returns true if the given value is a positive integer, and false
-- if not. Although it doesn't operate on tables, it is included here as it is
-- useful for determining whether a given table key is in the array part or the
-- hash part of a table.
------------------------------------------------------------------------------------
--]]
local function isPositiveInteger(v)
return type(v) == 'number' and v >= 1 and math.floor(v) == v and v < math.huge
end


--[[
------------------------------------------------------------------------------------
-- reverseNumKeys
--
-- This takes a table and returns an array containing the numbers of any numerical
-- keys that have non-nil values, sorted in reverse numerical order.
------------------------------------------------------------------------------------
--]]
local function reverseNumKeys(t)
local nums = {}
local ispi = isPositiveInteger
for k, _ in pairs(t) do
if ispi(k) then
nums[#nums + 1] = k
end
end
table.sort(nums, function(a, b) return a > b end)
return nums
end

--[[
------------------------------------------------------------------------------------
-- reverseSparseIpairs
--
-- This is a reverse iterator for sparse arrays. It can be used like a reversed ipairs, but can
-- handle nil values.
------------------------------------------------------------------------------------
--]]
local function reverseSparseIpairs(t)
local nums = reverseNumKeys(t)
local i = 0
local lim = #nums
return function ()
i = i + 1
if i <= lim then
local key = nums[i]
return key, t[key]
else
return nil, nil
end
end
end

--[[
------------------------------------------------------------------------------------
-- addMultipleKeys
--
-- This takes a table and adds all the values in an array as keys to a single object
------------------------------------------------------------------------------------
--]]
local function addMultipleKeys(arr, keys, val)
if keys then
for _, v in ipairs(keys) do
arr[v] = val
end
end
end

--[[
------------------------------------------------------------------------------------
-- deepReverseTable
--
-- This takes a table and returns a new table where the values are keys and vice versa
------------------------------------------------------------------------------------
--]]
local function deepReverseTable(t)
local rev = {}
for k, v in pairs(t) do
if type(v) == 'table' then
addMultipleKeys(rev, v, k)
else
rev[v] = k
end
end
return rev
end

--[[
------------------------------------------------------------------------------------
-- makeLengthTable
--
-- This takes a table and returns a new table where keys are the lengths of the string in each subtable
------------------------------------------------------------------------------------
--]]
local function makeLengthTable(t)
local result = {}
local ulen = mw.ustring.len
local ins = table.insert
for _, v in pairs(t) do
local len = ulen(v)
local subr = result[len]
if subr then
ins(subr, v)
else
result[len] = { v }
end
end
return result
end

--[[
------------------------------------------------------------------------------------
-- Object
--
-- Root object
------------------------------------------------------------------------------------
--]]
local Object = {}

function Object:new (o)
o = o or {} -- create object if user does not provide one
o.super = self
setmetatable(o, self)
self.__index = self
return o
end

function Object:tableInherit(name, k)
repeat
local field = rawget(self, name)
local result = field and field[k]
if result then
return result
else
self = rawget(self, 'super')
end
until not self

return nil
end

local parameters = {}

local parameter_lookup = {}

local Parameter = Object:new{ defaults = {} }

function Parameter:new (o)
local result = self.super.new(self, o)
result.lookup = deepReverseTable(result.values)
local code = rawget(result, 'code')
if code and code ~= '' then
parameters[code] = result
end
parameter_lookup[code] = code
addMultipleKeys(parameter_lookup, result.names, code)
return result
end

function Parameter:default(lang, arg, arg2)
if arg and arg ~= '' then
return arg:lower()
else
if lang and lang ~= '' then
local d = rawget(self, 'defaults')
if d then
local l = d[lang]
if type(l) == 'table' then
l = l[arg2]
end
if l then
return l
end
end
end

local fallback = rawget(self, 'fallback')

if type(fallback) == 'function' then
return fallback()
else
return fallback
end
end
end

function Parameter:get(arg)
local result = rawget(self, 'lookup')[arg]
if result then
return result
else
return nil
end
end

function Parameter:getArgument(args)
local code = self.code
if code and code ~= '' then
local result = args[code]
if result then
return result
else
local names = rawget(self, 'names')
if names then
for _, v in pairs(names) do
result = args[v]
if result then
return result
end
end
end
end
end
return nil
end

local function setupParameters()
for k, v in pairs(parameters) do
parameter_lookup[k] = k
local names = rawget(v, 'names')
addMultipleKeys(parameter_lookup, names, k)
end
end

local function translateParameters(args)
local result = {}
for k, v in pairs(args) do
local c
if tonumber(k) then
c = k
else
c = parameter_lookup[k]
end
--[[
if not c then
return err('Illegal parameter: " .. k)
end
]]
if c then
result[c] = v
end
end
return result
end

--[[
wordify

Usage:
{{#invoke:Wordify | main | x | prec= | lk= | numsys= | lang= | state= | case= | class= | simplify= }}

--]]

function p.main(frame)
local args = getArgs(frame)
local translated = translateParameters(args)
if type(translated) ~= 'table' then
return err('Illegal argument: ' .. translated)
end
local x = args[1]
local numsys = parameters.numsys:getArgument(translated)
local prec = parameters.prec:getArgument(translated)
local lk = parameters.lk:getArgument(translated)
local lang = parameters.lang:getArgument(translated)
local script = parameters.script:getArgument(translated)
local state = parameters.state:getArgument(translated)
local case = parameters.case:getArgument(translated)
local class = parameters.class:getArgument(translated)
local possessed = parameters.possessed:getArgument(translated)
local person = parameters.person:getArgument(translated)
local plural = parameters.plural:getArgument(translated)
local exclude = parameters.exclude:getArgument(translated)
local simplify = parameters.simplify:getArgument(translated)
return p._wordify(x, prec, yesno(lk), numsys, lang, script, state, case, class, yesno(possessed), tonumber(person), yesno(plural), tonumber(exclude), yesno(simplify))
end

local language = Parameter:new{
code = 'lang',
names = { 'language' },
values = {},
fallback = getCurrentLanguage
}

local precision = Parameter:new{
code = 'prec',
names = { 'precision' },
values = {},
fallback = 0
}

local link = Parameter:new{
code = 'lk',
names = { 'link' },
values = {},
fallback = false
}

local number_systems = Parameter:new{
code = 'numsys',
names = { 'scale' },
values = {
indian = { 'indian', 'ind' },
myriad = { 'myriad' },
long = { 'long', 'fra' },
short = {'short', 'usa' }
},
defaults = {},
fallback = 'long'
}

local possessed = Parameter:new{
code = 'possessed',
values = {},
fallback = false
}

local person = Parameter:new{
code = 'person',
values = {},
fallback = false
}

local plural = Parameter:new{
code = 'plural',
values = {},
fallback = false
}

local exclude = Parameter:new{
code = 'exclude',
values = {},
fallback = false
}

local simplify = Parameter:new{
code = 'simplify',
values = {},
fallback = false
}

local scripts = Parameter:new{
code = 'script',
values = {
arab = { 'arabic' },
aran = { 'nastaliq' },
armn = { 'armenian' },
bali = { 'balinese' },
beng = { 'bengali' },
bugi = { 'buginese', 'lontara' },
cans = { 'cans' },
cher = { 'cherokee' },
cyrl = { 'cyrilic' },
deva = { 'devanagari' },
ethi = { 'ethiopic', "ge'ez" },
geor = { 'georgian' },
geok = { 'khutsuri' },
grek = { 'greek' },
gujr = { 'gujarati' },
guru = { 'gurmunkhi' },
hang = { 'hangul' },
hani = { 'hanzi', 'kanji', 'hanja' },
hans = { 'han simplified', 'simplified han', 'simplified chinese', 'chinese simplified' },
hant = { 'han traditional', 'traditional han', 'traditional chinese', 'chinese traditional' },
hebr = { 'hebrew' },
java = { 'javanese' },
khmr = { 'khmer' },
knda = { 'kannada' },
laoo = { 'lao'},
latn = { 'latin' },
mong = { 'mongolian' },
mlym = { 'malayalam' },
mymr = { 'myanmar', 'burmese' },
orya = { 'oriya', 'odia' },
rohg = { 'hanifi rohingya' },
sinh = { 'sinhala' },
sund = { 'sundanese' },
syrc = { 'syriac' },
syre = { 'ʾesṭrangēlā' },
syrj = { 'western syriac' },
syrn = { 'eastern syriac' },
taml = { 'tamil'},
tavt = { 'tai viet' },
telu = { 'telugu' },
tfng = { 'tifinagh' },
tglg = { 'tagalog' },
thaa = { 'thaana' },
thai = { 'thai' },
tibt = { 'tibetan' },
yiii = { 'yi' }
},
defaults = {},
fallback = 'latin'
}

local states = Parameter:new{
code = 'state',
values = {
c = { 'construct' },
d = { 'definite' },
i = { 'indefinite' }
},
fallback = 'indefinite'
}

local classes = Parameter:new{
code = 'class',
values = {
an = { 'animate' },
['cl-1'] = { 'class 1', 'class i' },
['cl-1a'] = { 'class 1a' },
['cl-2'] = { 'class 2', 'class ii' },
['cl-2a'] = { 'class 2a' },
['cl-3'] = { 'class 3', 'class iii' },
['cl-4'] = { 'class 4', 'class iv' },
['cl-5'] = { 'class 5', 'class v' },
['cl-6'] = { 'class 6', 'class vi' },
['cl-7'] = { 'class 7', 'class vii' },
['cl-8'] = { 'class 8', 'class viii' },
['cl-9'] = { 'class 9', 'class ix' },
['cl-10'] = { 'class 10', 'class x' },
co = { 'common' },
f = { 'feminine' },
['in'] = { 'inanimate' },
m = { 'masculine' },
['m-an'] = { 'masculine animate' },
['m-i'] = { 'masculine inanimate' },
n = { 'neuter' },
ve = { 'vegetable' },
x = { 'x' },
y = { 'y' }
},
fallback = 'neuter',
class_strings = {
'kategória', 'κατηγορία',
'osztály', 'flokkur',
'classe', 'clâsse', 'klasse', 'luokka', 'darasa', 'razred', 'разред', 'разряд', 'ประเภท',
'clase', 'klase', 'klaso', 'klasa', 'clasă', 'class', 'klass', 'kelas', 'aicme', 'sinif', 'třída', 'είδος', 'класс', 'класа', 'קלאַס', 'พรรค์', 'မျိုး', 'صِنْف', 'صَنْف',
'clas', 'klas', 'klad', 'rühm', 'τάξη', 'клас', 'しゅるい', 'ชนิด', 'ຊະນິດ', 'کلاس',
'դաս', 'صنف', 'رده',
'cl', '種類', '种类',
'類', '类'
}
}

classes.class_lengths = makeLengthTable(classes.class_strings)

function classes:get(class)
local function matchSimilarClasses(class, classlen, pos, t, len, lr)
local function makeNumberedClass(class, affixlen)
local rest
if lr then
rest = mw.ustring.sub(class, affixlen+1)
else
rest = mw.ustring.sub(class, 1, -(affixlen+1))
if mw.ustring.sub(rest, -1, -1) == "." then
rest = mw.ustring.sub(rest, 1, -2) -- 1. Klasse
end
end
local num = tonumber(rest)
if num then
return 'cl-' .. tostring(num)
else
return nil
end
end

local len1 = len + 1
if classlen > len1 then
local cand
if lr then
cand = mw.ustring.sub(class, 1, len)
else
cand = mw.ustring.sub(class, -len)
end
for _, v in pairs(t) do
if cand == v then
return makeNumberedClass(class, len1)
end
end
end
return nil
end

local result = self.super.get(self, class)
if result then
return result
else
local l = mw.ustring.len(class)
local bstart, bend = string.find(class, ' ')
local dstart, dend = string.find(class, '-')
if bstart or dstart then
local pos
if bstart and dstart then
if bstart > dstart then
pos = dstart
else
pos = bstart
end
elseif bstart then
pos = bstart
else
pos = dstart
end
if pos > 1 then
local len = pos-1
local v = self.class_lengths[len]
if v then
local cls = matchSimilarClasses(class, l, pos, v, len, true)
if cls then
return cls
end
end
end

if bstart then
bstart, bend = string.find(class, " [^ ]*$")
end
if dstart then
dstart, dend = string.find(class, "-[^-]*$")
end
if bstart and dstart then
if bstart > dstart then
pos = bstart
else
pos = dstart
end
elseif bstart then
pos = bstart
else
pos = dstart
end
if pos < l then
local len = l-pos
local v = self.class_lengths[len]
if v then
local cls = matchSimilarClasses(class, l, pos, v, len, true)
if cls then
return cls
end
end
end
end
local plain = mw.ustring.gsub(class, '-', '')
return self.lookup[plain]
end
end

local cases = Parameter:new{
code = 'case',
names = {},
values = {
abe = { 'abessiv' },
abl = { 'ablativ' },
abs = { 'absolutiv' },
accus = { 'accusativ', 'akkusativ', 'wenfall', 'acusativo', 'akuzativ', 'tožilnik', 'biernik', 'galininkas', 'þolfall', 'вини́тельный' },
['accus-n'] = { 'accusative-nominative', 'akkusativ-nominativ', 'acusativo-nominativo', 'nominatiiviakkusatiivi' },
['accus-g'] = { 'accusative-genitive', 'akkusativ-genitiv', 'acusativo-genitivo', 'genetiiviakkusatiivi' },
accud = { 'accudativ', 'akkudativ' },
adel = { 'adelativ' },
ades = { 'adessiv', 'adesyvas' },
adv = { 'adverbial' },
al = { 'allativ', 'adlativ', 'direktiv', 'aliatyvas' },
av = { 'aversiv' },
ag = { 'agentiv' },
an = { 'antessiv' },
ap = { 'apudessiv' },
b = { 'benefactiv', 'benefaktiv', 'destinativ' },
ca = { 'causal' },
['ca-fi'] = { 'causal-final' },
comi = { 'comitativ', 'komitativ', 'assoziativ' },
comp = { 'comparativ' },
da = { 'dativ', 'wemfall', 'dajalnik', 'celownik', 'naudininkas', 'þágufall', 'да́тельный' },
de = { 'delativ' },
di = { 'distributiv' },
['di-tem'] = { 'distributive-temporal' },
eg = { 'egressiv' },
el = { 'elativ' },
eq = { 'equativ', 'äquativ' },
er = { 'ergativ' },
['er-g'] = { 'ergative-genitive' },
es = { 'essiv' },
['es-fo'] = { 'essive-formal' },
['es-mod'] = { 'essive-modal' },
ex = { 'exessiv' },
fo = { 'formal' },
g = { 'genitiv', 'wesfall', 'wessenfall', 'genetiv', 'rodilnik', 'dopełniacz', 'kilmininkas', 'eignarfall', 'роди́тельный' },
id = { 'identical' },
il = { 'illativ', 'kryptininkas' },
ine = { 'inessiv' },
ini = { 'initiativ' },
intran = { 'intransitiv' },
intrat = { 'intrativ' },
instruc = { 'instructiv', 'instruktiv' },
instrum = { 'instrumental', 'instrumentál', 'orodnik', 'narzędnik', 'įnagininkas', 'твори́тельный' },
['instrum-comi'] = { 'instrumental-comitativ' },
la = { 'lativ' },
li = { 'limitativ' },
lo = { 'locativ', 'lokativ', 'lokál', 'mestnik', 'miejscownik', 'vietininkas' },
mod = { 'modal' },
n = { 'nominativ', 'werfall', 'rektus', 'rectus', 'imenovalnik', 'mianownik', 'vardininkas', 'nefnifall', 'имени́тельный' },
obl = { 'oblique', 'obliquus', 'oblik' },
obj = { 'objectiv' },
['obj/obl'] = { 'objective/oblique' },
ori = { 'orientativ' },
orn = { 'ornativ' },
pa = { 'partitiv' },
peg = { 'pegativ' },
perl = { 'perlativ' },
pert = { 'pertingent' },
possesse = { 'possessed' },
possessi = { 'possessiv' },
postel = { 'postelativ' },
postes = { 'postessiv' },
pre = { 'prepositional', 'präpositiv', 'предло́жный' },
pri = { 'privativ' },
pro = { 'prolativ' },
r = { 'revertiv' },
se = { 'semblativ' },
so = { 'sociativ' },
sube = { 'subessiv' },
subl = { 'sublativ' },
supere = { 'superessiv' },
superl = { 'superlativ' },
tem = { 'temporal' },
ter = { 'terminativ' },
tr = { 'translativ' },
v = { 'vocativ', 'vokativ', 'wołacz', 'šauksmininkas' }
},
fallback = 'nominative'
}


function cases:get(case)
local result = self.super.get(self, case)
if result then
return result
else
local l = mw.ustring.len(case)
local matched
if l > 4 then
local last = mw.ustring.sub(case, -4, -1)
if last == 'ivus' then
matched = true
case = mw.ustring.sub(case, 1, -3)
result = self.lookup[case]
if result then
return result
end
elseif last == 'iivi' then
matched = true
case = mw.ustring.sub(case, 1, -4) .. 'v'
result = self.lookup[case]
if result then
return result
end
end
end
if l > 3 and not matched then
local last = mw.ustring.sub(case, -3, -1)
if last == 'ive' or last == 'ivo' then
matched = true
case = mw.ustring.sub(case, 1, -2)
result = self.lookup[case]
if result then
return result
end
end
end
if l > 2 and not matched then
local last = mw.ustring.sub(case, -2, -1)
if last == 'if' then
matched = true
case = mw.ustring.sub(case, 1, -2) .. 'v'
result = self.lookup[case]
if result then
return result
end
end
end
local plain = mw.ustring.gsub(case, '-', '')
return self.lookup[plain]
end
end

local function linkBegin(lang)
if not lang or lang == '' then
return "[["
else
return "[[:" .. lang .. ":"
end
end

local function linkEnd(u)
if not u or u == '' then
return "]]"
else
return "|" .. u .. "]]"
end
end

local function link_en(i, stem, u)
return (i > 39 and "Names of large numbers" or ("Orders of magnitude (numbers)#10" .. i)) .. linkEnd(u)
end

local Adder = Object:new{}

function Adder:getAdditional(lang, i)
local one, simplify

local top = self:tableInherit('additional', i)
if top then
local entry = (top and lang and top[lang]) or top
if entry then
one, simplify = entry[1], entry.simplify
end
end

return one, simplify
end

--[[
Rules grammars

<possessive-rules> ::= "{}" | <string> | "{" <possessor-cases> "}" | <possessive-function>
<possessor-cases> ::= <singular-possessors> | <singular-posessors> "," <plural-posessors>
<singular-possessors> ::= "{" <singular-possessor-cases> "}"
<singular-posessor-cases> := <simple-posessor-case> | <simple-possessor-case> "," <singular-possessor-cases>
<simple-posessor-case> := "{ {" <singular-possessed> "," <plural-possessed> "} }" | <possessor-function>
<singular-possessed> ::= <possessed>
<plural-possessed> ::= <possessed>
<possessed> ::= <string> | "{" <possessed-cases> "}" | <possessed-function>
<plural-posessors> ::= "{" <plural-possessor-cases> "}"
<plural-possessor-cases> := <plural-posessor-case> | <plural-possessor-case> "," <plural-possessor-cases>
<plural-possessor-case> ::= "{" <clusivity-cases> "}"
<clusivity-cases> ::= <simple-possessor-case> | <simple-possessor-case> "," <clusivity-cases>

<inflection-rules> ::= "{}" | "{" <stem-statement> "}" | "{" <number-cases> "}" | "{" <stem-statement> "," <number-cases> "}"
<stem-statement> ::= "stem" "=" <stem-function>
<number-cases> ::= <number-case> | <number-case> "," <number-cases>
<number-case> ::= <number-index> <number-rule>
<number-index> ::= "" | "[" <integer> "]" "=" | | "[" "fraction" "]" "="
<number-rule> ::= <string> | <ending-cases-list> | <state-cases> | <number-function>
<ending-cases-list> ::= "{" <ending-cases> "}"
<ending-cases> ::= <ending-case> | <ending-case> "," <ending-cases>
<ending-case> ::= <string-index> "=" <ending-rule>
<ending-rule> ::= <string> | <class-cases-list> | <state-cases> | <ending-function>
<class-cases-list> ::= "{" <class-cases> "}"
<class-cases> ::= <class-case> | <class-case> "," <class-cases>
<class-case> ::= <string-index> "=" <class-rule>
<class-rule> ::= <string> | <grammatical-cases-list> | <state-cases> | <class-function>
<state-cases> ::= "{" <indefinite-rule> "}" | "{" <indefinite-rule> "," <definite-rule> "}" | "{" <indefinite-rule> "," <definite-rule> "," <construct-rule> "}"
<indefinite-rule> ::= <state-rule>
<definite-rule> ::= <state-rule>
<construct-rule> ::= <state-rule>
<state-rule> ::= <string> | <grammatical-cases-list> | <state-function>
<grammatical-cases-list> ::= "{" <grammatical-cases> "}"
<grammatical-cases> ::= <grammatical-case> | <grammatical-case> "," <grammatical-cases>
<grammatical-case> ::= <string-index> "=" <grammatical-rule>
<grammatical-rule> ::= <string> | <simple-class-cases-list> | "{" <possessed-cases> "}" | <grammatical-function>
<simple-class-cases-list> ::= "{" <simple-class-cases> "}"
<simple-class-cases> ::= <simple-class-case> | <simple-class-case> "," <simple-class-cases>
<simple-class-case> ::= <string-index> "=" <simple-class-rule>
<simple-class-rule> ::= <string> | <simple-ending-cases-list> | <class-function>
<simple-ending-cases-list> ::= "{" <simple-ending-cases> "}"
<simple-ending-cases> ::= <simple-ending-case> | <simple-ending-case> "," <simple-ending-cases>
<simple-ending-case> ::= <string-index> "=" <simple-ending-rule>
<simple-ending-rule> ::= <string> | <ending-function>

<possessed-cases> ::= <possessed-case> | <possessed-case> "," <possessed-cases>
<possessed-case> ::= <string-index> "=" <possessed-rule>
<string-index> ::= <identifier> | "[" <string> "]"
<possessed-rule> ::= <string> | <possessed-function>
]]

local families = {
indian = {},
myriad = {},
short = {},
long = {}
}

local Family = Object:new{}

function Family:setDefaults(defscale)
local name = self.code
if name and name ~= '' then
local langs = number_systems.defaults
if not langs then
langs = {}
number_systems.defaults = langs
end
if defscale then
langs[name] = defscale
end
local scale = self.scale
if scale then
for k, v in pairs(scale) do
families[k][name] = self
if not defscale and v.default then
langs[name] = k
end
local s = v.default_script
if not s then
local script = v.script
if script then
s = singleEntry(script)
end
end
if s then
local scales = scripts.defaults
if not scales then
scales = {}
scripts.defaults = scales
end
local ls = scales[name]
if not ls then
ls = {}
scales[name] = ls
end
ls[k] = s
end
end
end
end
return nil
end

function Family:new (o)
local result = Object.new(self, o)
local name = result.code
if name and name ~= '' then
local k = result.default_scale
if not k then
local scale = result.scale
if scale then
k = singleEntry(scale)
end
end
result:setDefaults(k)
end
local pars = rawget(result, 'parameters')
if pars then
for k, v in pairs(pars) do
local p = parameters[k]
local names = v.names
if names then
for _, n in names do
local ns = p.names
if not ns then
ns = {}
p.names = ns
end
table.insert(ns, n)
end
addMultipleKeys(parameter_lookup, names, name)
end
local vales = v.values
if values then
for i, n in values do
local ns = p.lookup
if not ns then
ns = {}
p.lookup = ns
end
ns[n] = i
end
end
end
end
return result
end

local Script = Adder:new{}

local hant_script = Script:new{
code = 'hani',
additional = {
[4] = { '萬' },
[8] = { '億' },
[12] = { '兆' },
[16] = { '京' },
[20] = { '垓' },
[24] = { '秭' },
[28] = { '穣' },
[32] = { '溝' },
[36] = { '澗' },
[40] = { '正' },
[44] = { '載' },
[48] = { '極' }
}
}

local hanja_script = hant_script:new{}

local kanji_script = hant_script:new{
additional = {
[4] = { '万' }
}
}

local hans_script = kanji_script:new{
code = 'hans',
additional = {
[8] = { '亿' },
[32] = { '沟' },
[36] = { '涧' },
[44] = { '载' },
[48] = { '极' }
}
}

local hangul_script = Script:new{
code = 'hang',
additional = {
[4] = { '만' },
[8] = { '억' },
[12] = { '조' },
[16] = { '경' },
[20] = { '해' },
[24] = { '자' },
[28] = { '양' },
[32] = { '구' },
[36] = { '간' },
[40] = { '정' },
[44] = { '재' },
[48] = { '극' }
}
}

local language_ko = Family:new{
code = 'ko',
scale = { myriad = Adder:new{
top = 48,
link = '큰_수의_이름',
script = { hang = hangul_script, hani = hanja_script },
default_script = 'hang' } }
}

local language_ja = Family:new{
code = 'ja',
scale = { myriad = Adder:new{
top = 48,
link = '10の冪',
script = { hani = kanji_script } } }
}

local language_zh = Family:new{
code = 'zh',
scale = { myriad = Adder:new{
top = 48,
link = '中文数字',
script = { hans = hans_script, hant = hant_script },
default_script = 'hans' } }
}

local latin = Family:new{
code = 'la',

space = true,

root = 'lli',

suffix = { 'o', 'ard' },

prefix = { 'mi', 'bi', 'tri', 'quadri', 'quinti', 'sexti', 'septi', 'octi', 'noni', 'deci',
[20] = 'viginti',
[30] = 'triginti',
[40] = 'quadraginti',
[50] = 'quinquaginti',
[60] = 'sexaginti',
[70] = 'septuaginti',
[80] = 'octoginti',
[90] = 'nonaginti',
[100] = 'centi'
},

unit_prefix = { 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem' },

prefix_exception = { [16] = { la = 'sedeci' } },

unit_prefix_exception = {},

inflection = { { o = { { [''] = '', g = 'nis', da = 'ni', accus = { [''] = 'nem', n = ''}, abl = 'ni' } },
[''] = { { [''] = 'um', g = 'i', da = 'o', abl = 'o' } } },
{ o = { { [''] = { [''] = 'nes', n = 'nia' }, g = 'nium', da = 'nibus', abl = 'nibus' } },
[''] = { { [''] = 'a', g = 'orum', da = 'is', abl = 'is' } } } },

scale = { long = Adder:new{ top = 306, link = 'Nomina permagnorum numerorum' } }
}

local function makeArdMaker(minval, thousand)
return function (scale, i, step, args, r, simplify)
if i < minval then
return nil
end
local j = math.floor(i / step)
if (j*step)+3 == i then
local u, simp, stem = scale:unit(i-3, args, 1000, false)
return thousand .. " " .. u, (r == 1), stem
else
return nil
end
end
end

local language_ia = latin:new{
code = 'ia',
suffix = { 'on', 'ardo' },
inflection = { stem = makeArdMaker(15, "mille"),
'',
function (u, args, r, simplify)
if mw.ustring.sub(u, 1, 6) == "mille " then
return u
else
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "o" then return u .. "s" else return u .. "es" end
end
end },
scale = { long = Adder:new{
top = 18,
link = function(i, stem, u)
local start, finish = string.find(u, ' ')
if not start then
return stem .. linkEnd(u)
else
local first = mw.ustring.sub(u, 1, start - 1)
local second = mw.ustring.sub(u, finish + 1)
local secondlink = linkBegin('ia') .. stem .. linkEnd(second)
return first .. " " .. secondlink, true
end
end } }
}

local language_is = latin:new{
code = 'is',
root = 'llj',
suffix = { 'ón', 'arð' },
prefix = { [4] = 'kvaðri', [5] = 'kvinti' },
inflection = { { n = { { [''] = '', g = 'ar' },
{ n = 'in', accus = 'ina', da = 'inni', g = 'arinnar' } },
[''] = { { n = 'ur', accus = '', da = 'i', g = 's' },
{ n = 'urinn', accus = 'inn', da = 'inum', g = 'sins' } } },
{ n = { { [''] = 'ir', da = 'um', g = 'a' },
{ [''] = 'irnar', da = 'unum', g = 'anna' } },
[''] = { { n = 'ar', accus = 'a', da = 'um', g = 'a' } ,
{ n = 'arnir', accus = 'ana', da = 'unum', g = 'anna' } } } },
scale = { long = Adder:new{ top = 30, link = 'Stórar tölur' } }
}

local language_nl = latin:new{
code = 'nl',
root = 'lj',
suffix = { 'oen', 'ard' },
prefix_exception = { [16] = { nl = 'sedeci' } },
inflection = {},
scale = { long = Adder:new{ top = 141, link = 'Lijst van machten van tien' } }
}

local language_af = language_nl:new{
code = 'af',
prefix = { [4] = 'kwadri', [5] = 'kwinti', [6] = 'seksti', [8] = 'okti', [10] = 'desi' },
scale = { long = Adder:new{ top = 63, link = 'Kort en lang skaalverdeling' } }
}

local c_family = latin:new{
code = '',
capitalize = true
}

local language_de = c_family:new{
code = 'de',
suffix = { 'on', 'arde' },
prefix = { [8] = 'Okti', [10] = 'dezi' },
unit_prefix = { [2] = 'Do', [6] = 'Se', [8] = 'Okto' },
inflection = { '', { e = 'n',
[''] = 'en' } },
scale = { long = Adder:new{ top = 306, link = 'Zahlennamen' } }
}

local language_lb = c_family:new{
code = 'lb',
suffix = { 'oun', 'ard' },
inflection = { '', 'en' },
scale = { long = Adder:new{ top = 27, link = 'Lëscht vun de Prefixe fir Moosseenheeten' } }
}

local li_family = latin:new{
code = '',
root = 'li'
}

local language_ca = li_family:new{
code = 'ca',
suffix = { 'ó', 'ard' },
inflection = { '', { d = 's',
[''] = function (u, args, r, simplify) return mw.ustring.sub(u, 1, -2) .. "ons" end } },
scale = { long = Adder:new{ top = 306, link = 'Escales curta i llarga' } }
}

local language_eo = li_family:new{
code = 'eo',
suffix = { 'ono', 'ardo' },
prefix = { [2] = 'dui', [4] = 'kvari', [5] = 'kvini', [6] = 'sesi', [7] = 'sepi', [8] = 'oki', [9] = 'naŭi', [10] = 'deki' },
unit_prefix = { [4] = 'kvatuor', [5] = 'kvin', [6] = 'seks', [8] = 'okto' },
inflection = { '', 'j' },
scale = { long = Adder:new{ top = 177, link = 'Vortoj por grandegaj nombroj' } }
}

local language_it = li_family:new{
code = 'it',
suffix = { 'one', 'ardo' },
inflection = { '', function (u, args, r, simplify) return mw.ustring.sub(u, 1, -2) .. "i" end },
scale = { long = Adder:new{
top = 63,
link = function(i, stem, u) return ("Ordini di grandezza (numeri)#10" .. i) .. linkEnd(u) end,
exception = {
[36] = 'none',
[39] = 'none',
[42] = 'none',
[45] = 'none',
[48] = 'none',
[51] = 'none',
[54] = 'none',
[57] = 'none'
} } }
}

local language_scn = li_family:new{
code = 'scn',
suffix = { 'uni', 'ardu' },
inflection = { '', function (u, args, r, simplify)
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "i" then return u else return mw.ustring.sub(u, 1, -2) .. "i" end
end},
scale = { long = Adder:new{
top = 63,
exception = {
[30] = 'none',
[33] = 'none',
[36] = 'none',
[39] = 'none',
[42] = 'none',
[45] = 'none',
[48] = 'none',
[51] = 'none',
[54] = 'none',
[57] = 'none'
} } }
}

local language_pl = li_family:new{
code = 'pl',
suffix = { 'on', 'ard' },
prefix = { [3] = 'try', [4] = 'kwadry', [5] = 'kwinty', [6] = 'seksty', [7] = 'septy', [8] = 'okty', [10] = 'decy' },
inflection = { { { n = '', g = 'a', da = 'owi', accus = '', instrum = 'em', [''] = { n = 'ie', [''] = 'zie' } } },
{ { [''] = 'y', g = 'ów', da = 'om', instrum = 'ami', lo = 'ach' } },
[5] = { { [''] = function (u, args, r, simplify)
local floor = math.floor
local n = floor(r/100)
local m = r - n * 100
if m < 2 or (m > 4 and m < 22) then
return u .. 'ów'
elseif m < 5 then
return u .. 'y'
else
local o = floor(m/10)
local p = m - o * 10
if p > 1 and p < 5 then
return u .. 'y'
else
return u .. 'ów'
end
end
end,
g = 'ów', da = 'om', instrum = 'ami', lo = 'ach', v = 'y' } },
fraction = 'a' },
scale = { long = Adder:new{ top = 75, link = 'Liczebniki główne potęg tysiąca' } }
}

local language_pt = li_family:new{
code = 'pt',
suffix = { 'ão' },
inflection = { stem = makeArdMaker(9, "mil"),
'',
function (u, args, r, simplify)
if mw.ustring.sub(u, 1, 4) == "mil " then
return u
else
return mw.ustring.sub(u, 1, -3) .. "ões"
end
end },
scale = { long = Adder:new{
top = 60,
exception = { [6] = { 'milhão' } } } }
}

local ib_family = latin:new{
code = '',
root = 'll',
suffix = { 'ón', 'ardo' }
}

local milArdMaker = makeArdMaker(9, "mil")

local language_an = ib_family:new{
code = 'an',
prefix = { [4] = 'quatri' },
inflection = { stem = milArdMaker,
'',
function (u, args, r, simplify)
if mw.ustring.sub(u, 1, 4) == "mil " then
return u
else
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "o" then return u .. "s" else return mw.ustring.sub(u, 1, -3) .. "ons" end
end
end },
scale = { long = Adder:new{ top = 24, link = 'Potencia de diez' } }
}

local language_gl = ib_family:new{
code = 'gl',
inflection = { stem = milArdMaker,
'',
function (u, args, r, simplify)
if mw.ustring.sub(u, 1, 4) == "mil " then
return u
else
return u .. "s"
end
end },
scale = { long = Adder:new{ top = 18 } }
}

local es_family = ib_family:new{
code = '',
prefix = { [4] = 'cuatri' },
plural = function (u, args, r, simplify)
if mw.ustring.sub(u, 1, 4) == "mil " then
return u
else
local n = mw.ustring.len(u)
if mw.ustring.sub(u, n, n) == "o" then return u .. "s" else return mw.ustring.sub(u, 1, -3) .. "ones" end
end
end
}

local language_ast = es_family:new{
code = 'ast',
inflection = { stem = milArdMaker,
'',
es_family.plural },
scale = { long = Adder:new{ top = 30, link = 'Escales numbériques llarga y curtia' } }
}

local language_es = es_family:new{
code = 'es',
unit_prefix = { [4] = 'cuatro', [9] = 'noven' },
inflection = { stem = makeArdMaker(15, "mil"),
'',
es_family.plural },
scale = { long = Adder:new{ top = 120, link = function(i, stem, u) return ("Orden de magnitud (números)#10" .. i) .. linkEnd(u) end } }
}


local onard_family = latin:new{
code = '',
suffix = { 'on', 'ard' },
}

local language_en = onard_family:new{
code = 'en',
inflection = { { { n = '', possessi = "'s" } },
{ { n = function (u, args, r, simplify)
if simplify then
return u .. 's'
else
return u
end
end,
possessi = function (u, args, r, simplify)
if simplify then
return u .. "s'"
else
return u .. "'s"
end
end } } },
default_scale = 'short',
scale = {
long = Adder:new{ top = 306, link = link_en, additional = { [100] = { 'googol' } } },
short = Adder:new{ top = 303, link = link_en, additional = { [100] = { 'googol' } } },
indian = Adder:new{
top = 14,
link = function(i, stem, u)
local start, finish = string.find(u, ' ')
if not start then
return u .. linkEnd(u)
else
local first = mw.ustring.sub(u, 1, start - 1)
local second = mw.ustring.sub(u, finish + 1)
local firstlink = linkBegin('en') .. first .. linkEnd(first)
if first == second then
return firstlink .. " " .. second, true
else
return firstlink .. " " .. linkBegin('en') .. second .. linkEnd(second), true
end
end
end,
additional = {
[5] = { 'lakh' },
[7] = { 'crore' },
[12] = { 'lakh crore' },
[14] = { 'crore crore' }
} }
}
}

local language_fr = onard_family:new{
code = 'fr',
prefix = { [10] = 'déci' },
unit_prefix = { [3] = 'tré', [9] = 'noni' },
inflection = { '', 's' },
scale = { long = Adder:new{ top = 57, link = function(i, stem, u) return (i > 36 and "Noms des grands nombres" or ("Ordres de grandeur de nombres#10" .. i)) .. linkEnd(u) end } }
}

local k_family = onard_family:new{
code = '',
prefix = { [4] = 'kvadri', [5] = 'kvinti', [8] = 'okti' }
}

local language_hu = k_family:new{
code = 'hu',
suffix = { 'ó', 'árd' },
prefix = { [6] = 'szexti', [7] = 'szepti' },
unit_prefix = { [3] = 'tri', [4] = 'kva', [5] = 'kvint', [6] = 'szex' },
inflection = { { d = { { n = '', accus = 'ot', da = 'nak', instrum = 'dal', ['ca-fi'] = 'ért', tr = 'dá', ter = 'ig', ['es-fo'] = 'ként', ine = 'ban', supere = 'on', ades = 'nál', il = 'ba', subl = 'ra', al = 'hoz', el = 'ból', de = 'ról', abl = 'tól', possessi = { 'é', 'éi' } } },
[''] = { { n = '', accus = 't', da = 'nak', instrum = 'val', ['ca-fi'] = 'ért', tr = 'vá', ter = 'ig', ['es-fo'] = 'ként', ine = 'ban', supere = 'n', ades = 'nál', il = 'ba', subl = 'ra', al = 'hoz', el = 'ból', de = 'ról', abl = 'tól', possessi = { 'é', 'éi' } } } },
{ d = { { n = 'ok', accus = 'okat', da = 'oknak', instrum = 'okkal', ['ca-fi'] = 'okért', tr = 'okká', ter = 'okig', ['es-fo'] = 'okként', ine = 'okban', supere = 'okon', ades = 'oknál', il = 'okba', subl = 'okra', al = 'okhoz', el = 'okból', de = 'okról', abl = 'októl', possessi = { 'oké', 'okéi' } } },
[''] = { { n = 'k', accus = 'kat', da = 'knak', instrum = 'kkal', ['ca-fi'] = 'kért', tr = 'kká', ter = 'kig', ['es-fo'] = 'kként', ine = 'kban', supere = 'kon', ades = 'knál', il = 'kba', subl = 'kra', al = 'khoz', el = 'kból', de = 'król', abl = 'któl', possessi = { 'ké', 'kéi' } } } }
},
possessive = { d = { { { { 'om', 'aim' } }, { { 'od', 'jaid' } }, { { 'ja', 'jai'} } },
{ { { 'unk', 'jaink' } }, { { 'otok', 'jaitok' } }, { { 'juk', 'jaik'} } } },
[''] = { { { { 'm', 'im' } }, { { 'd', 'id' } }, { { 'ja', 'i'} } },
{ { { 'nk', 'ink' } }, { { 'tok', 'itok' } }, { { 'juk', 'ik'} } } } },
scale = { long = Adder:new{ top = 96, link = 'Tíz hatványai' } }
}

local language_sv = k_family:new{
code = 'sv',
root = 'lj',
inflection = { { { n = '', g = 's' },
{ n = 'en', g = 'ens' } },
{ { n = 'er', g = 'ers' },
{ n = 'erna', g = 'ernas' } } },
scale = { long = Adder:new{ top = 177, link = 'Namn på stora tal' } }
}

local s_family = k_family:new{
code = '',
prefix = { [6] = 'seksti' }
}

local language_da = s_family:new{
code = 'da',
inflection = { { { n = '', possessi = "s" },
{ n = 'en', possessi = "ens" } },
{ { n = 'er', possessi = "ers" },
{ n = 'erne', possessi = "ernes" } } },
scale = { long = Adder:new{ top = 63, link = 'Store tal' } }
}

local language_fi = s_family:new{
code = 'fi',
root = 'lj',
suffix = { 'oon' },
prefix = { [9] = 'novi', [10] = 'deki' },
inflection = { stem = makeArdMaker(9, "tuhat"),
function (u, args, r, simplify)
local case = args.case
if mw.ustring.sub(u, 1, 6) == "tuhat " then
local base = 'tuha'
local cases = { n = 't', ['accus-n'] = 't', ['accus-g'] = 'nnen', g = 'nnen', pa = 'tta', ine = 'nnessa', el = 'nnesta', il = 'nteen', ades = 'nnella', abl = 'nnelta', al = 'nnelle', es = 'netena', tr = 'nneksi', abe = 'nnetta' }
return base .. cases[case] .. mw.ustring.sub(u, 6)
else
local cases = { n = 'a', ['accus-n'] = 'a', ['accus-g'] = 'an', g = 'an', pa = 'aa', ine = 'assa', el = 'asta', il = 'aan', ades = 'alla', abl = 'alta', al = 'alle', es = 'ana', tr = 'aksi', abe = 'atta', }
return u .. cases[case]
end
end,
function (u, args, r, simplify)
local case = args.case
if mw.ustring.sub(u, 1, 6) == "tuhat " then
local base = 'tuha'
local cases = { n = 'tta', ['accus-n'] = 'nnet', g = 'nsien', pa = 'nsia', ine = 'nsissa', el = 'nsista', il = 'nsiin', ades = 'nsilla', abl = 'nsilta', al = 'nsille', es = 'nsina', tr = 'nsiksi', instruc = 'nsin', abe = 'nsitta', comi = 'nsine' }
if simplify and (case == '' or case == 'n') then
return u
else
return base .. cases[case] .. mw.ustring.sub(u, 6)
end
else
local cases = { n = 'aa', ['accus-n'] = 'at', g = 'ien', pa = 'ia', ine = 'issa', el = 'ista', il = 'iin', ades = 'illa', abl = 'ilta', al = 'ille', es = 'ina', tr = 'iksi', instruc = 'in', abe = 'itta', comi = 'ine' }
if simplify and (case == '' or case == 'n') then
return u .. 'at'
else
return u .. cases[case]
end
end
end },
scale = { long = Adder:new{ top = 63, link = 'Suurten lukujen nimet' } }
}

local language_no = s_family:new{
code = 'no',
prefix = { [10] = 'desi' },
unit_prefix = { [2] = 'do', [5] = 'kvin', [6] = 'seks', [8] = 'okto' },
inflection = { { { n = '', g = 's' },
{ n = 'en', g = 'ens' } },
{ { n = 'er', g = 'ers' },
{ n = 'ene', g = 'enes' } } },
scale = { long = Adder:new{ top = 81, link = 'Navn på store tall' } }
}

local language_sl = s_family:new{
code = 'sl',
root = 'lij',
inflection = { { n = '',
[''] = 'a' },
{ d = 'i',
[''] = 'a' },
'e',
[5] = { d = '',
[''] = 'ov' },
fraction = { d = 'e',
[''] = 'a' } },
scale = { long = Adder:new{ top = 63, link = 'Imena velikih števil' } }
}

local u_family = k_family:new{
code = '',
root = 'li',
unit_prefix = { [4] = 'kvadro', [5] = 'kvin' }
}

local language_cs = u_family:new{
code = 'cs',
prefix = { [50] = 'kvinkvaginti' },
inflection = { { n = { { n = '', [''] = 'u', accus = '', instrum = 'em', v = 'e'} },
[''] = { { n = 'a', g = 'y', [''] = 'ě', accus = 'u', instrum = 'ou', v = 'o'} } },
{ n = { { [''] = 'y', g = 'ů', da = 'ům', lo = 'ech'} },
[''] = { { [''] = 'y', g = '', da = 'ám', instrum = 'ami', lo = 'ách'} } },
[5] = { n = { { [''] = 'ů', da = 'ům', instrum = 'y', lo = 'ech', v = 'y' } },
[''] = { { [''] = '', da = 'ám', instrum = 'ami', lo = 'ách', v = 'y' } } },
fraction = { n = 'u',
[''] = 'y' } },
scale = { long = Adder:new{ top = 99, link = 'Desítková soustava#Názvy velkých čísel' } }
}

local function ardInflectGenitivePlural_sk(u, args, r, simplify)
return mw.ustring.sub(u, 1, -4) .. "árd"
end

local language_sk = u_family:new{
code = 'sk',
suffix = { 'ón', 'ard' },
prefix = { [40] = 'kvadraginti', [50] = 'kvinginti', [60] = 'seksaaginti', [80] = 'oktoginti', [90] = 'nonaginti' },
unit_prefix = { [8] = 'okto' },
inflection = { { n = { { [''] = '', g = 'a', da = 'u', instrum = 'om', lo = 'e' } },
[''] = { { n = 'a', g = 'y', accus = 'u', instrum = 'ou', [''] = 'e' } } },
{ n = { { [''] = 'y', g = 'ov', da = 'om', instrum = 'mi', lo = 'och' } },
[''] = { { n = 'y', da = 'ám', accus = 'y', instrum = 'ami', lo = 'ách',
g = ardInflectGenitivePlural_sk } } },
[5] = { n = { { [''] = 'ov', da = 'om', instrum = 'mi', lo = 'och' } },
[''] = { { [''] = ardInflectGenitivePlural_sk,
da = 'ám', instrum = 'ami', lo = 'ách' } } },
fraction = { n = 'a',
[''] = ardInflectGenitivePlural_sk } },
scale = { long = Adder:new{ top = 306, link = 'Veľké čísla' } }
}

function Family:getPrefix(i)
return self:tableInherit('prefix', i)
end

function Family:getUnitPrefix(i)
return self:tableInherit('unit_prefix', i)
end

function Family:makePrefix(j)
local entry = self.prefix_exception[j] and self.prefix_exception[j][self.code]
local p
if entry then
p = entry
else
p = self:getPrefix(j)
if not p then
if j < 11 then
return nil
elseif j < 100 then
local k = math.floor(j / 10)
local d = k * 10
local l = j - d
local unitentry = self.unit_prefix_exception[l] and self.unit_prefix_exception[l][self.code]
local u
if unitentry then
u = unitentry
else
u = self:getUnitPrefix(l)
end
local decentry = self.prefix_exception[d] and self.prefix_exception[d][self.code]
local x
if decentry then
x = decentry
else
x = self:getPrefix(d)
end
p = u .. x
else
return nil
end
end
end
if self.capitalize then
return mw.ustring.upper(mw.ustring.sub(p, 1, 1)) .. mw.ustring.sub(p, 2)
else
return p
end
end

function Family:buildOne(i, step)
local k = i / 3
if k ~= _round(k, 0) then
return nil
end
local j
if step == 3 then
j = math.floor((i - 3)/ step)
else
j = math.floor(i / step)
end
if j < 1 then
return nil
else
local pref = self:makePrefix(j)
local suf
if step == 3 then
suf = self.suffix[1]
else
suf = (j * step) == i and self.suffix[1] or self.suffix[2]
end
return pref .. self.root .. suf
end
end

local Scale = Adder:new{}

local indian_scale = Scale:new{
name = 'indian',
step = 1,
family = families['indian']
}

local myriad_scale = Scale:new{
name = 'myriad',
step = 4,
family = families['myriad']
}

local scale3 = Scale:new{
build = true
}

local short_scale = scale3:new{
name = 'short',
step = 3,
family = families['short']
}

local long_scale = scale3:new{
name = 'long',
step = 6,
family = families['long']
}

local scales = {
indian = indian_scale,
long = long_scale,
myriad = myriad_scale,
short = short_scale,

ind = indian_scale,
fra = long_scale,
usa = short_scale
}


function Scale:getLanguage(lang)
local family = self.family
return family and family[lang]
end

function Scale:getField(name, lang, top)
local family = self.family
local language = family and family[lang]
local scales = language and language.scale
local special = scales and scales[self.name]
local result = special and special[name]
if result then
return result, true -- overriden
else
local v = self[name]
if top then
return v, false
else
return v and v[lang], false
end
end
end

function Scale:getOne(i, args, r)
local lang = args.lang
local one, simplify

local function getAdditional(o, lang)
local one, simplify
local script = o.script
if script then
local top = (lang and script[lang]) or script
local scr = top and top[args.script]
if scr then
one, simplify = scr:getAdditional(nil, i)
end
end

if not one then
one, simplify = o:getAdditional(lang, i)
end

return one, simplify
end

do
local exception, over = self:getField('exception', lang, true)
if exception then
local top = exception[i]
local entry = top and ((over or type(top) == 'string') and top or top[lang])
if entry then
one, simplify = entry[1], entry.simplify
end
end
end

local language = args.language

if not one then
local scales = language.scale
local special = scales and scales[self.name]
if special then
one, simplify = getAdditional(special, nil)
end
end

if not one then
one, simplify = getAdditional(self, lang)
end

if one then
return one, simplify
elseif language.inflection and language.inflection.stem then
local d = language.inflection.stem
if type(d) == 'function' then
return d(self, i, self.step, args, r, simplify)
end
else
return nil
end
end

function Scale:unit(i, args, r, simplify)
local language, one, stem, entry, inflectState, inflectEndings, inflectClass

local function makeApplier(simplify, f)
return function (d, arg)
if not d then
return nil
elseif type(d) == 'function' then
return d(one, args, r, simplify), simplify, stem
elseif type(d) == 'table' then
return f(d, arg)
else
return one .. d, simplify, stem
end
end
end

local function makeDoer(topn, ensure, arr, simplify, f)
return function (n, arg)
local d = arr[n]
if d then
return f(d, arg)
else
if topn > 1 and n > 2 then
d = arr[2]
if d then
return f(d, arg)
end
end
if topn > 0 and n > 1 then
d = arr[1]
if d then
return f(d, arg)
end
end
if ensure then
return one, simplify, stem
else
return nil
end
end
end
end

local function doMain(arr, simplify, ensure, applier, doer, f)
if arr then
return f(applier, doer)
elseif ensure then
return one, simplify, stem
else
return nil
end
end

local function doFun(arr, simplify, topn, ensure, application, main)
local applier = makeApplier(simplify, application)
local doer
if topn then
doer = makeDoer(topn, ensure, arr, simplify, applier)
end
return doMain(arr, implify, ensure, applier, doer, main)
end

local function inflectPossessed(arr, other, simplify)
return doFun(arr, simplify, 1, true,
function(d, arg) return inflectEndings(d, simplify, false, false, false) end,
function (applier, doer)
if (other and args.possessed) or ((not other) and r > 1) then
return doer(2)
else
return doer(1)
end
end)

end

local function declineCase(d, simplify, docla)
local applyCase = makeApplier(simplify,
function(d, arg)
if docla then
local result, simp, s = inflectClass(d, simplify, false, true, false)
if result then
return result, simp, s
end
end
return inflectPossessed(d, true, simplify)
end)
local c = d[args.case]
if not c then
c = d[''] -- default inflection
end
return applyCase(c)
end

inflectClass = function(t, simplify, dosta, dosub, docas)
local class = args.class
return doFun(t, simplify, 0, false,
function(v, arg)
local result, simp, s
if dosub then
result, simp, s = inflectEndings(v, simplify, false, false, false)
end
if result then
return result, simp, s
elseif docas then
result, simp, s = declineCase(v, simplify, false)
end
if result then
return result, simp, s
elseif dosta then
return inflectState(v, simplify, false)
else
return nil
end
end,
function(applier, doer)
local done, elsevalue
for k, v in pairs(t) do
if k == '' then
elsevalue = v
if done then
break
end
elseif not done and type(k) == 'string' then
local result, simp, s = doer(class)
if result then
return result, simp, s
else
if elsevalue then
break
else
done = true
end
end
end
end
return applier(elsevalue)
end)
end

inflectState = function(arr, simplify, docla)
return doFun(arr, simplify, 1, true,
function(d, arg) return declineCase(d, simplify, docla) end,
function(applier, doer)
local state = args.state
if state == 'c' then
return doer(3)
elseif state == 'd' then
return doer(2)
else
return doer(1)
end
end)

end

local function possessiveClusivity(arr, n, plural, simplify)
return doFun(arr, simplify, 1, true,
function(d, arg) return inflectPossessed(d, false, simplify) end,
function(applier, doer)
if plural then
local exclude = args.exclude
if not exclude or n ~= 2 then
return doer(1)
elseif exclude == 3 then
return doer(2)
elseif exclude == 2 then
return doer(3)
else
return doer(1)
end
else
return doer(1)
end
end)
end

local function possessivePerson(arr, plural, arg, simplify)
return doFun(arr, simplify, 2, true,
function(d, arg) return possessiveClusivity(d, arg, plural, simplify) end,
function(applier, doer) return doer(args.person, args.person) end)

end

local function possessivePlural(arr, simplify)
return doFun(arr, simplify, 1, true,
function(d, arg) return possessivePerson(d, arg, nil, simplify) end,
function(applier, doer)
if args.plural then
return doer(2, true)
else
return doer(1, false)
end
end)
end

inflectEndings = function(t, simplify, docla, dosta, dopos)
return doFun(t, simplify, nil, true,
function(v, arg)
local result, simp, s
if docla then
result, simp, s = inflectClass(v, simplify, true, false, true)
end
if result then
return result, simp, s
elseif dosta then
return inflectState(v, simplify, docla)
elseif dopos then
return possessivePlural(v, simplify)
else
return nil
end
end,
function(applier, doer)
local olen, elsevalue
local ulen = mw.ustring.len
local usub = mw.ustring.sub
for k, v in pairs(t) do
if k == '' then
elsevalue = v
elseif type(k) == 'string' then
local l = ulen(k)
if not olen then
olen = ulen(one)
end
if olen >= l then
if k == usub(one, -l, -1) then
return applier(v)
end
end
end
end
return applier(elsevalue)
end)
end

local function inflectNumberCase(number_case, simplify)
local applyNumberCase = makeApplier(simplify,
function(d, arg)
local result, simp, s = inflectEndings(d, simplify, true, true, false)
if result then
return result, simp, s
else
return inflectState(d, simplify, true)
end
end)
if entry and entry[number_case] then
return entry[number_case], simplify, entry[1] or stem
elseif not one then
return nil
elseif language.inflection then
return applyNumberCase(language.inflection[number_case])
end
end

local function inflectNumber(number_case, simplify)
local result, simp, st
if number_case == 5 then
result, simp, st = inflectNumberCase(5, simplify)
end
if result then
return result, simp, st
end
if number_case == 5 or number_case == 3 then
result, simp, st = inflectNumberCase(3, simplify)
end
if result then
return result, simp, st
end
if number_case == 5 or number_case == 3 or number_case == 2 then
result, simp, st = inflectNumberCase(2, simplify)
end
if result then
return result, simp, st
else
result, simp, st = inflectNumberCase(1, simplify)
if result then
return result, simp, st
else
return one, simplify, stem
end
end
end

local function possessive(simplify)
local applyPossessive = makeApplier(simplify,
function(d, arg)
local result, simp, s = inflectEndings(d, simplify, false, false, true)
if result then
return result, simp, s
else
return possessivePlural(d, simplify)
end
end)
if entry and entry.possessive then
return entry.possessive, simplify, entry.possessive
elseif not one then
return nil
else
return applyPossessive(language.possessive)
end
end

language = args.language
local s
one, s, stem = self:getOne(i, args, r)
local simp = simplify or s
if not one then
one = self.build and language and language:buildOne(i, self.step)
stem = one
end
local exception, over = self:getField('exception', lang, true)
local top = exception and exception[i]
entry = top and ((over or type(top) == 'string') and top or top[lang])
if args.person then
return possessive(simplify)
else
if r == 1 then
return inflectNumber(1, simp)
elseif r == 2 then
return inflectNumber(2, simplify)
elseif r == 3 or r == 4 then
return inflectNumber(3, simplify)
elseif r == _round(r, 0) then
return inflectNumber(5, simplify)
else
local result, rs, st = inflectNumberCase('fraction', simp)
if result then
return result, rs, st
else
return inflectNumber(5, simplify)
end
end
end
end

function Scale:unitLink(lk, i, stem, u, lang)
if lk then
local f = self:getField('link', lang)
if f then
if type(f) == 'function' then
local l, full = f(i, stem, u)
if full then
return l
else
return linkBegin(lang) .. l
end
else
return linkBegin(lang) .. f .. linkEnd(u)
end
else
return linkBegin('en') .. link_en(i, stem, u)
end
else
return u
end
end

function Scale:found(args, i, r)
local lk = args.lk
local u, simp, stem = self:unit(i, args, r, args.simplify)
if not u then
return nil
elseif args.simplify or simp then
return self:unitLink(lk, i, stem, u, args.lang)
else
local lang = args.lang
return mf.formatNum(r, lang, args.prec) .. ((args.language.space and " ") or "") .. self:unitLink(lk, i, stem, u, lang)
end
end

function Scale:binary(x, args, top, bottom)
local target, target_r
local lang = args.lang
local prec = args.prec
local floor = math.floor
local pow = math.pow
local rou = _round
local block, iblock
if self.step == 4 then
block = 10000
iblock = 4
else
block = 1000
iblock = 3
end
while top >= bottom do
local i
if top == bottom then
i = top
else
local diff = top - bottom
local d = floor(diff / 2)
local m = bottom + d
if m/iblock == floor(m/iblock) then
i = m
else
i = m + 2
end
end
local y = x / pow(10,i)
local r = rou(y, prec)
local exception, over = self:getField('exception', lang, true)
local entry = exception and exception[i]
if not entry or (entry ~= 'none' and (over or entry[lang] ~= "none")) then
if r >= block and top > i then
bottom = i + iblock
target = i
target_r = r
elseif r >= 1 then
local result = self:found(args, i, r)
if result then
return result
else
top = i - iblock
end
else
top = i - iblock
end
elseif r < block or top == i then
top = i - iblock
else
local result
if top > i and r >= block then
result = self:binary(x, args, top, i + iblock)
end
if result then
return result
elseif i > bottom then
result = self:binary(x, args, i - iblock, bottom)
if result then
return result
end
end
break
end
end

if target then
local result = self:found(args, target, target_r)
if result then
return result
else
return nil
end
end

return nil
end

function Scale:wordify(x, args)
local prec = args.prec
return mf.formatNum(_round(x, prec), args.lang, prec)
end

function scale3:wordify(x, args)
local toptop = self:getField('top', args.lang)
if toptop then
do
local top = toptop
local bottom = 102
local result = self:binary(x, args, top, bottom)
if result then
return result
end
end

if 100 <= toptop then -- allow googol
local top = 100
local bottom = 100
local result = self:binary(x, args, top, bottom)
if result then
return result
end
end

do
local top = (99 <= toptop and 99) or toptop
local bottom = 6
local result = self:binary(x, args, top, bottom)
if result then
return result
end
end
end

return Scale.wordify(self, x, args)
end

function myriad_scale:wordify(x, args)
local toptop = self:getField('top', args.lang)
if toptop then
do
local top = toptop
local bottom = 4
local result = self:binary(x, args, top, bottom)
if result then
return result
end
end
end

return Scale.wordify(self, x, args)
end

function indian_scale:wordify(x, args)
local pow = math.pow
local rou = _round
local prec = args.prec
local scales = args.language.scale
local special = scales and scales[self.name]
local scripts = special and special.script
local scr = (scripts and scripts[lang]) or special
for i, _ in reverseSparseIpairs((scr and scr.additional) or self.additional) do
local y = x / pow(10,i)
local r = rou(y, prec)
if r >= 1 then
return self:found(args, i, r)
end
end

return Scale.wordify(self, x, args)
end

function p._wordify(x, prec, lk, numsys, lang, script, state, case, class, possessed, person, plural, exclude, simplify)
local deflang = language:default(nil, lang)
local defsys = number_systems:default(deflang, numsys)
local canonsys = number_systems:get(defsys) or defsys

if tonumber(x) then
local scale = scales[canonsys]
if scale then
local language = scale:getLanguage(deflang)
if language then
local defscript = scripts:default(deflang, script, canonsys)
local canonscript = scripts:get(defscript) or defscript
local defstate = states:default(deflang, state)
local canonstate = states:get(defstate) or defstate
local defcase = cases:default(deflang, case)
local canoncase = cases:get(defcase) or defcase
local defclass = classes:default(deflang, class)
local canonclass = classes:get(defclass) or defclass

local args = {
prec = prec,
lk = lk,
lang = deflang,
language = language,
script = canonscript,
state = canonstate,
case = canoncase,
class = canonclass,
possessed = possessed,
person = person,
plural = plural,
exclude = exclude,
simplify = simplify
}

return scale:wordify(x, args)
else
return err("Language '" .. deflang .. "' not supported by number system '" .. canonsys .. "'")
end
else
return err("number system '" .. canonsys .. "' not supported")
end
else
return err("Not a number: " .. x)
end
end

--[[
Helper function that interprets the input numerically. If the
input does not appear to be a number, attempts evaluating it as
a parser functions expression.
]]

function p._cleanNumber(number_string)
if type(number_string) == 'number' then
-- We were passed a number, so we don't need to do any processing.
return number_string, tostring(number_string)
elseif type(number_string) ~= 'string' or not number_string:find('%S') then
-- We were passed a non-string or a blank string, so exit.
return nil, nil;
end

-- Attempt basic conversion
local number = tonumber(number_string)

-- If failed, attempt to evaluate input as an expression
if number == nil then
local success, result = pcall(mw.ext.ParserFunctions.expr, number_string)
if success then
number = tonumber(result)
number_string = tostring(number)
else
number = nil
number_string = nil
end
else
number_string = number_string:match("^%s*(.-)%s*$") -- String is valid but may contain padding, clean it.
number_string = number_string:match("^%+(.*)$") or number_string -- Trim any leading + signs.
if number_string:find('^%-?0[xX]') then
-- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead.
number_string = tostring(number)
end
end

return number, number_string
end

return p

Navigation menu