Module:Rotations

From Tradelands Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Rotations/doc

--[[ <nowiki>
Various functions for activities that have time based rotations
--]]
local p = {}


local seconds_in_day = 24 * 60 * 60
local seconds_in_minute = 60

local _on_ = 'table-bg-green'
local _off_ = 'table-bg-grey'

local yesno = {
	[true] = _on_,
	[false] = _off_
}

local unit_seconds_from_name = {
	minute = seconds_in_minute,
	day = seconds_in_day
}

local lang = mw.language.new('en')

--[[
Returns the plural of the word
--]]
function p.plural(word, n, plural)
	if n == 1 then
		return word
	else
		return plural or (word .. 's')
	end
end

--[[

--]]
function p.on_off(on_time, total_time, offset, unit_seconds)
	local units_after_utc = math.floor(os.time() / unit_seconds)
	local units_into_start = (units_after_utc + offset) % total_time

	local on = units_into_start < on_time

	local units_until_change
	if on then
		units_until_change = on_time - units_into_start
	else
		units_until_change = total_time - units_into_start
	end

	return on, units_until_change
end

--[[
Returns a number that can be used to identify the rotation based on:
* The number of days per rotation
* The number of rotations available
* The offset of days such that Tuesday 1 January 1970 - offset would be the starting day for rotation 1 (the absolute value of this should be less than interval * rotation_count)

Also returns a second value that determines how many days until the next rotation
--]]
function p.rotation_days(interval, rotation_count, offset)
	local days_after_utc = math.floor(os.time() / seconds_in_day)
	local days_into_period = (days_after_utc + offset) % (interval * rotation_count)

	local rotation = math.floor(days_into_period / interval) + 1
	local days_until_next_rotation = interval - days_into_period % interval

	return rotation, days_until_next_rotation
end

--[[
Returns a number that can be used to identify the rotation based on:
* The number of minutes per rotation
* The number of rotations available
* The offset of minutes such that Tuesday 1 January 1970 - offset would be the starting time for rotation 1

Also returns a second value that determines how many minutes until the next rotation
--]]
function p.rotation_minutes(interval, rotation_count, offset)
	local minutes_after_utc = math.floor(os.time() / seconds_in_minute)
	local minutes_into_period = (minutes_after_utc + offset) % (interval * rotation_count)

	local rotation = math.floor(minutes_into_period / interval) + 1
	local minutes_until_next_rotation = interval - minutes_into_period % interval

	return rotation, minutes_until_next_rotation
end

--[[

--]]
function p.simple_on_off(on_time, total_time, offset, unit_name)
	local unit_seconds = unit_seconds_from_name[unit_name]

	local on, change_time = p.on_off(on_time, total_time, offset, unit_seconds)

	local ret_table = mw.html.create('table')
				:addClass('wikitable')
				:css({ ['text-align'] = 'center',
					float = 'right' })
				:tag('tr')
					:tag('td')
						:wikitext('Time until ' .. (on and 'end' or 'start') .. ': ' .. change_time .. ' ' .. p.plural(unit_name, change_time))
						:addClass(yesno[on])
					:done()
				:done()

	return ret_table
end

local function date_of(i_rot, interval, curr_rot, next_in, total_rots)
	local s = os.time() + seconds_in_day * (next_in + interval * ((i_rot - curr_rot - 1) % total_rots) )
	if i_rot==curr_rot then
		return 'Now!'
	else
		return lang:formatDate('j M', '@' .. s, nil)
	end
end

local function date_of_full(i_rot, interval, curr_rot, next_in, total_rots)
	local s = os.time() + seconds_in_day * (next_in + interval * ((i_rot - curr_rot - 1)) )
	return lang:formatDate('j F Y', '@' .. s, nil)
end

--[[

--]]
function p.simple_table(rotation_names, interval, offset, dated)
	local rotation, next = p.rotation_days(interval, #rotation_names, offset)
	local align = 'center'

	if dated then
		align = 'left'
		pad = '0.5em'
	end

	local ret_table = mw.html.create('table')
				:addClass('wikitable')
				:css({ ['text-align'] = align,
					margin = '3px',
					float = 'right' })
				:tag('caption')
					:wikitext('Current rotation')
				:done()
	local td
	for i, v in ipairs(rotation_names) do
		td = ret_table:tag('tr'):tag('td')
		td			:addClass(yesno[i==rotation])
					:wikitext(v)
					:done()
				:done()
			:done()
		if dated then
			td:css('padding-left', '0.5em')
				:tag('span')
				:css({ ['float'] = 'right',
					['text-align'] = 'right',
					['font-size'] = '80%',
					['margin-left'] = '5px' })
				:wikitext(date_of(i, interval, rotation, next, #rotation_names))
		end
	end
	td = ret_table:tag('tr'):tag('td')
	td			:css('text-align', 'center')
				:wikitext("'''Next: "..next..' '..p.plural('day', next).."'''")
			:done()
		:done()
	return ret_table
end

--[[

--]]
function p.simple_table_minutes(rotation_names, interval, offset)
	local rotation, next = p.rotation_minutes(interval, #rotation_names, offset)
	local align = 'center'

	local ret_table = mw.html.create('table')
				:addClass('wikitable')
				:css({ ['text-align'] = align,
					margin = '3px',
					float = 'right' })
				:tag('caption')
					:wikitext('Current rotation')
				:done()
	local td
	for i, v in ipairs(rotation_names) do
		td = ret_table:tag('tr'):tag('td')
		td			:addClass(yesno[i==rotation])
					:wikitext(v)
					:done()
				:done()
			:done()
	end
	td = ret_table:tag('tr'):tag('td')
	td			:css('text-align', 'center')
				:wikitext("'''Next: "..next..' '..p.plural('minute', next).."'''")
			:done()
		:done()
	return ret_table
end

function p.resourcecount()
	return p.simple_on_off(15, 60, 30, 'minute')
end

return p