Module:Sandbox/User:Fearthe1337/Animal timers

From WIDEVERSE Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sandbox/User:Fearthe1337/Animal timers/doc

-- <nowiki>
local lang = mw.getContentLanguage()
local yesno = require('Module:Yesno')
local calc = require('Module:Form calculator')
local tables = require('Module:Tables')

local p = {}
local data = {
	['rabbit'] = { cycleLength = 5, regularCycleLength = 7, img = 'Common brown rabbit', page = 'Rabbit (Player-owned farm)', order = 1 },
	['chicken'] = { cycleLength = 50, regularCycleLength = 75, img = 'Common white hen', page = 'Chicken (Player-owned farm)', order = 2 },
	['chinchompa'] = { cycleLength = 150, regularCycleLength = 225, img = 'Grey chinchompa', page = 'Chinchompa (Player-owned farm)', order = 3 },
	['sheep'] = { cycleLength = 100, regularCycleLength = 200, img = 'White ewe', page = 'Sheep (Player-owned farm)', order = 4 },
	['spider'] = { cycleLength = 180, regularCycleLength = 360, img = 'Spirit spider (player-owned farm)', page = 'Spider (Player-owned farm)', order = 5 },
	['zygomite'] = { cycleLength = 500, regularCycleLength = 1000, img = 'Gloomshroom zygomite', page = 'Zygomite (Player-owned farm)', order = 6 },
	['cow'] = { cycleLength = 300, regularCycleLength = 900, img = 'Kandarin cow', page = 'Cow (Player-owned farm)', order = 7 },
	['yak'] = { cycleLength = 400, regularCycleLength = 1200, img = 'Spirit yak', page = 'Yak (Player-owned farm)', order = 8 },
	['dragon'] = { cycleLength = 1000, regularCycleLength = 3000, img = 'Black dragon (player-owned farm)', page = 'Dragon (Player-owned farm)', order = 9 },
	['frog'] = { cycleLength = 200, regularCycleLength = 300, img = 'Common green frog', page = 'Frog (Player-owned_farm)', order = 10 },
	['salamander'] = { cycleLength = 1005, regularCycleLength = 1507,5, img = 'Green salamander (player-owned farm)', page = 'Salamander (Player-owned farm)', order = 11 },
	['jadinko'] = { cycleLength = 700, regularCycleLength = 1400, img = 'Draconic jadinko (player-owned farm)', page = 'Jadinko (Player-owned farm)', order = 12 },
	['varanusaur'] = { cycleLength = 800, regularCycleLength = 1600, img = 'Feral dinosaur (player-owned farm)', page = 'Varanusaur', order = 13 },
	['brutish dinosaur'] = { cycleLength = 1100, regularCycleLength = 3300, img = 'Brutish dinosaur (player-owned farm)', page = 'Brutish dinosaur (Player-owned farm)', order = 14 },
	['arcane apoterrasaur'] = { cycleLength = 1100, regularCycleLength = 3300, img = 'Arcane apoterrasaur (player-owned farm)', page = 'Arcane apoterrasaur (Player-owned farm)', order = 15 },
	['spicati apoterrasaur'] = { cycleLength = 1200, regularCycleLength = 2600, img = 'Spicati apoterrasaur (player-owned farm)', page = 'Spicati apoterrasaur (Player-owned farm)', order = 16 },
	['oculi apoterrasaur'] = { cycleLength = 1300, regularCycleLength = 3900, img = 'Oculi apoterrasaur (player-owned farm)', page = 'Oculi apoterrasaur (Player-owned farm)', order = 17 },
	['scimitops'] = { cycleLength = 1100, regularCycleLength = 3300, img = 'Scimitops (player-owned farm)', page = 'Scimitops (Player-owned farm)', order = 18 },
	['asciatops'] = { cycleLength = 1200, regularCycleLength = 3600, img = 'Asciatops (player-owned farm)', page = 'Asciatops (Player-owned farm)', order = 19 },
	['malletops'] = { cycleLength = 1300, regularCycleLength = 3900, img = 'Malletops (player-owned farm)', page = 'Malletops (Player-owned farm)', order = 20 },
	['bagrada rex'] = { cycleLength = 1200, regularCycleLength = 3600, img = 'Bagrada rex (player-owned farm)', page = 'Bagrada rex (Player-owned farm)', order = 21 },
	['corbicula rex'] = { cycleLength = 1200, regularCycleLength = 3600, img = 'Corbicula rex (player-owned farm)', page = 'Corbicula rex (Player-owned farm)', order = 22 },
	['pavosaurus rex'] = { cycleLength = 1400, regularCycleLength = 4200, img = 'Pavosaurus rex (player-owned farm)', page = 'Pavosaurus rex (Player-owned farm)', order = 23 },
}
local data_order = {}
for k,v in pairs(data) do
	data_order[v.order] = k
end

function append(t,...)
	for i,v in ipairs({...}) do
		table.insert(t,v)
	end
end

function sortAnimals(a,b)
	return data[a].order < data[b].order
end

