Module:Calendar

From Mighty Party Wiki
Jump to navigation Jump to search

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

-- This module implements [[Template:Calendar]].
-- All date functions are in UTC

local p = {}

function p._main(args)
	local currentDate = os.time()
	local baseDate = os.time{year=2022, month=8, day=12, hour=10} -- base date to determine rotation day
	local days = math.floor((currentDate - baseDate) / 60 / 60 / 24)
	
	if args[1] == "daily" then --daily reset at 1800
		local dailyReset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=18} 
		if dailyReset - currentDate <= 0 then 
			if args[2] == "date" then
				return os.date("%A, %B %d, %H:%M UTC", dailyReset + 60 * 60 * 24)
			end
			return displayRelativeTime(dailyReset - currentDate + 60 * 60 * 24) 
		else 
			if args[2] == "date" then
				return os.date("%A, %B %d, %H:%M UTC", dailyReset)
			end
			return displayRelativeTime(dailyReset - currentDate)
		end
	end
	if args[1] == "weekly" then --weekly reset at Sunday 1800
		local weeklyReset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=18} 
		while (os.date("*t", weeklyReset).wday ~= 1) or (weeklyReset - currentDate <= 0) do
			weeklyReset = weeklyReset + (60 * 60 * 24)
		end
		if args[2] == "date" then
			return os.date("%A, %B %d, %H:%M UTC", weeklyReset) 
		end
		return displayRelativeTime(weeklyReset - currentDate)
	end
	if args[1] == "league" then --league season reset every other monday at 2300
		local leagueReset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=23} 
		while (os.date("*t", leagueReset).wday ~= 2) or (leagueReset - currentDate <= 0) do
			leagueReset = leagueReset + (60 * 60 * 24)
		end
		if (math.floor((currentDate) / 60 / 60 / 24) % 14 < 7) then
			leagueReset = leagueReset + (7 * 24 * 60 * 60)
		end
		if args[2] == "date" then
			return os.date("%A, %B %d, %H:%M UTC", leagueReset) 
		end
		return displayRelativeTime(leagueReset - currentDate)
	end
	if args[1] == "friendship" then --daily reset at 0600
		local tokenreset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=6} 
		if tokenreset - currentDate <= 0 then 
			if args[2] == "date" then
				return os.date("%A, %B %d, %H:%M UTC", tokenreset + 60 * 60 * 24)
			end
			return displayRelativeTime(tokenreset - currentDate + 60 * 60 * 24) 
		else 
			if args[2] == "date" then
				return os.date("%A, %B %d, %H:%M UTC", tokenreset)
			end
			return displayRelativeTime(tokenreset - currentDate)
		end
	end
	if args[1] == "goldmine" then --gold mine at 2000, 0200, 1400
		local goldmine1 = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=20} 
		local goldmine2 = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=2} 
		local goldmine3 = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=14} 

		if goldmine1 - currentDate <= 0 then 
			goldmine1 = goldmine1 + 60 * 60 * 24
		end
		if goldmine2 - currentDate <= 0 then 
			goldmine2 = goldmine2 + 60 * 60 * 24
		end
		if goldmine3 - currentDate <= 0 then 
			goldmine3 = goldmine3 + 60 * 60 * 24
		end
		
		if args[2] == "date" then
			return os.date("%A, %B %d, %H:%M UTC", goldmine1) .. "<br/>" .. os.date("%A, %B %d, %H:%M UTC", goldmine2) .. "<br/>" .. os.date("%A, %B %d, %H:%M UTC", goldmine3)
		end
		return displayRelativeTime(goldmine1 - currentDate) .. "<br/>" .. displayRelativeTime(goldmine2 - currentDate) .. "<br/>" .. displayRelativeTime(goldmine3 - currentDate)
	end
	if args[1] == "turfwar" then --turf war clash at 0050, 1250, 1850, weekly reset Monday 1900
		local turfwar1 = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=0, min=50} 
		local turfwar2 = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=12, min=50} 
		local turfwar3 = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=18, min=50} 
		local turfwarreset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=19} 
		while (os.date("*t", turfwarreset).wday ~= 2) or (turfwarreset - currentDate <= 0) do
			turfwarreset = turfwarreset + (60 * 60 * 24)
		end		

		--don't display past clashes
		if turfwar1 - currentDate <= 0 then 
			turfwar1 = turfwar1 + 60 * 60 * 24
		end
		if turfwar2 - currentDate <= 0 then 
			turfwar2 = turfwar2 + 60 * 60 * 24
		end
		if turfwar3 - currentDate <= 0 then 
			turfwar3 = turfwar3 + 60 * 60 * 24
		end
		
		--clashes don't happen on monday
		if os.date("*t", turfwar1).wday == 2 then
			turfwar1 = turfwar1 + 60 * 60 * 24
		end
		if os.date("*t", turfwar2).wday == 2 then
			turfwar2 = turfwar2 + 60 * 60 * 24
		end
		if os.date("*t", turfwar3).wday == 2 then
			turfwar3 = turfwar3 + 60 * 60 * 24
		end
		
		if args[2] == "date" then
			return "'''Clash 1:''' " .. os.date("%A, %B %d, %H:%M UTC", turfwar1) .. "<br/>'''Clash 2:''' " .. os.date("%A, %B %d, %H:%M UTC", turfwar2) .. "<br/>'''Clash 3:''' " .. os.date("%A, %B %d, %H:%M UTC", turfwar3)
		end
		if args[2] == "next" then
			return "'''Next Turf War:''' " .. os.date("%A, %B %d, %H:%M UTC", turfwarreset) .. "<br/>Starts in " .. displayRelativeTime(turfwarreset - currentDate)
		end
		return "'''Clash 1:''' " .. displayRelativeTime(turfwar1 - currentDate) .. "<br/>'''Clash 2:''' " .. displayRelativeTime(turfwar2 - currentDate) .. "<br/>'''Clash 3:''' " .. displayRelativeTime(turfwar3 - currentDate) 
	end
	if args[1] == "trial" then --dungeon of trials changes at Monday 1000
		local trialReset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=10} 
		while (os.date("*t", trialReset).wday ~= 2) or (trialReset - currentDate <= 0) do
			trialReset = trialReset + (60 * 60 * 24)
		end
		if args[2] == "date" then
			return os.date("%A, %B %d, %H:%M UTC", trialReset) 
		end
		if args[2] == "current" then
			if math.floor((currentDate) / 60 / 60 / 24) % 14 < 7 then
				return "The Pit"
			else
				return "Dark Tower"
			end
		end
		if args[2] == "next" then
			if math.floor((currentDate) / 60 / 60 / 24) % 14 < 7 then
				return "Dark Tower"
			else
				return "The Pit"
			end
		end
		if args[2] == "darktower" then
			local startDay = currentDate
			local endDay = currentDate
			if math.floor((currentDate) / 60 / 60 / 24) % 14 < 7 then
				startDay = trialReset
				endDay = trialReset + (7 * 24 * 60 * 60)
			else
				startDay = trialReset - (7 * 24 * 60 * 60)
				endDay = trialReset
			end
			
			if currentDate < startDay then
				return "'''Start:''' " .. os.date("%A, %B %d, %H:%M UTC", startDay) .. "<br/>'''End:''' " .. os.date("%A, %B %d, %H:%M UTC", endDay)
			else
				return "'''Start:''' " .. os.date("%A, %B %d, %H:%M UTC", startDay) .. "<br/>'''End:''' " .. os.date("%A, %B %d, %H:%M UTC", endDay)
			end
		end
		if args[2] == "darktowerdate" then
			local startDay = currentDate
			local endDay = currentDate
			if math.floor((currentDate) / 60 / 60 / 24) % 14 < 7 then
				startDay = trialReset
				endDay = trialReset + (7 * 24 * 60 * 60)
			else
				startDay = trialReset - (7 * 24 * 60 * 60)
				endDay = trialReset
			end
			
			if currentDate < startDay then
				return "Starts in " .. displayRelativeTime(startDay - currentDate)
			else
				return "'''Currently Active'''<br/>Ends in " .. displayRelativeTime(endDay - currentDate)
			end
		end
		if args[2] == "pit" then
			local startDay = currentDate
			local endDay = currentDate
			if math.floor((currentDate) / 60 / 60 / 24) % 14 < 7 then
				startDay = trialReset - (7 * 24 * 60 * 60) 
				endDay = trialReset
			else
				startDay = trialReset
				endDay = trialReset + (7 * 24 * 60 * 60) 
			end
			
			if currentDate < startDay then
				return "'''Start:''' " .. os.date("%A, %B %d, %H:%M UTC", startDay) .. "<br/>'''End:''' " .. os.date("%A, %B %d, %H:%M UTC", endDay) 
			else
				return "'''Start:''' " .. os.date("%A, %B %d, %H:%M UTC", startDay) .. "<br/>'''End:''' " .. os.date("%A, %B %d, %H:%M UTC", endDay) 
			end
		end
		if args[2] == "pitdate" then
			local startDay = currentDate
			local endDay = currentDate
			if math.floor((currentDate) / 60 / 60 / 24) % 14 < 7 then
				startDay = trialReset - (7 * 24 * 60 * 60) 
				endDay = trialReset
			else
				startDay = trialReset
				endDay = trialReset + (7 * 24 * 60 * 60) 
			end
			
			if currentDate < startDay then
				return "Starts in " .. displayRelativeTime(startDay - currentDate)
			else
				return "'''Currently Active'''<br/>Ends in " .. displayRelativeTime(endDay - currentDate)
			end
		end
		return displayRelativeTime(trialReset - currentDate)
	end
	if args[1] == "divinearena" then --divine arena changes every other day at 1800
		local divinearenareset = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=18} 
		divinearenareset = divinearenareset + (((math.floor((currentDate) / 60 / 60 / 24) % 2) + 1) * 24 * 60 * 60)
		if args[2] == "date" then
			return os.date("%A, %B %d, %H:%M UTC", divinearenareset) 
		end
		return displayRelativeTime(divinearenareset - currentDate)
	end
	if args[1] == "chosenherotype" then
		local rotation = math.floor((days-4) / 14) % 6
		if rotation == 0 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'chaos', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'melee', link='yes'}} end
		if rotation == 1 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'order', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'ranged', link='yes'}} end
		if rotation == 2 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'nature', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'melee', link='yes'}} end
		if rotation == 3 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'chaos', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'ranged', link='yes'}} end
		if rotation == 4 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'order', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'melee', link='yes'}} end
		if rotation == 5 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'nature', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'ranged', link='yes'}} end
	end	
	if args[1] == "reborntype" then
		local rotation = math.floor((days-6) / 14) % 6
		if rotation == 0 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'order', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'ranged', link='yes'}} end
		if rotation == 1 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'chaos', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'melee', link='yes'}} end
		if rotation == 2 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'chaos', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'ranged', link='yes'}} end
		if rotation == 3 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'nature', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'melee', link='yes'}} end
		if rotation == 4 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'nature', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'ranged', link='yes'}} end
		if rotation == 5 then return mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'order', link='yes'}} .. " " .. mw.getCurrentFrame():expandTemplate{title='Icon', args = { 'melee', link='yes'}} end
	end	
	
	local currentRotationDay = days % 14 --determine current day in rotation
	local startDay = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=10} 
	local endDay = os.time{year=os.date("*t").year, month=os.date("*t").month, day=os.date("*t").day, hour=10} 
	local active = false
	local offset = 0
	local duration = 0
	
	if args[1] == "globalevent" then -- 7-13 global event
		duration = 6
		if (currentRotationDay >= 0 and currentRotationDay < 7) then
			active = false
			offset = 7
		end
		if (currentRotationDay >= 7 and currentRotationDay < 14) then
			active = true
			offset = 14-1 -- -1 for cooldown
		end
	end
	if args[1] == "chosenhero" then -- 0-3 chosen hero
		duration = 3
		if (currentRotationDay >= 0 and currentRotationDay < 4) then
			active = true
			offset = 3+1 -- +1 for cooldown
		end
		if (currentRotationDay >= 4 and currentRotationDay < 14) then
			active = false
			offset = 14
		end
	end
	if args[1] == "reborn" then -- 0-3 chosen hero
		duration = 1
		if (currentRotationDay >= 0 and currentRotationDay < 2) then
			active = false
			offset = 2
		end
		if (currentRotationDay >= 2 and currentRotationDay < 3) then
			active = true
			offset = 3
		end
		if (currentRotationDay >= 3 and currentRotationDay < 14) then
			active = false
			offset = 14
		end
	end
	if args[1] == "ascensionoflegends" then -- 0-3 ascension of legends
		duration = 3
		if (currentRotationDay >= 0 and currentRotationDay < 3) then
			active = true
			offset = 3
		end
		if (currentRotationDay >= 3 and currentRotationDay < 14) then
			active = false
			offset = 14
		end
	end
	if args[1] == "legendarywish" then -- 3-5/10-12 legendary wish
		duration = 2
		if (currentRotationDay >= 0 and currentRotationDay < 3) then
			active = false
			offset = 3
		end
		if (currentRotationDay >= 3 and currentRotationDay < 5) then
			active = true
			offset = 5
		end
		if (currentRotationDay >= 5 and currentRotationDay < 10) then
			active = false
			offset = 10
		end
		if (currentRotationDay >= 10 and currentRotationDay < 12) then
			active = true
			offset = 12
		end
		if (currentRotationDay >= 12 and currentRotationDay < 14) then
			active = false
			offset = 14
		end
	end	
	if args[1] == "unityoffactions" then -- 3-6 unity of factions
		duration = 4
		if (currentRotationDay >= 0 and currentRotationDay < 3) then
			active = false
			offset = 3
		end
		if (currentRotationDay >= 3 and currentRotationDay < 7) then
			active = true
			offset = 7
		end
		if (currentRotationDay >= 7 and currentRotationDay < 14) then
			active = false
			offset = 14+3
		end
	end
	if args[1] == "goldvein" then -- 3-6 gold rush
		duration = 7
		if (currentRotationDay >= 0 and currentRotationDay < 7) then
			active = false
			offset = 7
		end
		if (currentRotationDay >= 7 and currentRotationDay < 14) then
			active = true
			offset = 14
		end
	end
	
	--fix day off by one when between 0000 and 1000
	if ((os.date("*t", currentDate).hour >= 0) and (os.date("*t", currentDate).hour)) < 10 then
	    offset = offset - 1
	end
	
	if args[1] == "globalevent" or args[1] == "chosenhero" or args[1] == "reborn" or args[1] == "ascensionoflegends" or args[1] == "unityoffactions" or args[1] == "goldvein" or args[1] == "legendarywish" then
		
		if active then
			endDay = currentDate + (offset - currentRotationDay) * 60 * 60 * 24
			endDay = os.time{year=os.date("*t", endDay).year, month=os.date("*t", endDay).month, day=os.date("*t", endDay).day, hour=10} 
			startDay = endDay - (duration * 60 * 60 * 24)
		else
			startDay = currentDate + (offset - currentRotationDay) * 60 * 60 * 24
			startDay = os.time{year=os.date("*t", startDay).year, month=os.date("*t", startDay).month, day=os.date("*t", startDay).day, hour=10} 
			endDay = startDay + (duration * 60 * 60 * 24)
		end
		if args[2] == "date" then
			return "'''Start:''' " .. os.date("%A, %B %d, %H:%M UTC", startDay) .. "<br/>'''End:''' " .. os.date("%A, %B %d, %H:%M UTC", endDay) 
		end
		if currentDate < startDay then
			return "Starts in " .. displayRelativeTime(startDay - currentDate)
		else
			return "'''Currently Active'''<br/>Ends in " .. displayRelativeTime(endDay - currentDate)
		end
	end
	return mw.getCurrentFrame():preprocess("<small>This page was last cached on {{#time: l H:i T, j F Y}}. [{{fullurl:{{FULLPAGENAME}}|action=purge}} Click here to purge the server cache to update dates and times.]<br/>Listed events and dates are predictions of upcoming events. Special events may change the schedule. Check [https://discord.com/channels/327079160784879626/464059481018335233 #events-announcements] on the [https://discord.gg/mightyparty official Discord] for the official schedule.</small>")
end

function p.main(frame)
	local args = {}
	for k, v in pairs(frame:getParent().args) do
		args[k] = v
	end
	return p._main(args)
end

function displayRelativeTime(t)
	local seconds = t % 60
	t = math.floor(t / 60)
	local minutes = t % 60
	t = math.floor(t / 60)
	local hours = t % 24
	local days = math.floor(t / 24)
	local result = ""
	if days > 0 then
		result = result .. days .. (days == 1 and " day" or " days") .. ", "
	end
	if hours > 0 then
		result = result .. hours .. (hours == 1 and " hour" or " hours") .. ", "
	end
	if minutes > 0 then
		result = result .. minutes .. (minutes == 1 and " minute" or " minutes") .. ", "
	end
	
	return result:sub(1, -3)
end

return p