local export = {}
local m_table = require( "Module:table" )
local m_links = require( "Module:links" )
local m_string_utilities = require( "Module:string utilities" )
local lang = require( "Module:languages" ).getByCode( "mn" )
local com = require( "Module:mn-common" )
local iut = require( "Module:inflection utilities" )
local m_para = require( "Module:parameters" )
local char = mw.ustring.char
local find = mw.ustring.find
local format = mw.ustring.format
local len = m_string_utilities.ulen
local match = mw.ustring.match
local gmatch = mw.ustring.gmatch
local sub = mw.ustring.sub
local gsub = mw.ustring.gsub
local lower = mw.ustring.lower
local split = mw.text.split
local reverse = m_string_utilities.reverse
local upper = mw.ustring.upper
table.append = require( "Module:table" ).append
local output_noun_slots = {
nom_sg = "nom|s",
gen_sg = "gen|s",
datloc_sg = "dat|-|loc|s",
acc_sg = "acc|s",
abl_sg = "abl|s",
ins_sg = "ins|s",
com_sg = "com|s",
priv_sg = "priv|s",
dirc_sg = "dirc|s",
nom_pl = "nom|p",
gen_pl = "gen|p",
datloc_pl = "dat|-|loc|p",
acc_pl = "acc|p",
abl_pl = "abl|p",
ins_pl = "ins|p",
com_pl = "com|p",
priv_pl = "priv|p",
dirc_pl = "dirc|p",
nom_sg_refl = "nom|s|refl",
gen_sg_refl = "gen|s|refl",
datloc_sg_refl = "dat|-|loc|s|refl",
acc_sg_refl = "acc|s|refl",
abl_sg_refl = "abl|s|refl",
ins_sg_refl = "ins|s|refl",
com_sg_refl = "com|s|refl",
priv_sg_refl = "priv|s|refl",
dirc_sg_refl = "dirc|s|refl",
nom_pl_refl = "nom|p|refl",
gen_pl_refl = "gen|p|refl",
datloc_pl_refl = "dat|-|loc|p|refl",
acc_pl_refl = "acc|p|refl",
abl_pl_refl = "abl|p|refl",
ins_pl_refl = "ins|p|refl",
com_pl_refl = "com|p|refl",
priv_pl_refl = "priv|p|refl",
dirc_pl_refl = "dirc|p|refl",
}
local output_noun_slots_with_linked = m_table.shallowcopy( output_noun_slots )
output_noun_slots_with_linked = "nom|s"
output_noun_slots_with_linked = "nom|p"
local input_params_to_slots_both = {
= "nom_sg",
= "nom_pl",
= "gen_sg",
= "gen_pl",
= "datloc_sg",
= "datloc_pl",
= "acc_sg",
= "acc_pl",
= "abl_sg",
= "abl_pl",
= "ins_sg",
= "ins_pl",
= "com_sg",
= "com_pl",
= "priv_sg",
= "priv_pl",
= "dirc_sg",
= "dirc_pl",
= "nom_sg_refl",
= "nom_pl_refl",
= "gen_sg_refl",
= "gen_pl_refl",
= "datloc_sg_refl",
= "datloc_pl_refl",
= "acc_sg_refl",
= "acc_pl_refl",
= "abl_sg_refl",
= "abl_pl_refl",
= "ins_sg_refl",
= "ins_pl_refl",
= "com_sg_refl",
= "com_pl_refl",
= "priv_sg_refl",
= "priv_pl_refl",
= "dirc_sg_refl",
= "dirc_pl_refl",
}
local input_params_to_slots_sg = {
= "nom_sg",
= "gen_sg",
= "datloc_sg",
= "acc_sg",
= "abl_sg",
= "ins_sg",
= "com_sg",
= "priv_sg",
= "dirc_sg",
= "nom_sg_refl",
= "gen_sg_refl",
= "datloc_sg_refl",
= "acc_sg_refl",
= "abl_sg_refl",
= "ins_sg_refl",
= "com_sg_refl",
= "priv_sg_refl",
= "dirc_sg_refl",
}
local input_params_to_slots_pl = {
= "nom_pl",
= "gen_pl",
= "datloc_pl",
= "acc_pl",
= "abl_pl",
= "ins_pl",
= "com_pl",
= "priv_pl",
= "dirc_pl",
= "nom_pl_refl",
= "gen_pl_refl",
= "datloc_pl_refl",
= "acc_pl_refl",
= "abl_pl_refl",
= "ins_pl_refl",
= "com_pl_refl",
= "priv_pl_refl",
= "dirc_pl_refl",
}
local cases = {
nom = true,
gen = true,
datloc = true,
acc = true,
abl = true,
ins = true,
com = true,
priv = true,
dirc = true,
}
local accented_cases = {
= "nom",
= "gen",
= "datloc",
= "acc",
= "abl",
= "ins",
= "com",
= "priv",
= "dirc",
}
local function skip_slot( number, slot )
return number == "sg" and find( slot, "_p$" ) or
number == "pl" and find( slot, "_s$" )
end
local function add( data, slot, stem_and_ending, footnotes )
local stem
local ending
if not stem_and_ending then
return
end
if skip_slot( data.number, slot ) then
return
end
if type( stem_and_ending ) == "string" then
stem = stem_and_ending
ending = ""
else
stem = stem_and_ending
ending = stem_and_ending
end
iut.add_forms( data.forms, slot, stem, ending, com.combine_stem_ending )
end
local function process_slot_overrides( data, do_slot )
for slot, overrides in pairs( data.overrides ) do
if skip_slot( data.number, slot ) then
error( "Override specified for invalid slot '" .. slot .. "' due to '" .. data.number .. "' number restriction" )
end
if do_slot( slot ) then
data.forms = nil
local slot_is_plural = find( slot, "_p$" )
for _, override in ipairs( overrides ) do
for _, value in ipairs( override.values ) do
local form = value.form
local combined_notes = iut.combine_footnotes( data.footnotes, value.footnotes )
end
end
end
end
end
local function vowelharmony( infl, data )
return com.vowelharmony( infl, data )
end
local function syllables( infl )
return #com.syllables( infl )
end
local function propernoun( infl, data )
if sub( infl, 1, 1 ) ~= lower( sub( infl, 1, 1 ) ) then
return true
else
return false
end
end
local function voweldeletion( infl, data )
return com.voweldeletion( infl, data )
end
local function attributive( infl, data )
end
local function plural( infl, data )
local vh = vowelharmony( infl, data )
local reduced = voweldeletion( infl, data )
if data.decl == "g" then
return infl .. "г" .. vh.uu .. "д"
elseif data.decl == "n" then
elseif data.decl == "r" then
local matches = {
{ {
match( infl, "ч.н$" ),
match( infl, "ён$" )
},
"д"
},
{ { match( infl, "$" ) },
"н" .. vh.uu .. "д"
},
{ {
match( infl, "$" ),
match( reduced, "$" ), -- C, and also loanwords with a word-final long vowel written as a single vowel
match( infl, "$" ) and data.bor
},
"г" .. vh.uu .. "д"
},
{ { match( infl, "$" ) },
"и" .. vh.u .. "д"
},
{ { match( infl, "$" ) },
vh.u .. "д"
},
{ { match( infl, "?$" ) },
vh.uu .. "д"
}
}
for s,t in ipairs( matches ) do
for _,m in pairs( t ) do
if match( infl, "^хүн$" ) then
return "хүмүүс"
elseif t == "д" then
return sub( infl, 1, len( infl ) - 1 ) .. t
else
return reduced .. t
end
end
end
end
end
local function genitive( infl, data )
local vh = vowelharmony( infl, data )
local reduced = voweldeletion( infl, data )
if data.decl == "g" then
return infl .. "гийн"
elseif data.decl == "n" then
elseif data.decl == "r" then
local matches = {
{ { match( infl, "н$" ) },
vh.ii
},
{ {
match( infl, "$" ),
match( reduced, "и$" )
},
"н"
},
{ {
match( infl, "$" ),
match( reduced, "$" ), -- C, and also loanwords with a word-final long vowel written as a single vowel
match( infl, "$" ) and data.bor
},
"гийн"
},
{ { match( infl, "$" ) },
"ийн"
},
{ {
match( infl, "$" ),
match( infl, "$" ),
match( infl, "$" ) -- not C
},
vh.ii .. "н"
}
}
for s,t in ipairs( matches ) do
for _,m in pairs( t ) do
if m then return { reduced, t } end
end
end
end
end
local function dativelocative( infl, data )
local vh = vowelharmony( infl, data )
local syllables = syllables( infl )
local reduced = voweldeletion( infl, data )
if data.decl == "g" then
return infl .. "d"
elseif data.decl == "n" then
elseif data.decl == "r" then
local vowel = ""
local consonant = ""
local matches = {
{ {
match( infl, "$" ) or match( infl, "п$" ),
( match( infl, "в$" ) or match( infl, "б$" ) ) and ( data.syllables ~= 1 or match( infl, "^" .. consonant .. consonant ) ),
match( infl, vowel .. vowel .. "$" ) or match( infl, consonant .. "р$" ),
( match( infl, "р$" ) or match( infl, vowel .. "с$" ) ) and ( data.syllables ~= 1 or data.proper == true ),
match( infl, vowel .. "ь?с$" ),
match( infl, "ьс$" ),
match( infl, "ис$" ),
},
"т"
},
{ {
match( infl, vowel .. "$" ),
match( infl, "б$" ),
match( infl, "$" ),
match( infl, "ь$" ),
},
"д"
},
{ {
match( infl, "ь?$" ),
match( infl, "ь$" )
},
"ид"
},
{ {
match( infl, ".$" ),
},
vh.a .. "д"
}
}
for s,t in ipairs( matches ) do
for _,m in pairs( t ) do
if m then
if match( infl, "ь$" ) then
return { sub( infl, 1, len( infl ) - 1 ), t }
elseif match( infl, "$" ) then
return { reduced, t }
else
return { infl, t }
end
end
end
end
return infl .. "д"
end
end
local function accusative( infl, data )
local vh = vowelharmony( infl, data )
local reduced = voweldeletion( infl, data )
if data.decl == "g" then
return infl .. "г"
elseif data.decl == "n" then
elseif data.decl == "r" then
local matches = {
{ {
match( infl, "$" ),
match( infl, "$" ),
match( reduced, "$" ), -- C, and also loanwords with a word-final long vowel written as a single vowel
match( reduced, "и$" ),
match( infl, "$" ) and data.bor
},
"г"
},
{ { match( infl, "$" ) },
"ийг"
},
{ {
match( infl, "$" ),
match( infl, "$" ),
match( infl, "$" ) -- not C
},
vh.ii .. "г"
}
}
for s,t in ipairs( matches ) do
for _,m in pairs( t ) do
if m then return { reduced, t } end
end
end
end
end
local function aa( infl, data, decl )
local vh = vowelharmony( infl, data )
local reduced = voweldeletion( infl, data )
if decl == "g" then
return infl .. "г" .. vh.aa
elseif decl == "n" then
elseif decl == "r" then
local matches = {
{ {
match( infl, "$" ),
match( infl, "$" ),
match( reduced, "$" ), -- C, and also loanwords with a word-final long vowel written as a single vowel
match( reduced, "и$" ),
match( infl, "$" ) and data.bor
},
"г" .. vh.aa
},
{ { match( infl, "$" ) },
vh.a
},
{ { match( infl, "$" ) },
"и" .. vh.a
},
{ {
match( infl, "$" ),
match( infl, "$" ) -- not C
},
vh.aa
}
}
for s,t in ipairs( matches ) do
for _,m in pairs( t ) do
if m then return reduced, t end
end
end
end
end
local function ablative( infl, data )
local stem, ending = aa( infl, data, data.decl )
return { stem, ending .. "с" }
end
local function instrumental( infl, data )
if match( data.decl, "" ) then
local stem, ending = aa( infl, data, "r" )
return { stem, ending .. "р" }
elseif match( data.decl, "g" ) then
local stem, ending = aa( infl, data, "g" )
return { stem, ending .. "р" }
end
end
local function reflexive( infl, data )
if match( data.decl, "" ) then
local stem, ending = aa( infl, data, "r" )
return { stem, ending }
elseif match( data.decl, "g" ) then
local stem, ending = aa( infl, data, "g" )
return { stem, ending }
end
end
local function comitative( infl, data )
local vh = vowelharmony( infl, data )
if match( infl, "ь$" ) then
return { sub( infl, 1, len( infl ) - 1 ), "ит" .. vh.ai, }
else
return { infl, "т" .. vh.ai, }
end
end
local function privative( infl, data )
return { infl, "гүй" }
end
local function directional( infl, data )
local vh = vowelharmony( infl, data )
if match( infl, "рь?$" ) then
return { infl, " л" .. vh.uu, }
else
return { infl, " р" .. vh.uu, }
end
end
local function equative( infl, data )
end
local function handle_derived_slots_and_overrides( data )
add( data, "nom_sg", data.lemma )
add( data, "gen_sg", genitive( data.lemma, data ) )
add( data, "datloc_sg", dativelocative( data.lemma, data ) )
add( data, "acc_sg", accusative( data.lemma, data ) )
add( data, "abl_sg", ablative( data.lemma, data ) )
add( data, "ins_sg", instrumental( data.lemma, data ) )
add( data, "com_sg", comitative( data.lemma, data ) )
add( data, "priv_sg", privative( data.lemma, data ) )
add( data, "dirc_sg", directional( data.lemma, data ) )
add( data, "nom_pl", plural( data.lemma, data ) )
add( data, "gen_pl", genitive( data.forms.form, data ) )
add( data, "datloc_pl", dativelocative( data.forms.form, data ) )
add( data, "acc_pl", accusative( data.forms.form, data ) )
add( data, "abl_pl", ablative( data.forms.form, data ) )
add( data, "ins_pl", instrumental( data.forms.form, data ) )
add( data, "com_pl", comitative( data.forms.form, data ) )
add( data, "priv_pl", privative( data.forms.form, data ) )
add( data, "dirc_pl", directional( data.forms.form, data ) )
add( data, "nom_sg_refl", reflexive( data.lemma, data ) )
add( data, "gen_sg_refl", reflexive( data.forms.form, data ) )
add( data, "datloc_sg_refl", reflexive( data.forms.form, data ) )
add( data, "acc_sg_refl", reflexive( data.forms.form, data ) )
add( data, "abl_sg_refl", reflexive( data.forms.form, data ) )
add( data, "ins_sg_refl", reflexive( data.forms.form, data ) )
add( data, "com_sg_refl", reflexive( data.forms.form, data ) )
add( data, "priv_sg_refl", reflexive( data.forms.form, data ) )
add( data, "dirc_sg_refl", reflexive( data.forms.form, data ) )
add( data, "nom_pl_refl", reflexive( data.forms.form, data ) )
add( data, "gen_pl_refl", reflexive( data.forms.form, data ) )
add( data, "datloc_pl_refl", reflexive( data.forms.form, data ) )
add( data, "acc_pl_refl", reflexive( data.forms.form, data ) )
add( data, "abl_pl_refl", reflexive( data.forms.form, data ) )
add( data, "ins_pl_refl", reflexive( data.forms.form, data ) )
add( data, "com_pl_refl", reflexive( data.forms.form, data ) )
add( data, "priv_pl_refl", reflexive( data.forms.form, data ) )
add( data, "dirc_pl_refl", reflexive( data.forms.form, data ) )
-- Compute linked versions of potential lemma slots, for use in {{mn-noun}}.
-- We substitute the original lemma (before removing links) for forms that
-- are the same as the lemma, if the original lemma has links.
for _, slot in ipairs( { "nom_sg", "nom_pl" } ) do
iut.insert_forms( data.forms, slot .. "_linked", iut.map_forms( data.forms, function( form )
if form == data.orig_lemma_no_links and find( data.orig_lemma, "%[%[" ) then
return data.orig_lemma
else
return form
end
end ) )
end
end
--[=[ function export.loanworddiagnostic( text )
local consonant = ""
local vconsonant = ""
local vowel = ""
local cvowel = ""
local ivowel = ""
local sign = ""
local soft = ""
local hard = ""
local prefixes = {
"аб", "авто", "агро", "алко", "анарх", "анти", "архео", "астро", "аудио", "афро", "аэро", "баро", "био", "видео", "внутр", "эко", "гекто", "гео", "геронто", "гимна", "гига", "гидро", "гипер", "дека", "демо", "деци", "диа", "евро", "зепто", "изо", "интер", "интра", "инфра", "йокто", "квази", "кибер", "кило", "кино", "ко", "контра", "лабо", "либер", "макро", "мега", "мета", "метро", "микро", "милли", "мини", "мото", "мульти", "нано", "нео", "об", "олимп", "орга", "пано", "панто", "пара", "поли", "полу", "пост", "пре", "про", "псевдо", "радио", "суб", "супер", "теле", "тетр", "техн", "три", "турбо", "ультра", "фото", "цис", "четвер", "четыр", "экс", "электр"
}
local suffixes = {
"атор", "атори", "еон", "етик", "жер", "изм", "ист", "логи", "мент", "метр", "оми", "пол", "порт", "сер", "тер", "техник", "ятор", "ятори"
}
local loanword
local matches = {
match( text, "" ), -- always used in loanwords
match( text, consonant .. vconsonant .. consonant ), -- voweled consonant in the middle of a cluster
match( text, consonant .. vconsonant .. sign .. consonant ),
match( text, "" .. consonant ), -- б followed by consonant
match( text, consonant .. "" ), -- consonant followed by й
match( text, cvowel .. cvowel .. cvowel ), -- triple common vowel
match( text, "и" ),
match( text, hard .. consonant ),
match( text, hard .. "" ),
match( text, vowel .. sign ),
match( text, "э" .. consonant ),
match( text, consonant .. vconsonant .. "$" ), -- word-final voweled consonant after consonant
match( text, consonant .. sign .. vconsonant .. "$" ),
match( text, "" .. consonant .. "$" ),
match( text, "" .. sign .. consonant .. "$" ),
match( text, "" .. consonant .. "$" ),
match( text, "" .. sign .. consonant .. "$" ),
match( text, "э$" ),
match( text, "^" ), -- starting with й, ь or ъ
match( text, "^" .. consonant .. consonant ) -- starting with consonant cluster
}
for _,v in pairs( matches ) do
if v then
loanword = true
break
end
end
if loanword ~= true then
for _,prefix in pairs( prefixes ) do
if match( text, "^" .. prefix ) then
loanword = true
break
end
end
end
if loanword ~= true then
for _,suffix in pairs( suffixes ) do
if match( text, suffix .. "$" ) then
loanword = true
break
end
end
end
if loanword == true then return true else return false end
end ]=]--
local function parse_indicator_spec( angle_bracket_spec )
local inside = match( angle_bracket_spec, "^<(.*)>$" )
local data = { overrides = {}, forms = {} }
if inside ~= "" then
local segments = iut.parse_balanced_segment_run( inside, "" )
local dot_separated_groups = iut.split_alternating_runs( segments, "%." )
for i, dot_separated_group in ipairs( dot_separated_groups ) do
local part = dot_separated_group
local case_prefix = sub( part, 1, 3 )
if cases or accented_cases then
local slot, override = parse_override( dot_separated_group )
if data.overrides then
table.insert( data.overrides, override )
else
data.overrides = { override }
end
elseif part == "" then
if #dot_separated_group == 1 then
error( "Blank indicator: '" .. inside .. "'" )
end
data.footnotes = fetch_footnotes( dot_separated_group )
elseif part == "r" or part == "n" or part == "g" then
if data.decl then
error( "Can't specify declension twice: '" .. inside .. "'" )
end
data.decl = part
elseif part == "sg" or part == "pl" then
if data.number then
error( "Can't specify number twice: '" .. inside .. "'" )
end
data.number = part
elseif part == "а" or part == "о" or part == "ө" or part == "э" then
if data.vh_override then
error( "Can't specify vowel harmony twice: '" .. inside .. "'" )
end
data.vh_override = part
elseif part == "bor" or part == "Russian" then
if data.bor then
error( "Can't specify borrowing twice: '" .. inside .. "'" )
end
data.bor = part
elseif part == "proper" then
if data.proper then
error( "Can't specify proper noun twice: '" .. inside .. "'" )
end
data.proper = true
else
error( "Unrecognized indicator '" .. part .. "': '" .. inside .. "'" )
end
end
else
error( "Blank indicator: '" .. inside .. "'" )
end
return data
end
local function set_defaults_and_check_bad_indicators( data )
-- Set default values.
if not data.adj then
if data.proper then
data.number = data.number or "sg"
else
data.number = data.number or "both"
end
end
end
local function check_indicators_match_lemma( data )
-- Check for indicators that don't make sense given the context.
if data.decl == "n" and match( data.lemma, "н$" ) then
error( "Hidden-n declension cannot be specified with a lemma ending in н" )
end
if data.decl == "g" and not match( data.lemma, "н$" ) then
error( "Hidden-g declension can only be specified with a lemma ending in н" )
end
end
local function detect_indicator_spec( data )
if propernoun( data.lemma, data ) then data.proper = true end
set_defaults_and_check_bad_indicators( data )
check_indicators_match_lemma( data )
end
local function detect_all_indicator_specs( alternant_multiword_spec )
local is_multiword = #alternant_multiword_spec.alternant_or_word_specs > 1
iut.map_word_specs( alternant_multiword_spec, function( data )
detect_indicator_spec( data )
data.multiword = is_multiword
end )
end
local propagate_multiword_properties
local function propagate_alternant_properties( alternant_spec, property, mixed_value, nouns_only )
local seen_property
for _, multiword_spec in ipairs( alternant_spec.alternants ) do
propagate_multiword_properties( multiword_spec, property, mixed_value, nouns_only )
if seen_property == nil then
seen_property = multiword_spec
elseif multiword_spec and seen_property ~= multiword_spec then
seen_property = mixed_value
end
end
alternant_spec = seen_property
end
propagate_multiword_properties = function( multiword_spec, property, mixed_value, nouns_only )
local seen_property = nil
local last_seen_nounal_pos = 0
local word_specs = multiword_spec.alternant_or_word_specs or multiword_spec.word_specs
for i = 1, #word_specs do
local is_nounal
if word_specs.alternants then
propagate_alternant_properties( word_specs, property, mixed_value )
is_nounal = not not word_specs
elseif nouns_only then
is_nounal = not word_specs.adj
else
is_nounal = not not word_specs
end
if is_nounal then
if not word_specs then
error( "Internal error: noun-type word spec without " .. property .. " set" )
end
for j = last_seen_nounal_pos + 1, i - 1 do
word_specs = word_specs or word_specs
end
last_seen_nounal_pos = i
if seen_property == nil then
seen_property = word_specs
elseif seen_property ~= word_specs then
seen_property = mixed_value
end
end
end
if last_seen_nounal_pos > 0 then
for i = last_seen_nounal_pos + 1, #word_specs do
word_specs = word_specs or word_specs
end
end
multiword_spec = seen_property
end
local function propagate_properties_downward( alternant_multiword_spec, property, default_propval )
local propval1 = alternant_multiword_spec or default_propval
for _, alternant_or_word_spec in ipairs( alternant_multiword_spec.alternant_or_word_specs ) do
local propval2 = alternant_or_word_spec or propval1
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs( alternant_or_word_spec.alternants ) do
local propval3 = multiword_spec or propval2
for _, word_spec in ipairs( multiword_spec.word_specs ) do
local propval4 = word_spec or propval3
if propval4 == "mixed" then
error( "Attempt to assign mixed " .. property .. " to word" )
end
word_spec = propval4
end
end
else
if propval2 == "mixed" then
error( "Attempt to assign mixed " .. property .. " to word" )
end
alternant_or_word_spec = propval2
end
end
end
local function propagate_properties( alternant_multiword_spec, property, default_propval, mixed_value )
propagate_multiword_properties( alternant_multiword_spec, property, mixed_value, "nouns only" )
propagate_multiword_properties( alternant_multiword_spec, property, mixed_value, false )
propagate_properties_downward( alternant_multiword_spec, property, default_propval )
end
local function normalize_all_lemmas( alternant_multiword_spec )
iut.map_word_specs( alternant_multiword_spec, function( data )
data.orig_lemma = data.lemma
data.orig_lemma_no_links = m_links.remove_links( data.lemma )
data.lemma = data.orig_lemma_no_links
end )
end
local function compute_categories_and_annotation( alternant_multiword_spec )
local cats = {}
local function insert( cattype )
m_table.insertIfNot( cats, "Mongolian " .. cattype )
end
if alternant_multiword_spec.pos == "noun" then
if alternant_multiword_spec.number == "sg" then
insert( "uncountable nouns" )
elseif alternant_multiword_spec.number == "pl" then
insert( "pluralia tantum" )
end
end
local annotation
if alternant_multiword_spec.manual then
alternant_multiword_spec.annotation =
alternant_multiword_spec.number == "sg" and "sg-only" or
alternant_multiword_spec.number == "pl" and "pl-only" or
""
else
local annparts = {}
local bor = nil
local decl = {}
local irregs = {}
local stems = {}
local reducible = nil
local vh = {}
local function do_word_spec( data )
m_table.insertIfNot( vh, vowelharmony( data.lemma, data ).a )
insert( vowelharmony( data.lemma, data ).a .. "-harmonic nouns" )
if data.decl == "r" then
m_table.insertIfNot( decl, "reg" )
insert( "regular declension " .. alternant_multiword_spec.pos .. "s" )
elseif data.decl == "n" then
m_table.insertIfNot( decl, "hidden-n" )
insert( "hidden-n declension " .. alternant_multiword_spec.pos .. "s" )
elseif data.decl == "g" then
m_table.insertIfNot( decl, "hidden-g" )
insert( "hidden-g declension " .. alternant_multiword_spec.pos .. "s" )
end
if data.bor then bor = true end
if voweldeletion( data.lemma, data ) ~= data.lemma then reducible = true end
end
local key_entry = alternant_multiword_spec.first_noun or 1
if #alternant_multiword_spec.alternant_or_word_specs >= key_entry then
local alternant_or_word_spec = alternant_multiword_spec.alternant_or_word_specs
if alternant_or_word_spec.alternants then
for _, multiword_spec in ipairs( alternant_or_word_spec.alternants ) do
key_entry = multiword_spec.first_noun or 1
if #multiword_spec.word_specs >= key_entry then
do_word_spec( multiword_spec.word_specs )
end
end
else
do_word_spec( alternant_or_word_spec )
end
end
if alternant_multiword_spec.pos == "proper noun" then
table.insert( annparts, "proper" )
elseif alternant_multiword_spec.number ~= "both" then
table.insert( annparts, alternant_multiword_spec.number == "sg" and "sg-only" or "pl-only" )
end
if #vh > 0 then
table.insert( annparts, table.concat( vh, "/" ) .. "-harmonic" )
end
if #decl > 0 then
table.insert( annparts, table.concat( decl, "/" ) .. " decl" )
end
if bor then
table.insert( annparts, "borr" )
end
if reducible then
table.insert( annparts, "reduc" )
end
if #irregs > 0 then
table.insert( annparts, table.concat( irregs, " // " ) )
end
alternant_multiword_spec.annotation = table.concat( annparts, " " )
if #stems > 1 then
insert( alternant_multiword_spec.pos .. "s with multiple stems" )
end
end
alternant_multiword_spec.categories = cats
end
local function combine_stem_ending( stem, ending )
return stem .. ending
end
local function show_forms( alternant_multiword_spec )
local lemmas = {}
local props = {
lemmas = lemmas,
slot_table = output_noun_slots_with_linked,
lang = lang,
canonicalize = form,
include_translit = true,
footnotes = alternant_multiword_spec.footnotes,
allow_footnote_symbols = not not alternant_multiword_spec.footnotes,
}
iut.show_forms( alternant_multiword_spec.forms, props )
end
local function make_table( alternant_multiword_spec )
local forms = alternant_multiword_spec.forms
local function header( min_width )
min_width = min_width or "70"
return gsub( [===[
<div>
<div class="NavFrame" style="display:inline-block; min-width:MINWIDTHem">
<div class="NavHead" style="background:#eff7ff;">{title}{annotation} </div>
<div class="NavContent">
{\op}| style="background:#F9F9F9; text-align:center; min-width:MINWIDTHem; width:100%;" class="inflection-table"
|-
]===], "MINWIDTH", min_width )
end
local function reflexive( min_width )
min_width = min_width or "70"
return gsub( [===[|-
|{\cl}
<div class="NavFrame" min-width:MINWIDTHem">
<div class="NavHead" style="background:#eff7ff;">Reflexive forms </div>
<div class="NavContent">
{\op}| style="background:#F9F9F9; text-align:center; min-width:MINWIDTHem; width:100%;" class="inflection-table"
|-
]===], "MINWIDTH", min_width )
end
local function template_footer()
return [===[|-
|{\cl}{notes_clause}</div></div></div></div>]===]
end
local table_spec_both = header( "45" ) .. [===[
! style="width:10em;background:#d9ebff" |
! style="background:#d9ebff;width:20em;" | singular / indefinite
! style="background:#d9ebff;width:20em;" | definite plural
|-
! style="background:#eff7ff" | nominative
| {nom_sg}
| {nom_pl}
|-
! style="background:#eff7ff" | genitive
| {gen_sg}
| {gen_pl}
|-
! style="background:#eff7ff" | dative-locative
| {datloc_sg}
| {datloc_pl}
|-
! style="background:#eff7ff" | accusative
| {acc_sg}
| {acc_pl}
|-
! style="background:#eff7ff" | ablative
| {abl_sg}
| {abl_pl}
|-
! style="background:#eff7ff" | instrumental
| {ins_sg}
| {ins_pl}
|-
! style="background:#eff7ff" | comitative
| {com_sg}
| {com_pl}
|-
! style="background:#eff7ff" | privative
| {priv_sg}
| {priv_pl}
|-
! style="background:#eff7ff" | directional
| {dirc_sg}
| {dirc_pl}
]===] .. reflexive( "45" ) .. [===[
! style="width:10em;background:#d9ebff" |
! style="background:#d9ebff;width:20em;" | singular / indefinite
! style="background:#d9ebff;width:20em;" | definite plural
|-
! style="background:#eff7ff" | nominative
| {nom_sg_refl}
| {nom_pl_refl}
|-
! style="background:#eff7ff" | genitive
| {gen_sg_refl}
| {gen_pl_refl}
|-
! style="background:#eff7ff" | dative-locative
| {datloc_sg_refl}
| {datloc_pl_refl}
|-
! style="background:#eff7ff" | accusative
| {acc_sg_refl}
| {acc_pl_refl}
|-
! style="background:#eff7ff" | ablative
| {abl_sg_refl}
| {abl_pl_refl}
|-
! style="background:#eff7ff" | instrumental
| {ins_sg_refl}
| {ins_pl_refl}
|-
! style="background:#eff7ff" | comitative
| {com_sg_refl}
| {com_pl_refl}
|-
! style="background:#eff7ff" | privative
| {priv_sg_refl}
| {priv_pl_refl}
|-
! style="background:#eff7ff" | directional
| {dirc_sg_refl}
| {dirc_pl_refl}
]===] .. template_footer()
local table_spec_sg = header( "30" ) .. [===[
! style="width:10em;background:#d9ebff" |
! style="background:#d9ebff" | singular / indefinite
|-
! style="background:#eff7ff" | nominative
| {nom_sg}
|-
! style="background:#eff7ff" | genitive
| {gen_sg}
|-
! style="background:#eff7ff" | dative-locative
| {datloc_sg}
|-
! style="background:#eff7ff" | accusative
| {acc_sg}
|-
! style="background:#eff7ff" | ablative
| {abl_sg}
|-
! style="background:#eff7ff" | instrumental
| {ins_sg}
|-
! style="background:#eff7ff" | comitative
| {com_sg}
|-
! style="background:#eff7ff" | privative
| {priv_sg}
|-
! style="background:#eff7ff" | directional
| {dirc_sg}
]===] .. reflexive( "30" ) .. [===[
! style="width:10em;background:#d9ebff" |
! style="background:#d9ebff" | singular / indefinite
|-
! style="background:#eff7ff" | nominative
| {nom_sg_refl}
|-
! style="background:#eff7ff" | genitive
| {gen_sg_refl}
|-
! style="background:#eff7ff" | dative-locative
| {datloc_sg_refl}
|-
! style="background:#eff7ff" | accusative
| {acc_sg_refl}
|-
! style="background:#eff7ff" | ablative
| {abl_sg_refl}
|-
! style="background:#eff7ff" | instrumental
| {ins_sg_refl}
|-
! style="background:#eff7ff" | comitative
| {com_sg_refl}
|-
! style="background:#eff7ff" | privative
| {priv_sg_refl}
|-
! style="background:#eff7ff" | directional
| {dirc_sg_refl}
]===] .. template_footer()
local table_spec_pl = header( "30" ) .. [===[
! style="width:10em;background:#d9ebff" |
! style="background:#d9ebff" | definite plural
|-
! style="background:#eff7ff" | nominative
| {nom_pl}
|-
! style="background:#eff7ff" | genitive
| {gen_pl}
|-
! style="background:#eff7ff" | dative-locative
| {datloc_pl}
|-
! style="background:#eff7ff" | accusative
| {acc_pl}
|-
! style="background:#eff7ff" | ablative
| {abl_pl}
|-
! style="background:#eff7ff" | instrumental
| {ins_pl}
|-
! style="background:#eff7ff" | comitative
| {com_pl}
|-
! style="background:#eff7ff" | privative
| {priv_pl}
|-
! style="background:#eff7ff" | directional
| {dirc_pl}
]===] .. reflexive( "30" ) .. [===[
! style="width:10em;background:#d9ebff" |
! style="background:#d9ebff" | definite plural
|-
! style="background:#eff7ff" | nominative
| {nom_pl_refl}
|-
! style="background:#eff7ff" | genitive
| {gen_pl_refl}
|-
! style="background:#eff7ff" | dative-locative
| {datloc_pl_refl}
|-
! style="background:#eff7ff" | accusative
| {acc_pl_refl}
|-
! style="background:#eff7ff" | ablative
| {abl_pl_refl}
|-
! style="background:#eff7ff" | instrumental
| {ins_pl_refl}
|-
! style="background:#eff7ff" | comitative
| {com_pl_refl}
|-
! style="background:#eff7ff" | privative
| {priv_pl_refl}
|-
! style="background:#eff7ff" | directional
| {dirc_pl_refl}
]===] .. template_footer()
local notes_template = [===[
<div style="width:100%;text-align:left;background:#d9ebff">
<div style="display:inline-block;text-align:left;padding-left:1em;padding-right:1em">
{footnote}
</div></div>
]===]
if alternant_multiword_spec.title then
forms.title = alternant_multiword_spec.title
else
forms.title = "Declension of <i lang=\"mn\" class=\"Cyrl\">" .. forms.lemma .. "</i>"
end
local annotation = alternant_multiword_spec.annotation or ""
if annotation == "" then
forms.annotation = ""
else
forms.annotation = " (<span style=\"font-weight:normal;\">" .. annotation .. "</span>)"
end
local table_spec =
alternant_multiword_spec.number == "sg" and table_spec_sg or
alternant_multiword_spec.number == "pl" and table_spec_pl or
table_spec_both
forms.notes_clause = forms.footnote ~= "" and
m_string_utilities.format( notes_template, forms ) or ""
return m_string_utilities.format( table_spec, forms )
end
function create_reflexives( infl, data )
data.syllables = #com.syllables( data.text )
vowelharmony( infl, data )
data.vh = data.vh.vh]
data.reduced = voweldeletion( infl, data )
data.text_nostress = lang:makeEntryName( data.text )
data.reduced_nostress = lang:makeEntryName( data.reduced )
return reflexive( infl, data )
end
local function create_caseforms( infl, data )
data.syllables = #com.syllables( data.text )
vowelharmony( infl, data )
data.vh = data.vh.vh]
data.reduced = voweldeletion( infl, data )
data.text_nostress = lang:makeEntryName( data.text )
data.reduced_nostress = lang:makeEntryName( data.reduced )
iut.add_forms( data.cases, "nom_" .. infl, data.text, "", combine_stem_ending, lang )
genitive( infl, data )
dativelocative( infl, data )
accusative( infl, data )
ablative( infl, data )
instrumental( infl, data )
comitative( infl, data )
privative( infl, data )
directional( infl, data )
return data
end
function export.do_generate_forms( parent_args, pos, from_headword, def )
local params = {
= { required = true, default = "хаан<r>" },
footnote = { list = true },
title = {},
pos = { default = "noun" }
}
local args = m_para.process( parent_args, params )
if not match( args, "<.*>" ) then error( "Please specify declension" ) end
local parse_props = {
parse_indicator_spec = parse_indicator_spec
}
local alternant_multiword_spec = iut.parse_inflected_text( args, parse_props )
alternant_multiword_spec.title = args.title
alternant_multiword_spec.pos = args.pos or pos
alternant_multiword_spec.footnotes = args.footnote
alternant_multiword_spec.args = args
normalize_all_lemmas( alternant_multiword_spec )
detect_all_indicator_specs( alternant_multiword_spec )
propagate_properties( alternant_multiword_spec, "proper", "", true )
propagate_properties( alternant_multiword_spec, "number", "both", "both" )
local inflect_props = {
skip_slot = function( slot )
return skip_slot( alternant_multiword_spec.number, slot )
end,
slot_table = output_noun_slots_with_linked,
get_variants = get_variants,
inflect_word_spec = handle_derived_slots_and_overrides,
}
iut.inflect_multiword_or_alternant_multiword_spec( alternant_multiword_spec, inflect_props )
compute_categories_and_annotation( alternant_multiword_spec )
return alternant_multiword_spec
end
function export.show( frame )
local parent_args = frame:getParent().args or frame.args
local alternant_multiword_spec = export.do_generate_forms( parent_args )
show_forms( alternant_multiword_spec )
return make_table( alternant_multiword_spec ) .. require( "Module:utilities" ).format_categories( alternant_multiword_spec.categories, lang )
end
local function lb( total )
return ( ( total + 1 ) / 14 ) * ( tonumber( mw.title.getCurrentTitle().subpageText ) - 1 )
end
local function ub( total )
return ( ( total + 1 ) / 14 ) * tonumber( mw.title.getCurrentTitle().subpageText )
end
function export.testpreprocess( rawtext )
local data = {}
data.text, data.spec = match( rawtext, "^(.*)<(.-)>$" )
data.text_nostress = lang:makeEntryName( data.text )
data.spec = split( data.spec, ".", true )
data.decl = data.spec
data.bor = data.spec or nil
data.syllables = #com.syllables( data.text )
vowelharmony( data )
propernoun( data )
data.vh = data.vh
data.reduced = export.voweldeletion( data )
data.reduced_nostress = lang:makeEntryName( data.reduced )
return data
end
local function testheader( section )
local title = mw.title.getCurrentTitle().subpageText
local function subpages( inflection )
local subpages = {}
for i=1,14 do
table.insert( subpages, "] " )
end
return table.concat( subpages )
end
if section == 1 then
return "<table style=\"float:right;\"><tr><td>]</td><td>" .. subpages( "vowel-harmony" ) .. "<tr><tr><td>]</td><td>" .. subpages( "vowel-deletion" ) .. "<tr><tr><td>]</td><td>" .. subpages( "loanword" ) .. "<tr></table><table>"
elseif section == 2 then
return "<table style=\"float:right;padding-top:1em;\"><tr><td>]</td><td>" .. subpages( "genitive" ) .. "<tr><tr><td>]</td><td>" .. subpages( "dative-locative" ) .. "<tr><tr><td>]</td><td>" .. subpages( "accusative" ) .. "<tr><tr><td>]</td><td>" .. subpages( "ablative" ) .. "<tr><tr><td>]</td><td>" .. subpages( "instrumental" ) .. "<tr></table><table>"
end
end
function export.voweldeletiontest( frame )
local function deletevowel( text ) -- deletes the second last character of the string
return sub( text, 1, len( text ) - 2 ) .. sub( text, len( text ), len( text ) )
end
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong_native = 0
local wrong_loan = 0
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or lb( #lemmas ) ) and i <= ( tonumber( frame.args ) or ub( #lemmas ) ) and match( sub( v.lemma, -1 ), "" ) and v.class ~= 16 then
local reduced = export.voweldeletion( v.lemma )
if v.class <= 15 or v.class == 18 or ( v.class >= 23 and v.class <= 25 ) or ( v.class >= 28 and v.class <= 30 ) or v.class == 32 then
if reduced == v.lemma then
correct = correct + 1
colour = "#BBFFBB"
elseif v.bor then
wrong_loan = wrong_loan + 1
colour = "#FFFFBB"
else
wrong_native = wrong_native + 1
colour = "#FFBBBB"
end
else
if reduced == deletevowel( v.lemma ) then
correct = correct + 1
colour = "#BBFFBB"
else
wrong_native = wrong_native + 1
colour = "#FFBBBB"
end
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. v.lemma .. "</td><td>" .. reduced .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" elseif colour == "#FFFFBB" then term = term .. "Incorrect loan</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<table><tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect (native):</td><td>" .. wrong_native .. "</td></tr><tr ><td>Incorrect (loanwords):</td><td>" .. wrong_loan .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong_native ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Reduced</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
function export.vowelharmonytest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong_native = 0
local wrong_loan = 0
local predicted_vh
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or lb( #lemmas ) ) and i <= ( tonumber( frame.args ) or ub( #lemmas ) ) and not v.bor then
local vharm = vowelharmony( v.lemma )
vharm = vharm
if vharm.position == "back" and vharm.quality == "unrounded" then
predicted_vh = 1
elseif vharm.position == "back" and vharm.quality == "rounded" then
predicted_vh = 2
elseif vharm.position == "front" and vharm.quality == "rounded" then
predicted_vh = 3
else
predicted_vh = 4
end
if predicted_vh == v.vh then
correct = correct + 1
colour = "#BBFFBB"
elseif v.bor then
wrong_loan = wrong_loan + 1
colour = "#FFFFBB"
else
wrong_native = wrong_native + 1
colour = "#FFBBBB"
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. v.lemma .. "</td><td>" .. v.vh .. "</td><td>" .. predicted_vh .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" elseif colour == "#FFFFBB" then term = term .. "Incorrect loan</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<table><tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect (native):</td><td>" .. wrong_native .. "</td></tr><tr ><td>Incorrect (loanwords):</td><td>" .. wrong_loan .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong_native ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Vowel harmony</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted VH</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
function export.loanwordtest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong = 0
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or lb( #lemmas ) ) and i <= ( tonumber( frame.args ) or ub( #lemmas ) ) then
if v.bor then
if ( export.loanworddiagnostic( v.lemma ) == true ) then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
else
if ( export.loanworddiagnostic( v.lemma ) == false ) then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. v.lemma .. "</td><td>"
if v.bor then
if colour == "#BBFFBB" then
term = term .. "Loanword</td><td>Loanword</td><td>Correct</td></tr>"
else
term = term .. "Loanword</td><td>Native word</td><td>Incorrect</td></tr>"
end
else
if colour == "#BBFFBB" then
term = term .. "Native word</td><td>Native word</td><td>Correct</td></tr>"
else
term = term .. "Native word</td><td>Loanword</td><td>Incorrect</td></tr>"
end
end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<table><tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect:</td><td>" .. wrong .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .. "<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Type</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
function export.genitivetest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong = 0
local data = {}
local gen
local stem
local known
local iin = { 1, 3, 5, 7, 14, 17, 18, 19, 21 }
local iiin = { 4, 6, 8, 22, 23, 24, 31, 32 }
local ii = { 2, 20 }
local n = { 15 }
local giiin = { 16, 30 }
local nii = { 9, 10, 11, 12, 12.1, 25, 26, 27 }
local inii = { 13, 28, 29 }
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or 0 ) and i <= ( tonumber( frame.args ) or 15000 ) and ( v.class <= 8 or ( v.class >= 14 and v.class <= 24 ) or v.class >= 30 ) then
data = export.testpreprocess( v.lemma )
gen = genitive( data )
stem = data.text
if v.class == 17 or ( v.class >= 19 and v.class <= 22 ) or v.class == 26 or v.class == 27 or v.class == 31 then
stem = sub( stem, 1, len( stem ) - 2 ) .. sub( stem, -1 )
elseif v.class == 8 or v.class == 18 or v.class == 23 or v.class == 24 or v.class == 28 or v.class == 29 then
stem = sub( stem, 1, len( stem ) - 1 )
end
for _,class in pairs( iin ) do
if v.class == class and v.vh <= 2 then
known = stem .. "ын"
elseif v.class == class and v.vh >= 3 then
known = stem .. "ийн"
end
end
for _,class in pairs( iiin ) do
if v.class == class then known = stem .. "ийн" end
end
for _,class in pairs( ii ) do
if v.class == class and v.vh <= 2 then
known = stem .. "ы"
elseif v.class == class and v.vh >= 3 then
known = stem .. "ий"
end
end
for _,class in pairs( n ) do
if v.class == class then known = stem .. "н" end
end
for _,class in pairs( giiin ) do
if v.class == class then known = stem .. "гийн" end
end
for _,class in pairs( nii ) do
if v.class == class and v.vh <= 2 then
known = stem .. "ны"
elseif v.class == class and v.vh >= 3 then
known = stem .. "ний"
end
end
for _,class in pairs( inii ) do
if v.class == class and v.vh <= 2 then
known = stem .. "ины"
elseif v.class == class and v.vh >= 3 then
known = stem .. "иний"
end
end
if gen == known then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. data.text .. "</td><td>" .. known .. "</td><td>" .. gen .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<table><tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect:</td><td>" .. wrong .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Known</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table></div>"
end
function export.dativelocativetest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong = 0
local data = {}
local datloc
local stem
local d = { 1, 2, 7, 8, 15, 16, 17, 18, 20, 23, 30 }
local ad = { 3, 19 }
local id = { 4, 24, 31, 32 }
local t = { 5, 6, 21, 22 }
local nd = { 12, 12.1, 13, 25 }
local _and = { 9, 10, 14, 26 }
local ind = { 11, 27, 28, 29 }
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or 0 ) and i <= ( tonumber( frame.args ) or 15000 ) and ( v.class <= 8 or ( v.class >= 14 and v.class <= 24 ) or v.class >= 30 ) then
data = export.testpreprocess( v.lemma )
datloc = dativelocative( data )
stem = data.text
for j,vh in pairs( { "а", "о", "ө", "э" } ) do
if j == v.vh then vowel = vh end
end
if v.class == 19 or v.class == 26 or v.class == 27 or v.class == 31 then
stem = sub( stem, 1, len( stem ) - 2 ) .. sub( stem, -1 )
elseif v.class == 24 or v.class == 28 or v.class == 29 then
stem = sub( stem, 1, len( stem ) - 1 )
end
for _,class in pairs( d ) do
if v.class == class then known = stem .. "д" end
end
for _,class in pairs( ad ) do
if v.class == class then known = stem .. vowel .. "д" end
end
for _,class in pairs( id ) do
if v.class == class then known = stem .. "ид" end
end
for _,class in pairs( t ) do
if v.class == class then known = stem .. "т" end
end
for _,class in pairs( nd ) do
if v.class == class then known = stem .. "нд" end
end
for _,class in pairs( _and ) do
if v.class == class then known = stem .. vowel .. "нд" end
end
for _,class in pairs( ind ) do
if v.class == class then known = stem .. "инд" end
end
if datloc == known then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. data.text .. "</td><td>" .. known .. "</td><td>" .. datloc .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<table><tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect:</td><td>" .. wrong .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Known</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
function export.accusativetest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong = 0
local data = {}
local acc
local stem
local known
local iig = { 1, 2, 3, 5, 7, 9, 12.1, 14, 17, 18, 19, 20, 21, 25, 26 }
local iiig = { 4, 6, 8, 10, 11, 13, 22, 23, 24, 27, 28, 29, 31, 32 }
local g = { 12, 15, 16, 30 }
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or 0 ) and i <= ( tonumber( frame.args ) or 15000 ) and ( v.class <= 8 or ( v.class >= 14 and v.class <= 24 ) or v.class >= 30 ) then
data = export.testpreprocess( v.lemma )
acc = accusative( data )
stem = data.text
if v.class == 17 or ( v.class >= 19 and v.class <= 22 ) or v.class == 26 or v.class == 27 or v.class == 31 then
stem = sub( stem, 1, len( stem ) - 2 ) .. sub( stem, -1 )
elseif v.class == 8 or v.class == 18 or v.class == 23 or v.class == 24 or v.class == 28 or v.class == 29 then
stem = sub( stem, 1, len( stem ) - 1 )
end
for _,class in pairs( iig ) do
if v.class == class and v.vh <= 2 then
known = stem .. "ыг"
elseif v.class == class and v.vh >= 3 then
known = stem .. "ийг"
end
end
for _,class in pairs( iiig ) do
if v.class == class then known = stem .. "ийг" end
end
for _,class in pairs( g ) do
if v.class == class then known = stem .. "г" end
end
if acc == known then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. data.text .. "</td><td>" .. known .. "</td><td>" .. acc .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect:</td><td>" .. wrong .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Known</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
function export.ablativetest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong = 0
local data = {}
local abl
local stem
local vowel
local known
local aas = { 1, 2, 3, 4, 5, 6, 14, 17, 18, 19, 20, 21, 22, 31, 32 }
local as = { 7 }
local ias = { 8, 23, 24 }
local gaas = { 15, 16, 30 }
local naas = { 9, 10, 11, 12, 12.1, 13, 25, 26, 27 }
local inaas = { 28, 29 }
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or 0 ) and i <= ( tonumber( frame.args ) or 15000 ) and ( v.class <= 8 or ( v.class >= 14 and v.class <= 24 ) or v.class >= 30 ) then
data = export.testpreprocess( v.lemma )
abl = ablative( data )
stem = data.text
for j,vh in pairs( { "а", "о", "ө", "э" } ) do
if j == v.vh then vowel = vh end
end
if v.class == 17 or ( v.class >= 19 and v.class <= 22 ) or v.class == 26 or v.class == 27 or v.class == 31 then
stem = sub( stem, 1, len( stem ) - 2 ) .. sub( stem, -1 )
elseif v.class == 8 or v.class == 18 or v.class == 23 or v.class == 24 then
stem = sub( stem, 1, len( stem ) - 1 )
end
for _,class in pairs( aas ) do
if v.class == class then
known = stem .. vowel .. vowel .. "с"
end
end
for _,class in pairs( as ) do
if v.class == class then
known = stem .. vowel .. "с"
end
end
for _,class in pairs( ias ) do
if v.class == class then
known = stem .. "и" .. vowel .. "с"
end
end
for _,class in pairs( gaas ) do
if v.class == class then
known = stem .. "г" .. vowel .. vowel .. "с"
end
end
for _,class in pairs( naas ) do
if v.class == class then
known = stem .. "н" .. vowel .. vowel .. "с"
end
end
for _,class in pairs( inaas ) do
if v.class == class then
known = stem .. "ин" .. vowel .. vowel .. "с"
end
end
if abl == known then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. data.text .. "</td><td>" .. known .. "</td><td>" .. abl .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect:</td><td>" .. wrong .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Known</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
function export.instrumentaltest( frame )
local lemmas = require( "Module:User:Theknightwho/mn-lemmas" ).group1
local terms = {}
local correct = 0
local wrong = 0
local data = {}
local ins
local stem
local vowel
local known
local aar = { 1, 2, 3, 4, 5, 6, 9, 10, 11, 14, 17, 18, 19, 20, 21, 22, 25, 26, 27, 31, 32 }
local ar = { 7, 12.1 }
local iar = { 8, 13, 23, 24, 28, 29 }
local gaar = { 12, 15, 16, 30 }
for i,v in pairs( lemmas ) do
if i >= ( tonumber( frame.args ) or 0 ) and i <= ( tonumber( frame.args ) or 15000 ) then
data = export.testpreprocess( v.lemma )
ins = instrumental( data )
stem = data.text
for j,vh in pairs( { "а", "о", "ө", "э" } ) do
if j == v.vh then vowel = vh end
end
if v.class == 17 or ( v.class >= 19 and v.class <= 22 ) or v.class == 26 or v.class == 27 or v.class == 31 then
stem = sub( stem, 1, len( stem ) - 2 ) .. sub( stem, -1 )
elseif v.class == 8 or v.class == 13 or v.class == 18 or ( v.class >= 23 and v.class <= 25 ) or v.class == 28 or v.class == 29 then
stem = sub( stem, 1, len( stem ) - 1 )
end
for _,class in pairs( aar ) do
if v.class == class then
known = stem .. vowel .. vowel .. "р"
end
end
for _,class in pairs( ar ) do
if v.class == class then
known = stem .. vowel .. "р"
end
end
for _,class in pairs( iar ) do
if v.class == class then
known = stem .. "и" .. vowel .. "р"
end
end
for _,class in pairs( gaar ) do
if v.class == class then
known = stem .. "г" .. vowel .. vowel .. "р"
end
end
if ins == known then
correct = correct + 1
colour = "#BBFFBB"
else
wrong = wrong + 1
colour = "#FFBBBB"
end
local term = "<tr " .. "style=\"background:" .. colour .. ";\"" .. "><td>" .. v.class .. "</td><td>" .. data.text .. "</td><td>" .. known .. "</td><td>" .. ins .. "</td><td>"
if colour == "#BBFFBB" then term = term .. "Correct</td></tr>" else term = term .. "Incorrect</td></tr>" end
table.insert( terms, term )
end
end
return testheader( 1 ) .. "<tr><td>Correct:</td><td>" .. correct .. "</td></tr><tr><td>Incorrect:</td><td>" .. wrong .. "</td></tr><tr><td>Accuracy:</td><td>" .. ( correct / ( correct + wrong ) ) * 100 .. "%</td></tr></table>" .. testheader( 2 ) .."<table class=\"wikitable sortable jquery-tablesorter\"><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Class</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Lemma</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Known</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Predicted</th><th class=\"headerSort\" tabindex=\"0\" role=\"columnheader button\" title=\"Sort ascending\">Status</th>" .. table.concat( terms ) .. "</table>"
end
return export