Module:Sandbox/Izno/Word counter

local p = {}

-- Returns the union of the values of two tables, as a sequence. local function union(t1, t2)

local vals = {} for k, v in pairs(t1) do		vals[v] = true end for k, v in pairs(t2) do		vals[v] = true end local ret = {} for k, v in pairs(vals) do		table.insert(ret, k)	end return ret end

-- Returns a table containing the numbers of the arguments that exist -- for the specified prefix. For example, if the prefix was 'data', and -- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}. local function get_arg_nums(args, prefix) local nums = {} for k, v in pairs(args) do local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$') if num then table.insert(nums, tonumber(num)) end end table.sort(nums) return nums end

local function trim_args(args) local new_args = {} for k,v in pairs(args) do		new_args[k] = mw.text.trim(v) end return new_args end

local function responses_have_signatures(response, response_signature) return response and response ~=  and response_signature and response_signature ~=  end

local function get_responses(args) local response_numbers = union(		get_arg_nums(args, 'response'),		get_arg_nums(args, 'response signature')	) table.sort(response_numbers) local responses = {} local response_signatures = {} for _, num in ipairs(response_numbers) do local response = args['response' .. num] local response_signature = args['response signature' .. num] if not responses_have_signatures(response, response_signature) then error('|response' .. num .. '= or |response signature' .. num .. '= is missing') end table.insert(responses, response) table.insert(response_signatures, response_signature) end return responses, response_signatures end

local function wordcount(word_limit, statement, signature, responses, response_signatures) -- this actually gets the word count. we slightly overcount because this is -- wikitext, so things like '\n* ' and elinks will cause an extra word. -- we can get a count of the '*' and similar constructs separately if we want. -- but parsing wikitext to count links is :(	-- tables are doomed and probably would just always be better placed on a	-- different page than the primary statements are.	-- from https://stackoverflow.com/questions/29133416/how-to-count-the-amount-of-words-in-a-text-file-in-lua	local _, n_statement = mw.ustring.gsub(statement .. table.concat(responses, '\n'), '%S+', '')	if n_statement > word_limit then error('Too many words') end	if n_statement <= 0 then error('No words') end

if not signature or signature == '' then error('No signature') end local joined_responses = { statement, signature }	for k, _ in ipairs(responses) do table.insert(joined_responses, responses[k] .. '\n' .. response_signatures[k]) end return table.concat(joined_responses) end

function p.statement(frame) local args = trim_args(frame.args)

local statement = args.statement or '' local signature = args.signature or '' local added_words = tonumber(args['added words']) or 0 local word_limit = 500 + added_words local responses, response_signatures = get_responses(args) return wordcount(word_limit, statement, signature, responses, response_signatures) end

return p