mirror of https://github.com/goraph/17rooms
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
442 lines
8.4 KiB
442 lines
8.4 KiB
local type = type |
|
local kbdru = { |
|
["q"] = "й", |
|
["w"] = "ц", |
|
["e"] = "у", |
|
["r"] = "к", |
|
["t"] = "е", |
|
["y"] = "н", |
|
["u"] = "г", |
|
["i"] = "ш", |
|
["o"] = "щ", |
|
["p"] = "з", |
|
["["] = "х", |
|
["]"] = "ъ", |
|
["a"] = "ф", |
|
["s"] = "ы", |
|
["d"] = "в", |
|
["f"] = "а", |
|
["g"] = "п", |
|
["h"] = "р", |
|
["j"] = "о", |
|
["k"] = "л", |
|
["l"] = "д", |
|
[";"] = "ж", |
|
["'"] = "э", |
|
["z"] = "я", |
|
["x"] = "ч", |
|
["c"] = "с", |
|
["v"] = "м", |
|
["b"] = "и", |
|
["n"] = "т", |
|
["m"] = "ь", |
|
[","] = "б", |
|
["."] = "ю", |
|
["`"] = "ё", |
|
["/"] = ".", |
|
shifted = { |
|
["q"] = "Й", |
|
["w"] = "Ц", |
|
["e"] = "У", |
|
["r"] = "К", |
|
["t"] = "Е", |
|
["y"] = "Н", |
|
["u"] = "Г", |
|
["i"] = "Ш", |
|
["o"] = "Щ", |
|
["p"] = "З", |
|
["["] = "Х", |
|
["]"] = "Ъ", |
|
["a"] = "Ф", |
|
["s"] = "Ы", |
|
["d"] = "В", |
|
["f"] = "А", |
|
["g"] = "П", |
|
["h"] = "Р", |
|
["j"] = "О", |
|
["k"] = "Л", |
|
["l"] = "Д", |
|
[";"] = "Ж", |
|
["'"] = "Э", |
|
["z"] = "Я", |
|
["x"] = "Ч", |
|
["c"] = "С", |
|
["v"] = "М", |
|
["b"] = "И", |
|
["n"] = "Т", |
|
["m"] = "Ь", |
|
[","] = "Б", |
|
["."] = "Ю", |
|
["`"] = "Ё", |
|
["1"] = "!", |
|
["2"] = "@", |
|
["3"] = "#", |
|
["4"] = ";", |
|
["5"] = "%", |
|
["6"] = ":", |
|
["7"] = "?", |
|
["8"] = "*", |
|
["9"] = "(", |
|
["0"] = ")", |
|
["-"] = "_", |
|
["="] = "+", |
|
["/"] = ",", |
|
} |
|
} |
|
|
|
local toupper = { |
|
["й"] = "Й", |
|
["ц"] = "Ц", |
|
["у"] = "У", |
|
["к"] = "К", |
|
["е"] = "Е", |
|
["н"] = "Н", |
|
["г"] = "Г", |
|
["ш"] = "Ш", |
|
["щ"] = "Щ", |
|
["з"] = "З", |
|
["х"] = "Х", |
|
["ъ"] = "Ъ", |
|
["ф"] = "Ф", |
|
["ы"] = "Ы", |
|
["в"] = "В", |
|
["а"] = "А", |
|
["п"] = "П", |
|
["р"] = "Р", |
|
["о"] = "О", |
|
["л"] = "Л", |
|
["д"] = "Д", |
|
["ж"] = "Ж", |
|
["э"] = "Э", |
|
["я"] = "Я", |
|
["ч"] = "Ч", |
|
["с"] = "С", |
|
["м"] = "М", |
|
["и"] = "И", |
|
["т"] = "Т", |
|
["ь"] = "Ь", |
|
["б"] = "Б", |
|
["ю"] = "Ю", |
|
["ё"] = "Ё", |
|
} |
|
|
|
local function lower(str) |
|
if type(str) ~= 'string' then |
|
return str |
|
end |
|
str = str:lower() |
|
for k, v in pairs(toupper) do |
|
str = str:gsub(v, k) |
|
end |
|
return str |
|
end |
|
|
|
local function upper(str) |
|
if type(str) ~= 'string' then |
|
return str |
|
end |
|
str = str:upper(); |
|
for k, v in pairs(toupper) do |
|
str = str:gsub(k, v) |
|
end |
|
return str |
|
end |
|
|
|
local function is_cap(str) |
|
if type(str) ~= 'string' then |
|
return false |
|
end |
|
local s, e |
|
for _, v in pairs(toupper) do |
|
if not s and str:find("^"..v) then |
|
s = true |
|
end |
|
if not e and str:find(v.."$") then |
|
e = true |
|
end |
|
if not s and str:find("^[A-Z]") then |
|
s = true |
|
end |
|
if not e and str:find("[A-Z]$") then |
|
e = true |
|
end |
|
end |
|
return s, e |
|
end |
|
|
|
local function cap(str) |
|
if type(str) ~= 'string' then |
|
return str |
|
end |
|
if str:find("^[a-z]") then |
|
str = str:gsub("^.", function(v) return v:upper() end) |
|
return str |
|
end |
|
for k, v in pairs(toupper) do |
|
local s = str:gsub("^"..k, v) |
|
if s ~= str then |
|
return s |
|
end |
|
end |
|
return str |
|
end |
|
|
|
local lang |
|
|
|
local function norm(str) |
|
if type(str) ~= 'string' then |
|
return str |
|
end |
|
if not lang.yo then |
|
str = str:gsub("ё", "е"):gsub("Ё", "Е") |
|
end |
|
return str |
|
end |
|
|
|
local vowels = { |
|
["у"] = true, |
|
["е"] = true, |
|
["ы"] = true, |
|
["а"] = true, |
|
["о"] = true, |
|
["и"] = true, |
|
["ю"] = true, |
|
["ё"] = true, |
|
["э"] = true, |
|
["я"] = true, |
|
} |
|
|
|
local function is_vowel(l) |
|
l = lower(l); |
|
return vowels[l] |
|
end |
|
|
|
local gram_tt = { |
|
["ИНФИНИТИВ"] = true; |
|
["КР_ПРИЛ"] = true; |
|
["КР_ПРИЧАСТИЕ"] = true; |
|
["Г"] = true; |
|
} |
|
|
|
local function flex_filter(v) |
|
local an = v.an |
|
if an["им"] then |
|
return true |
|
end |
|
if an["рд"] or an["дт"] or an["тв"] or an["пр"] or an["вн"] then |
|
return false |
|
end |
|
if an["0"] then |
|
return true |
|
end |
|
return gram_tt[an.t] |
|
end |
|
|
|
local function gram_info(a) |
|
local t = { } |
|
if a['мр'] then |
|
t.gen = 'male' |
|
elseif a['жр'] then |
|
t.gen = 'female' |
|
elseif a['ср'] then |
|
t.gen = 'neuter' |
|
else |
|
t.gen = 'any' |
|
end |
|
|
|
if a['мн'] then |
|
t.num = 'singular' |
|
elseif a['ед'] then |
|
t.num = 'plural' |
|
else |
|
t.num = 'any' |
|
end |
|
|
|
if a['буд'] then |
|
t.time = 'future' |
|
elseif a['прш'] then |
|
t.time = 'past' |
|
elseif a['нст'] then |
|
t.time = 'present' |
|
else |
|
t.time = 'any' |
|
end |
|
|
|
if a['1л'] then |
|
t.face = 'first' |
|
elseif a['2л'] then |
|
t.face = 'second' |
|
elseif a['3л'] then |
|
t.face = 'third' |
|
else |
|
t.face = 'any' |
|
end |
|
|
|
return t |
|
end |
|
|
|
local function __gram_compat(g1, g2, time) |
|
if g1.gen ~= g2.gen and g1.gen ~= 'any' and g2.gen ~= 'any' then return false end |
|
if not time then |
|
if g1.num ~= g2.num and g1.num ~= 'any' and g2.num ~= 'any' then return false end |
|
end |
|
if g1.time ~= g2.time and g1.time ~= 'any' and g2.time ~= 'any' then return false end |
|
if g1.face ~= g2.face and g1.face ~= 'any' and g2.face ~= 'any' then return false end |
|
return true |
|
end |
|
|
|
local function gram_eq(a, b) |
|
if not a or not b then return true end |
|
if a == 'ИНФИНИТИВ' or b == 'ИНФИНИТИВ' then |
|
return b == a or b == 'Г' or a == 'Г' |
|
end |
|
if a == 'КР_ПРИЛ' or b == 'КР_ПРИЛ' then |
|
return b == a -- or b == 'П' |
|
end |
|
if a == 'КР_ПРИЧАСТИЕ' or b == 'КР_ПРИЧАСТИЕ' then |
|
return b == a |
|
end |
|
if a == 'ПРИЧАСТИЕ' or b == 'ПРИЧАСТИЕ' then |
|
return b == a |
|
end |
|
if a == 'Г' or b == 'Г' then return a == b end |
|
return true |
|
end |
|
|
|
local function gram_compat(base, aa, bb) |
|
if not gram_eq(base.t, aa.t) then |
|
return false |
|
end |
|
-- local a, b = aa.t, bb.t |
|
local g1, g2 = gram_info(aa), gram_info(bb) |
|
if bb.noun then |
|
if not base['им'] then |
|
return false |
|
end |
|
local g0 = gram_info(base) |
|
if not __gram_compat(g0, g1, true) then return false end |
|
if not __gram_compat(g0, g2, true) then return false end |
|
end |
|
return __gram_compat(g1, g2) |
|
end |
|
|
|
local function gram_norm(an) |
|
local a = {} |
|
local g = {} |
|
for _, v in ipairs(an) do |
|
a[v] = true |
|
table.insert(g, v) |
|
end |
|
if not a['1л'] and not a['2л'] and not a['3л'] then |
|
table.insert(g, '3л') |
|
end |
|
return g |
|
end |
|
|
|
local function gram_score(an, g) |
|
local score = 0 |
|
g = gram_norm(g) |
|
if an["фам"] then score = score - 0.1 end |
|
if an["арх"] then score = score - 0.1 end |
|
if not g["од"] and not g["но"] and an["од"] and not an["но"] then score = score - 0.1 end |
|
for _, vv in ipairs(g or {}) do |
|
if vv:sub(1, 1) == '~' then |
|
vv = vv:sub(2) |
|
if an[vv] then |
|
score = score - 1 |
|
elseif an.t == vv then |
|
score = score - 10 |
|
end |
|
else |
|
if an[vv] then |
|
score = score + 1 |
|
elseif an.t == vv then |
|
score = score + 10 |
|
end |
|
end |
|
end |
|
return score |
|
end |
|
|
|
lang = { yo = false, |
|
kbd = kbdru, |
|
norm = norm, |
|
upper = upper, |
|
lower = lower, |
|
cap = cap, |
|
is_cap = is_cap, |
|
is_vowel = is_vowel, |
|
flex_filter = flex_filter, |
|
gram_compat = gram_compat, |
|
gram_score = gram_score, |
|
gram_t = { |
|
noun = 'С', |
|
nom = 'им', |
|
live = 'од', |
|
nonlive = 'но', |
|
neuter = 'ср', |
|
male = 'мр', |
|
female = 'жр', |
|
plural = 'мн', |
|
proper = 'имя', |
|
surname = 'фам', |
|
first = '1л', |
|
second = '2л', |
|
third = '3л', |
|
}; |
|
dict = { |
|
["ведро/ср,но,С"] = { |
|
"ведро/им", "вёдра/им,мн", |
|
"ведро/вн", "вёдра/вн,мн", |
|
"ведра/рд", "вёдер/рд,мн", |
|
"ведру/дт", "ведрам/дт,мн", |
|
"ведром/тв", "вёдрами/тв,мн", |
|
"ведре/пр", "вёдрах/пр,мн", |
|
}, |
|
["деревья/ср,но,мн,С"] = { |
|
"деревья/им"; |
|
"деревья/вн"; |
|
"деревьев/рд"; |
|
"деревьями/тв"; |
|
"деревьях/пр"; |
|
"деревьям/дт"; |
|
}; |
|
["листья/мр,но,мн,С"] = { |
|
"листья/им"; |
|
"листья/вн"; |
|
"листьев/рд"; |
|
"листьями/тв"; |
|
"листьях/пр"; |
|
"листьям/дт"; |
|
}; |
|
["дерево/ср,но,С"] = { |
|
"дерево/им", "деревья/им,мн"; |
|
"дерево/вн", "деревья/вн,мн"; |
|
"дерева/рд", "деревьев/рд,мн"; |
|
"деревом/тв", "деревьями/тв,мн"; |
|
"дереве/пр", "деревьях/пр,мн"; |
|
"дереву/пр", "деревьям/дт,мн"; |
|
}; |
|
["огонь/мр,но,С"] = { |
|
"огонь/им", "огни/им,мн", |
|
"огонь/вн", "огни/вн,мн", |
|
"огня/рд", "огней/рд,мн", |
|
"огню/дт", "огням/дт,мн", |
|
"огнём/тв", "огнями/тв,мн", |
|
"огне/пр", "огнях/пр,мн", |
|
}; |
|
["цветы/мн,мр,но,С"] = { -- цветки |
|
"цветы/им", |
|
"цветы/вн", |
|
"цветов/рд", |
|
"цветам/дт", |
|
"цветами/тв", |
|
"цветах/пр", |
|
}; |
|
["хлам/пр,2"] = "хламе"; |
|
["клевер/пр"] = "клевере"; |
|
["песок/пр,2"] = "песке"; |
|
}; |
|
} |
|
|
|
return lang
|
|
|