Module:User:Happy5214/WikiWork

local p = {}
local calculators = {}

-- Global imports
local getArgs = require('Module:Arguments').getArgs
local math = require "Module:Math"
local round = math._precision_format
local concat = table.concat
local format = string.format
local insert = table.insert

-- Statistics
local stats, total
local top, high, mid, low
local fa, a, ga, b, c, start, stub
local taskForce

-- Utility
local function pad(number)
	return round(tostring(number), '3')
end

local function getCount(type)
	return stats[type] or 0
end

-- Setup
local function setup()
	top = getCount(taskForce .. 'topFA') + getCount(taskForce .. 'topA') + getCount(taskForce .. 'topGA') + getCount(taskForce .. 'topB') + getCount(taskForce .. 'topC') + getCount(taskForce .. 'topStart') + getCount(taskForce .. 'topStub')
	high = getCount(taskForce .. 'highFA') + getCount(taskForce .. 'highA') + getCount(taskForce .. 'highGA') + getCount(taskForce .. 'highB') + getCount(taskForce .. 'highC') + getCount(taskForce .. 'highStart') + getCount(taskForce .. 'highStub')
	mid = getCount(taskForce .. 'midFA') + getCount(taskForce .. 'midA') + getCount(taskForce .. 'midGA') + getCount(taskForce .. 'midB') + getCount(taskForce .. 'midC') + getCount(taskForce .. 'midStart') + getCount(taskForce .. 'midStub')
	low = getCount(taskForce .. 'lowFA') + getCount(taskForce .. 'lowA') + getCount(taskForce .. 'lowGA') + getCount(taskForce .. 'lowB') + getCount(taskForce .. 'lowC') + getCount(taskForce .. 'lowStart') + getCount(taskForce .. 'lowStub')
	fa = getCount(taskForce .. 'topFA') + getCount(taskForce .. 'highFA') + getCount(taskForce .. 'midFA') + getCount(taskForce .. 'lowFA')
	a = getCount(taskForce .. 'topA') + getCount(taskForce .. 'highA') + getCount(taskForce .. 'midA') + getCount(taskForce .. 'lowA')
	ga = getCount(taskForce .. 'topGA') + getCount(taskForce .. 'highGA') + getCount(taskForce .. 'midGA') + getCount(taskForce .. 'lowGA')
	b = getCount(taskForce .. 'topB') + getCount(taskForce .. 'highB') + getCount(taskForce .. 'midB') + getCount(taskForce .. 'lowB')
	c = getCount(taskForce .. 'topC') + getCount(taskForce .. 'highC') + getCount(taskForce .. 'midC') + getCount(taskForce .. 'lowC')
	start = getCount(taskForce .. 'topStart') + getCount(taskForce .. 'highStart') + getCount(taskForce .. 'midStart') + getCount(taskForce .. 'lowStart')
	stub = getCount(taskForce .. 'topStub') + getCount(taskForce .. 'highStub') + getCount(taskForce .. 'midStub') + getCount(taskForce .. 'lowStub')
	total = top + high + mid + low
end

-- Calculators

function constantGenerator(classes, importances, func)
	local constants = {}
	for class,classValue in pairs(classes) do
		for imp,impValue in pairs(importances) do
			constants[imp .. class] = func(classValue, impValue)
		end
	end
	return constants
end

function calculators.constant(classes)
	local importances = {top=1, high=1, mid=1, low=1}
	return constantGenerator(classes, importances, function (class, importance) return class end)
end

function calculators.linear(classes, importances)
	return constantGenerator(classes, importances, function (class, importance) return class * importance end)
end

function calculators.exponential(classes, importances)
	return constantGenerator(classes, importances, function (class, importance) return class ^ importance end)
end

function sumOfCountsWithConstantMultipliers(constants)
	local sum = 0.0
	for classImp,multiplier in pairs(constants) do
		sum = sum + (multiplier * getCount(taskForce .. classImp))
	end
	return sum
end

function calculators.sum(constants)
	return sumOfCountsWithConstantMultipliers(constants)
end

function calculators.average(constants)
	return sumOfCountsWithConstantMultipliers(constants) / total
end

-- Statistics

local function original()
	local classes = {FA=0, A=1, GA=2, B=3, C=4, Start=5, Stub=6}
	return calculators.sum(calculators.constant(classes))
end

local function originalRelative()
	local classes = {FA=0, A=1, GA=2, B=3, C=4, Start=5, Stub=6}
	return calculators.average(calculators.constant(classes))
end

local function importanceAdjusted()
	local classes = {FA=0, A=1, GA=2, B=3, C=4, Start=5, Stub=6}
	local importances = {top=2, high=1.5, mid=1, low=0.5}
	return calculators.average(calculators.linear(classes, importances))
end

local function reverseImportanceAdjusted()
	local classes = {FA=0, A=1, GA=2, B=3, C=4, Start=5, Stub=6}
	local importances = {top=0.5, high=1, mid=1.5, low=2}
	return calculators.average(calculators.linear(classes, importances))
end

local function exponentialImportanceAdjusted()
	local classes = {FA=0, A=0.25, GA=0.5, B=1, C=2, Start=3, Stub=4}
	local importances = {top=4, high=2, mid=1, low=0.5}
	return calculators.average(calculators.exponential(classes, importances))
end

---- Ratios
local function importanceRatio()
	return (2*top + 1.5*high + 1*mid + 0.5*low) / total
