Module:games/data

local fun = require "Module:fun"

local function matches_to_array(text, pattern) if not text then return nil end local t = {} local i = 0 for match in text:gmatch(pattern) do		i = i + 1 t[i] = match end return t end

local function split(text, char) if not text then return nil end if #char ~= 1 then error(char .. " is not a single character.") end return matches_to_array(text, "[^" .. char .. "]+") end

local function grab_games(page) local games = {} local i = 0 local j, _, equals repeat i = i + 1 _, j, equals, games[i] = page:find("(===*)%s*Game " .. i .. "[^=]*%s*%1\n(.-)\n*==", j)		if not j then -- match to end of page _, j, equals, games[i] = page:find("(===*)%s*Game " .. i .. "[^=]*%s*%1(.+)\n*$", j)		end if j then j = j - #equals - 1 end until not j	if not games[1] then error("No games found!") end return games end

local days_in_month = { January = 31, February = 28, March = 31, April = 30, May = 31, June = 30, July = 31, August = 31, September = 30, October = 31, November = 30, December = 31, }

local months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }

local function month_and_day_to_day_in_year(month, day) local day_in_year = 0 for _, month_name in ipairs(months) do		if month_name == month then break end day_in_year = day_in_year + days_in_month[month_name] end return day_in_year + day end

local memo = {} setmetatable(	memo,	{		__index = function(self, key)			local val = {}			self[key] = val			return val		end	})

-- Memoize. local function get_day_in_year(month, day) local day_in_year = memo[month][day] if not day_in_year then day_in_year = month_and_day_to_day_in_year(month, day) memo[month][day] = day_in_year end return day_in_year end

-- Change this if game goes into January. local minutes_in_day = 24 * 60 local start_date = get_day_in_year("December", 1) local function get_time_in_days(date) local hour, minute, day, month, last_two_of_year = date:match("(%d%d):(%d%d), (%d+) (%a+) %d%d(%d%d)") return 365 * (tonumber(last_two_of_year) - 17) + get_day_in_year(month, tonumber(day)) - start_date + tonumber(hour) / 24 + tonumber(minute) / minutes_in_day end

local function round(decimals) local power = 10 ^ decimals return function(number) return math.floor(number * power) / power end end

local round4 = round(4) local function get_day_difference(date1, date2) return round4(math.abs(get_time_in_days(date1) - get_time_in_days(date2))) end

local function parse_games(games) local parsed_games = {} local function word_param_filter(word) return not word:find("^lang%d*=") and not word:find("^tr%d*=") end for i, game in ipairs(games) do		local parsed_game = {} parsed_games[i] = parsed_game local j = 0 local to_be_ignored, prev_date for game_entry, first_character in game:gmatch("\n%*%s+(([%[{])[^\n]+)") do			local interposing_words if first_character == "{" then if game_entry:find("ignore rules=", 1, true) then to_be_ignored = true else interposing_words = split(game_entry:match("{{game entry|([^}]+)}}"), "|") -- Remove |lang=, |langN=, |tr=, |trN=. interposing_words = fun.filter(						word_param_filter,						interposing_words) end else local wordlist = game_entry:match("%b[]%s+%b%s+%b[]") if wordlist:find("{{", 1, true) then local words_by_position = {} local _, endpos, word -- Grab any words in a link template. while true do						_, endpos, word = wordlist:find("{{[lm]|[^|]+|([^|]+)[^}]*}", endpos) if not endpos then break end words_by_position[endpos] = word end -- Grab bare links. endpos = 1 while true do						_, endpos, word = wordlist:find("%[%[([^%]]+)%]%]", endpos) if not endpos then break end words_by_position[endpos] = word end interposing_words = require("Module:table").compressSparseArray(words_by_position) else -- Grab bare links. interposing_words = matches_to_array(wordlist, "%[%[([^%]]+)%]%]") end end if interposing_words then local preceding = table.remove(interposing_words, 1) local length = #interposing_words local following = table.remove(interposing_words, length) interposing_words.count = length - 1 -- Change this if game goes into January. local date = game_entry:match("%d%d:%d%d, %d%d? %a+ %d%d%d%d") local day_difference if not date then mw.log("No date found in the game entry " .. game_entry .. ".") elseif prev_date then day_difference = get_day_difference(date, prev_date) end j = j + 1 prev_date = date parsed_game[j] = { preceding = preceding, following = following, interposing = interposing_words, username = game_entry:match("User:([^%]|]+)") or mw.log("No username found in the game entry " .. game_entry .. "."), date = date, day_difference = day_difference, }			elseif not to_be_ignored then mw.log("The game entry " .. game_entry .. " could not be parsed!") end end end return parsed_games end

--([^}]+)}}") do		names[name] = true	end	return names end --

local function count_points(games) local users = {} --	local conditional_logObject	if fullpagename == "Wiktionary:Christmas Competition 2017" then		function conditional_logObject end	else		function conditional_logObject(...)			return mw.logObject(...)		end	end	-- for _, game in ipairs(games) do		local prev for i, entry in ipairs(game) do			local user = entry.username -- user = is_Wonderfool[user] and "Wonderfool" or user -- 10 points for each successful extension of the chain. local points = 10 -- 5 points for each additional interposing word. points = points + (entry.interposing.count - 1) * 5 -- 25 points if last extension to chain was 3 days or more ago. local day_difference = entry.day_difference if day_difference and day_difference > 3 then -- conditional_logObject{ prev, entry, difference = day_difference } points = points + 25 end -- 10 points to the last user to extend each chain. if not game[i + 1] then points = points + 10 end entry.points = points -- prev = entry end end return games end

return count_points(parse_games(grab_games(mw.title.new("Wiktionary:Christmas Competition 2017"):getContent)))