function animalFiles(t)
	table.sort(t, sortAnimals)
	local t2 = {}
	for i,v in ipairs(t) do
		t2[i] = string.format('[[File:%s.png|link=%s|%s]]', data[v].img, data[v].page, lang:ucfirst(v))
	end
	return t2
end

function p.calculator()
	local args = {
		template = 'Sandbox/User:FearThe1337/Animal_timers/t',
		form = 'jsCalc-root-pof-timers-form',
		result = 'jsCalc-root-pof-timers-result',
		outputtype = 'verticaltable',
		param1 = 'time', label1 = 'Timespan to display (hours; negative for previous ticks)', type1 = 'int', range1='-inf-inf', default1 = '10',
		cat='no'
	}
	for i,v in ipairs(data_order) do
		j = i + 1
		args['param'..j] = v
		args['label'..j] = 'Show '..v
		args['type'..j] = 'check'
		args['range'..j] = 'yes,no'
	end
	return tostring(calc._main(args))
end

function p.main(frame)
	return p._main(frame:getParent().args)
end

function p._main(args)
	local hours = tonumber(args.time)
	if not hours then
		return "Please enter the hours required as a number"
	elseif hours == 0 then
		return "Please enter a non-zero number of hours (negative is fine)"
	end
	local animals = {}
	
	for k,v in pairs(data) do
		if yesno(args[k]) then
			table.insert(animals, k)
		end
	end
	
	if #animals == 0 then
		return "Please select at least one animal"
	end
	return "'''This calculator may not be accurate to in-game time any more - please report inaccuracies and actual tick times [[Talk:Player-owned farm#Breeding tick calculator issues|here]] so that it can be corrected!'''<br />"..tostring(p.execute(animals, hours))
end

function p.execute(animals, timespan_hours)
	local times = {}
	for _,a in ipairs(animals) do
		local adata = data[a]
		local g1 = p.animals_generate(adata.cycleLength, timespan_hours, 0)
		local g2 = p.animals_generate(adata.regularCycleLength, timespan_hours, adata.cycleLength)
		
		for _,t in ipairs(g1) do
			if times[t] == nil then
				times[t] = {}
				times[t][0] = {}
				times[t][1] = {}
			end
			table.insert(times[t][0], a)
		end
		for _,t in ipairs(g2) do
			if times[t] == nil then
				times[t] = {}
				times[t][0] = {}
				times[t][1] = {}
			end
			table.insert(times[t][1], a)
		end
	end
	
	
	local r = {
		'Cycles in the '
	}
	
	if timespan_hours > 0 then
		append(r, 'next ', timespan_hours)
	else
		append(r, 'last ', timespan_hours*-1)
	end
	append(r, lang:plural(timespan_hours, ' hour:\n', ' hours:\n'))
	
	
	local ret = mw.html.create('table'):addClass('wikitable sticky-header')
    tables._row(ret:tag('tr'), {'Time', 'Breeding pen', 'Regular pen'}, true)
	
	
	
	local times_arr = {}
	for k in pairs(times) do table.insert(times_arr, k) end
	table.sort(times_arr)
	for _,t in ipairs(times_arr) do
		local a = times[t][0]
		local b = times[t][1]
		a = animalFiles(a)
		b = animalFiles(b)
		
		local columns = {
			mw.getCurrentFrame():preprocess(string.format('%s (UTC)', lang:formatDate('H:i, d F Y ', '@' .. t))),
			table.concat(a, ' '),
			table.concat(b, ' ')
		}
		
		local class = ''
		tables._row(ret:tag('tr'):addClass(class), columns, false)
	end
	
	table.insert(r, tostring(ret))
	
	return table.concat(r)
end

function p.animals_generate(cycleLength, timespan_hours, adjust)
	local timeNow = os.time()
	local cycleInS = cycleLength * 60
	local adjustInS = adjust * 60
	local times = {}
	local startT, endT
	local lastCycleTime

	if timespan_hours > 0 then
		if adjust > 0 then
			lastCycleTime = (math.floor((timeNow+cycleInS-adjustInS) / cycleInS) * cycleInS)
		else
			lastCycleTime = (math.floor(timeNow / cycleInS) * cycleInS)
		end
		startT = lastCycleTime
		endT = timeNow + timespan_hours * 3600
		local cycleTime
		for cycleTime = startT, endT, cycleInS do
			if cycleTime >= timeNow then
				table.insert(times, cycleTime)
			end
		end
	else
		if adjust > 0 then
			lastCycleTime = (math.floor((timeNow+cycleInS-adjustInS+cycleInS) / cycleInS) * cycleInS)
		else
			lastCycleTime = (math.floor(timeNow / cycleInS) * cycleInS)
		end
		-- timespan_hours is negative 
		endT = timeNow + timespan_hours * 3600
		startT = lastCycleTime - cycleInS + 3 * adjust
		cycleInS = cycleInS * -1
		local cycleTime
		for cycleTime = startT, endT, cycleInS do
			if cycleTime <= timeNow then
				table.insert(times, cycleTime)
			end
		end
	end
	return times
end

function p.test()
	return p.execute({'brutish dinosaur'}, 100)
end

return p
-- </nowiki>