end

local function importanceAdjustedRatio()
	return importanceAdjusted() / original()
end

local function reverseImportanceAdjustedRatio()
	return reverseImportanceAdjusted() / original()
end

-- Table definitions
local columns = {{"ω", original},
                 {"Ω", originalRelative},
                 {"Importance-adjusted WikiWork", importanceAdjusted},
                 {"Importance ratio", importanceRatio},
                 {"Exponential importance-adjusted WikiWork", exponentialImportanceAdjusted},
                 }

function p._row(rowTaskForce)
	taskForce = rowTaskForce
	setup()
	local cells = {}
	for k,v in ipairs(columns) do
		insert(cells, pad(v[2]()))
	end
	return '| ' .. concat(cells, ' || ')
end

function p.row(frame)
	stats = getArgs(frame)
	return p._row('')
end

function p.header(frame)
	return p._header()
end

function p._header()
	local headers = {}
	for k,v in ipairs(columns) do
		insert(headers, v[1])
	end
	return '! ' .. concat(headers, ' !! ')
end

local taskForces = {
	"USRD",
	"IH",
	"USH",
	"TRL",
	"US66",
	"AL",
	"AK",
	"AZ",
	"AR",
	"CA",
	"CO",
	"CT",
	"DE",
	"DC",
	"FL",
	"GA",
	"HI",
	"ID",
	"IL",
	"IN",
	"IA",
	"KS",
	"KY",
	"LA",
	"ME",
	"MD",
	"MA",
	"MI",
	"MN",
	"MS",
	"MO",
	"MT",
	"NE",
	"NV",
	"NH",
	"NJ",
	"NM",
	"NY",
	"NC",
	"ND",
	"OH",
	"OK",
	"OR",
	"PA",
	"RI",
	"SC",
	"SD",
	"TN",
	"TX",
	"UT",
	"VT",
	"VA",
	"WA",
	"WV",
	"WI",
	"WY",
	"GU",
	"PR",
	"VI",
}

local shields = {
	USRD = "USRD logo.svg",
	IH = "I-blank.svg",
	USH = "US blank.svg",
	TRL = "Auto Trails logo.svg",
	US66 = "US 66 (CA).svg",
	AL = "Alabama blank.svg",
	AK = "Alaska blank shield.svg",
	AZ = "Arizona blank.svg",
	AR = "Arkansas blank.svg",
	CA = "California blank.svg",
	CO = "Colorado blank.svg",
	CT = "Connecticut Highway blank.svg",
	DE = "Elongated circle blank 2-digit.svg",
	DC = "DC-blank.svg",
	FL = "Florida blank.svg",
	GA = "Georgia blank.svg",
	HI = "HI-blank.svg",
	ID = "ID-blank.svg",
	IL = "Illinois blank.svg",
	IN = "Indiana blank.svg",
	IA = "Iowa blank.svg",
	KS = "K-blank.svg",
	KY = "Elongated circle blank 2-digit.svg",
	LA = "Louisiana blank.svg",
	ME = "MA Route blank.svg",
	MD = "MD blank.svg",
	MA = "MA Route blank.svg",
	MI = "M-Blank.svg",
	MN = "MN-blank.svg",
	MS = "Ellipse sign blank.svg",
	MO = "MO-blank.svg",
	MT = "MT-blank.svg",
	NE = "Nebraska state highway marker.svg",
	NV = "Nevada blank.svg",
	NH = "NH Route blank.svg",
	NJ = "Ellipse sign blank.svg",
	NM = "New Mexico blank.svg",
	NY = "NY-blank.svg",
	NC = "NC blank.svg",
	ND = "North Dakota blank.svg",
	OH = "OH-blank.svg",
	OK = "Oklahoma State Highway blank.svg",
	OR = "OR blank 2.svg",
	PA = "PA-blank2di.svg",
	RI = "Rhode Island blank.svg",
	SC = "South Carolina blank.svg",
	SD = "SD Blank-2d.svg",
	TN = "Tennessee blank.svg",
	TX = "Texas blank.svg",
	UT = "Utah blank.svg",
	VT = "Vermont blank border.svg",
	VA = "Virginia blank.svg",
	WA = "WA-blank.svg",
	WV = "WV-blank.svg",
	WI = "WIS blank.svg",
	WY = "WY-blank.svg",
	GU = "Guam Route blank.svg",
	PR = "Puerto Rico Highway blank.svg",
	VI = "Circle sign blank.svg",
}

local function fullRow(taskForce)
	local headerTemplate = '! scope="row" |'
	local image = format("[[File:%s|20px|link=]]", shields[taskForce])
	local link = taskForce == 'USRD' and '[[WP:USRD|USRD]]' or format("[[WP:USRD/%s|%s]]", taskForce, taskForce)
	local separator = '\n|'
	local row = {headerTemplate, image, link, separator, p._row(taskForce)}
	return concat(row, ' ')
end

function p._wikiwork()
	rows = {'{| class="wikitable sortable plainlinks"'}
	insert(rows, '! class="unsortable" | Task force\n' .. p._header())
	for _,taskForce in ipairs(taskForces) do
		insert(rows, fullRow(taskForce))
	end
	insert(rows, '|}')
	return concat(rows, "\n|-\n")
end

function p.wikiwork(frame)
	stats = getArgs(frame)
	return p._wikiwork()
end

return p