5,459 bytes added
, 21:00, 15 May 2022
--[[ <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