Modul:games
A modult a Modul:games/doc lapon tudod dokumentálni
local export = {}
local fun = require "Module:fun"
local m_table = require "Module:table"
local title = mw.title.getCurrentTitle()
local namespace = title.nsText
local fullpagename = title.fullText
--[[
local langbr = "⟨"
local rangbr = "⟩"
--]]
local function quote(word)
return "“" .. word .. "”"
end
local function link(word, lang)
if word:find("%[%[") then
return word
else
if lang then
return "[[" .. lang:makeEntryName(word) .. "|" .. word .. "]]"
else
return "[[" .. word .. "]]"
end
end
end
local function italicize(word)
if word:find("''") then
return word
else
return "''" .. word .. "''"
end
end
local function tag(word, script)
return '<span class="' .. script .. '">' .. word .. '</span>'
end
local function add_color(color, text, attribute)
return '<span style="color: ' .. color .. ';" ' .. (attribute or '') .. '>' .. text .. '</span>'
end
local is_combining = require "Module:Unicode data".is_combining
local find_best_script = require "Module:scripts".findBestScriptWithoutLang
local translit_module = {
Hang = "ko-translit",
ja = { "ja", "kana_to_romaji" },
}
local non_diacritic_equivalencies = {
["ð"] = "d", ["ø"] = "o", ["þ"] = "???", ["đ"] = "d", ["ħ"] = "h", ["ı"] = "i",
["ŋ"] = "n", ["œ"] = "???", ["ŧ"] = "t", ["ſ"] = "s", ["ß"] = "???",
["ł"] = "l", ["ᵃ"] = "a", ["ᵇ"] = "b", ["ᶜ"] = "c", ["ᵈ"] = "d", ["ᵉ"] = "e",
["ᶠ"] = "f", ["ᵍ"] = "g", ["ʰ"] = "h", ["ⁱ"] = "i", ["ʲ"] = "j", ["ᵏ"] = "k",
["ˡ"] = "l", ["ᵐ"] = "m", ["ⁿ"] = "n", ["ᵒ"] = "o", ["ᵖ"] = "p", ["ʳ"] = "r",
["ˢ"] = "s", ["ᵗ"] = "t", ["ᵘ"] = "u", ["ᵛ"] = "v", ["ʷ"] = "w", ["ˣ"] = "x",
["ʸ"] = "y", ["ᶻ"] = "z", ["ᴬ"] = "a", ["ᴮ"] = "b", ["ᴰ"] = "d", ["ᴱ"] = "e",
["ᴳ"] = "g", ["ᴴ"] = "h", ["ᴵ"] = "i", ["ᴶ"] = "j", ["ᴷ"] = "k", ["ᴸ"] = "l",
["ᴹ"] = "m", ["ᴺ"] = "n", ["ᴼ"] = "o", ["ᴾ"] = "p", ["ᴿ"] = "r", ["ᵀ"] = "t",
["ᵁ"] = "u", ["ⱽ"] = "v", ["ᵂ"] = "w", ["ₐ"] = "a", ["ₑ"] = "e", ["ₕ"] = "h",
["ᵢ"] = "i", ["ⱼ"] = "j", ["ₖ"] = "k", ["ₗ"] = "l", ["ₘ"] = "m", ["ₙ"] = "n",
["ₒ"] = "o", ["ₚ"] = "o", ["ᵣ"] = "r", ["ₛ"] = "s", ["ₜ"] = "t", ["ᵤ"] = "u",
["ᵥ"] = "v", ["ₓ"] = "x", -- ["ŋ"] = "n", ["ɔ"] = "o",
["ʿ"] = "", ["ʾ"] = "", ["ʻ"] = "", ["’"] = "",
-- ...
}
-- Remove all diacritics. Make use of the replacements shown above.
-- Remove spaces and hyphens.
local function regularize(word)
return (mw.ustring.lower(mw.ustring.toNFD(word))
:gsub(
"[\194-\244][\128-\191]+",
function (non_ASCII_character)
if is_combining(mw.ustring.codepoint(non_ASCII_character)) then
return ""
end
return non_diacritic_equivalencies[non_ASCII_character]
end))
:gsub(
"[ %-%']",
"")
end
-- Allowed parameters:
-- -- numbers
-- -- lang, lang1, lang2, ...
-- -- tr, tr1, tr2, ...
-- -- ignore rules (boolean)
local function get_args(args)
local words = {}
local langs, translits, ignore_rules
for arg, value in pairs(args) do
if type(arg) == "number" then
words[arg] = value
elseif type(arg) == "string" then
if arg == "ignore rules" then
ignore_rules = require("Module:yesno")(value)
else
local name, number = arg:match("^(%l+)(%d*)$")
if not (name == "lang" or name == "tr") then
error("The parameter |" .. arg .. "= is not used by this template.")
end
if number == "" then
number = 1
else
number = tonumber(number)
end
if name == "lang" then
langs = langs or {}
langs[number] = langs[number] and error("Two langs with index " .. number .. ".")
or value and (require("Module:languages").getByCode(value)
or error("Invalid language code " .. quote(value) .. "."))
else
translits = translits or {}
translits[number] = translits[number] and error("Two translits with index " .. number .. ".")
or value
end
end
end
end
return words, langs, translits, ignore_rules
end
local function show_words(previous_word, interposing_words, following_word)
return link(previous_word) .. " ("
.. table.concat(
fun.map(
function(word)
return italicize(link(word))
end,
interposing_words),
", ")
.. ") "
.. link(following_word)
end
function export.Christmas_Competition_entry(frame)
local words, langs, translits, ignore_rules = get_args(frame:getParent().args)
if namespace == "" or namespace == "Reconstruction" or namespace == "Appendix" then
error("This template is only supposed to be used in the Christmas Competition!")
end
words.length = #words
if words.length < 3 then
if namespace == "Template" then
words = { "Shèngdànjié", "jiellat", "llatino" }
else
error("This template wants at least three words.")
end
end
local regularized_words = {}
local nonLatin_i = 0
local last_interposing_word = (words.length or #words) - 1
for i, word in ipairs(words) do
-- Check for duplicate interposing words.
if 1 < i and i < last_interposing_word then
for j = i + 1, last_interposing_word do
if word == words[j] then
error("You used the word " .. quote(word) .. " twice, in parameters " .. i .. " and " .. j .. "!")
end
end
end
local tr
if word:find("[\128-\255]") then -- non-ASCII
local script = find_best_script(word)
if script and not script:find "Lat" then -- non-Latin
-- [[Module:ko-translit]] requires word to be in NFC.
nonLatin_i = nonLatin_i + 1
local lang = langs and langs[nonLatin_i]
if translits and translits[nonLatin_i] then
tr = translits[nonLatin_i]
elseif lang then
tr = lang:transliterate(mw.ustring.toNFC(word), require("Module:scripts").getByCode(script))
or translit_module[lang:getCode()]
and require("Module:" .. translit_module[lang:getCode()][1])[translit_module[lang:getCode()][2]](word)
or error("The " .. lang:getCode()
.. " transliteration module was unable to generate a transliteration for "
.. quote(word) .. ".")
elseif translit_module[script] then
local success, result = pcall(require("Module:" .. translit_module[script]).tr, mw.ustring.toNFC(word), script)
tr = success and result or error("[[Module:"
.. translit_module[script]
.. "]] wasn't able to generate a transliteration for "
.. quote(word) .. ".")
else
error("You need to give the language code for the word "
.. quote(word)
.. " in the |lang" .. nonLatin_i .. "= parameter so that the word can be transliterated.")
end
if tr then
if i == 1 or i == words.length then
word = tag(link(word, lang), script) .. " (" .. tr .. ")"
else
word = tag(link(word, lang), script) .. " (" .. italicize(tr) .. ")"
end
-- word = italicize(tr) .. " " .. langbr .. tag(link(word), script) .. rangbr
end
end
end
words[i] = word
regularized_words[i] = regularize(tr or word)
end
-- Complain if there aren't as many non-Latin-script words as lang parameters.
if langs then
if nonLatin_i < #langs then
error(#langs .. " |lang= parameter"
.. (#langs == 1 and "" or "s") .. ", but only "
.. nonLatin_i .. " non-Latin-script word"
.. (nonLatin_i == 1 and "" or "s") .. "!")
end
end
local previous_word = table.remove(words, 1)
local last_three = mw.ustring.sub(previous_word, -3)
local following_word = table.remove(words, #words)
local regularized_previous_word = table.remove(regularized_words, 1)
local regularized_last_three = regularized_previous_word:sub(-3)
local regularized_following_word = table.remove(regularized_words, #regularized_words)
-- Check interposing words.
local messages, message_number, message
for i, word in ipairs(regularized_words) do
local ending = word:match("^" .. regularized_last_three .. "(.+)$")
-- Rules:
-- -- Interposing words must start with last three letters of previous word.
-- -- After these three letters must be three or more additional letters.
-- -- These additional letters must begin the following word.
-- WARNING! The color-adding will probably not work with transliteration.
if not ending then
if ignore_rules then
message = true
else
message = "The interposing word "
.. quote(word) .. " must start with the last three letters of "
.. quote(previous_word) .. ", " .. quote(regularized_last_three) .. "."
end
elseif #ending < 3 then
if ignore_rules then
message = true
else
local difference = 3 - #ending
local agreement = difference == 1 and "" or "s"
message = "The interposing word "
.. quote(word) .. " needs " .. difference .. " more letter" .. agreement .. "."
end
elseif not regularized_following_word:find("^" .. ending) then
if ignore_rules then
message = true
else
message = "The last word " .. quote(following_word) .. " must start with "
.. quote(ending) .. ", the final letters of "
.. quote(word) .. " after the last three letters of "
.. quote(previous_word) .. ", " .. quote(last_three) .. ", are removed."
end
end
if message then
if ignore_rules then
messages = (messages or 0) + 1
else
messages = messages or {}
message_number = message_number or 1
messages[message_number] = message
message_number = message_number + 1
end
end
message = nil
end
if messages then
if ignore_rules then
local plural = messages > 1 and true or false
return show_words(previous_word, words, following_word) ..
' <span style="color: red;">Rules broken ' .. messages ..
' time' .. (plural and "s" or "") .. '!</span>'
else
error(table.concat(messages, " "))
end
else
return show_words(previous_word, words, following_word)
end
end
local Wonderfool_page = "User:AryamanA/Wonderfool"
local function get_Wonderfool_names()
local list = mw.title.new(Wonderfool_page):getContent():match("==List==\n*(.-)\n*==")
local names = {}
for name in list:gmatch("{{user|([^}]+)}}") do
names[name] = true
end
return names
end
local Autotable = require("Module:auto-subtable")
local function compile_points_per_user(games, dont_merge_Wonderfool)
local users = Autotable()
local merge_Wonderfool = not dont_merge_Wonderfool
local is_Wonderfool
if merge_Wonderfool then
is_Wonderfool = get_Wonderfool_names()
end
for _, game in ipairs(games) do
for i, entry in ipairs(game) do
local user = entry.username
if merge_Wonderfool then
user = is_Wonderfool[user] and "Wonderfool" or user
end
local userdata = users[user]
userdata.points = (userdata.points or 0) + entry.points
end
end
return users
end
local function compare(user_table)
local function get_compare_value(user)
return user_table[user].points
end
return function (user1, user2)
return get_compare_value(user1) > get_compare_value(user2)
end
end
local function link_username(username)
if username == "Wonderfool" then
return "[[" .. Wonderfool_page .. "|Wonderfool]]"
else
return "[[User:" .. username .. "|" .. username .. "]]"
end
end
local function print_points(users)
-- Have to remove auto-subtabling; copy in case this causes errors in the
-- calling function.
users = require("Module:table").deepcopy(users):un_auto_subtable()
return table.concat(
fun.mapIter(
function(data, user)
return "* " .. link_username(user) .. ": " .. data.points
end,
require("Module:table").sortedPairs(users, compare(users))),
"\n")
end
local function generate_statistics(games)
local statistics = Autotable()
local all = {}
statistics.all = all
for _, game in ipairs(games) do
for i, entry in ipairs(game) do
local user = entry.username
local userdata = statistics[user]
local interposing_count = entry.interposing.count
userdata[interposing_count] = (userdata[interposing_count] or 0) + 1
all[interposing_count] = (all[interposing_count] or 0) + 1
end
end
local averages = {}
for user, interposing_data in pairs(statistics) do
local total_interposing_words = 0
local total_entries = 0
for interposing_count, number_of_times in pairs(interposing_data) do
total_interposing_words = total_interposing_words + interposing_count * number_of_times
total_entries = total_entries + number_of_times
end
local average = total_interposing_words / total_entries
averages[user] = math.floor(average * 10 + 0.5 ) / 10
end
return statistics, averages
end
function print_statistics(statistics, averages)
local output = {}
for user, data in pairs(statistics) do
table.insert(output, "* " .. (user ~= "all" and link_username(user) or "all players"))
table.insert(output, "** " .. averages[user] .. " interposing word" .. (averages[user] * 10 ~= 10 and "s" or "") .. " per entry")
for interposing_count, number_of_times in pairs(data) do
table.insert(output, "** " .. interposing_count
.. " interposing word" .. (interposing_count ~= 1 and "s " or " ")
.. number_of_times .. " time"
.. (number_of_times ~= 1 and "s" or ""))
end
end
return table.concat(output, "\n")
end
local month_numbers = m_table.invert {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
}
-- Converts a date into a number that will allow the date column to be sorted reliably.
local function make_date_number(date)
local hour, minute, day_of_month, month, last_two_of_year =
string.match(date, "^(%d%d):(%d%d), (%d%d?) (%a+) %d%d(%d%d)")
-- Each part of the date is multiplied by the least power of two greater than
-- the maximum possible value that that part can have.
return ((((last_two_of_year - 17) * 2 + month_numbers[month]) * 16 + day_of_month) * 32 + hour) * 64 + minute
end
-- For concatenating virtual interposing word tables produced by mw.loadData.
local function concat(array, sep)
local str = array[1] or ""
for i = 2, 15 do
if array[i] then
str = str .. sep .. array[i]
else
break
end
end
return str
end
function export.show_parsed_games(frame)
local games = mw.loadData("Module:games/data")
local t = {
'{| class="wikitable sortable"',
'! game,<br>entry !! username !! date !! day<br>difference !! preceding<br>word !! interposing words !! count !! following<br>word !! points'
}
local function detect_and_tag(text)
if not text:find("[\128-\255]") then
return tag(link(text), "Latn")
end
return tag(link(text), find_best_script(text))
end
for game_number, game in ipairs(games) do
for entry_number, entry in ipairs(game) do
table.insert(
t,
('|-\n| data-sort-value="%s" | %d–%d || %s || data-sort-value="%d" | %s || %s || %s || %s || %d || %s || %d')
:format(string.format("%02d%02d", game_number, entry_number),
game_number, entry_number, entry.username,
make_date_number(entry.date), entry.date:gsub("December", "Dec"):gsub(".+", '<span style="white-space: nowrap;">%1</span>'),
entry.day_difference and ("%.4f"):format(entry.day_difference) or "—",
detect_and_tag(entry.preceding),
concat(fun.map(detect_and_tag, entry.interposing), ", "), entry.interposing.count,
detect_and_tag(entry.following),
entry.points))
end
end
table.insert(t, "|}")
return table.concat(t, "\n")
-- return require("Module:debug").highlight_dump()
end
function export.show_statistics(frame)
return print_statistics(generate_statistics(mw.loadData("Module:games/data")))
end
function export.print_points(frame)
return print_points(compile_points_per_user(mw.loadData("Module:games/data")))
end
function export.print_game_data(frame)
return require("Module:debug").highlight_dump(mw.loadData("Module:games/data"))
end
-- fun.logAll(export)
return export