Module:User:Pival13/Main Page

local cargo = mw.ext.cargo local escq = require 'Module:EscQ'.main1 local mf = require 'Module:MF'.main1 local Hash = require 'Module:HashUtil' local List = require 'Module:ListUtil' local Datetime = require 'Module:DatetimeUtil'

-----					Resources -----

local countdown = function (dt) if dt >= 86400 then return ('Days left: %d'):format(math.floor(dt / 86400)) elseif dt >= 3600 then return ('Hrs. left: %d'):format(math.floor(dt / 3600)) else return ('Mins. left: %d'):format(math.floor(dt / 60)) end end

local eventEntry = function (banner, dt) local eventbox = mw.html.create('div'):css('vertical-align', 'middle'):css("margin","5px 35px"):css("display","inline-block") eventbox:tag('div'):addClass('img-responsive'):wikitext(banner) eventbox:tag('b'):wikitext(countdown(dt)) return eventbox end

-----					Quests -----

local currentQuests = function (args, frame) local listQuests = cargo.query("Quests,QuestRewards", 		"Quests.GroupName=GroupName,Quests.EndTime=EndTime,Quests.StartTime=StartTime," .. 		IF(Kind='item',Item,Kind)=kind,SUM(Amount)=count,COUNT(Text)=nbQuests,		{			join = "Quests.WikiName=QuestRewards.WikiName",			where = "NOW BETWEEN Quests.StartTime AND Quests.EndTime",			having = "NOW BETWEEN StartTime AND EndTime",			orderBy = "Quests.WikiName",			groupBy = "Quests.GroupName,Kind,Item",			limit=1000,		}) local quests = {} local now = os.time for _, quest in ipairs(listQuests) do		if #quests > 0 and quests[#quests].name == quest.GroupName then table.insert(quests[#quests].rewards, {count=quest.count, kind=quest.kind}) quests[#quests].nbQuests = quests[#quests].nbQuests + tonumber(quest.nbQuests) else quests[#quests + 1] = { name = quest.GroupName, start = Datetime.from_cargo(quest.StartTime), remaining = Datetime.from_cargo(quest.EndTime) - now, nbQuests = tonumber(quest.nbQuests), rewards = }		end end for _, quest in ipairs(quests) do		quest.text = ("Rewards over %d quests:&#10;%s"):format(quest.nbQuests,			List.reduce(List.map(quest.rewards, function (reward)				return ' • ' .. reward.count .. ' ' .. reward.kind			end), function (v1, v2) return v1 .. '&#10;' .. v2			end)) end local tbl = mw.html.create('table'):css('width', '100%') for _, quest in ipairs(quests) do		local row = tbl:tag('tr') row:tag('td'):wikitext(frame:expandTemplate{			title = 'QuestPage',			args = {				quest.name,				frame:expandTemplate{					title = 'Hover',					args = { quest.name, quest.text }				},				ym = os.date("%b %Y", quest.start)			}		}) local cell = row:tag('td') if now - quest.start > quest.remaining * 4 then cell = cell:tag('b') end cell:wikitext(countdown(quest.remaining)) end

return tostring(tbl) end

-----					Special Maps -----

-- reverse appearance order for special maps -- rival domains -> ghb / bhb / lhb / mhb -> limited hb -> event maps local MAP_ORDER_FN = { function (v) return v.MapGroup == 'Rival Domains' end, function (v) return v.MapGroup == 'Grand Hero Battle' or v.MapGroup == 'Bound Hero Battle' or		v.MapGroup == 'Legendary Hero Battle' or v.MapGroup == 'Mythic Hero Battle' end, function (v) return v.MapGroup == 'Limited Hero Battle' end, function (v) return true end, }

local maps = function (args, frame) local upcoming = args.upcoming and tonumber(frame:callParserFunction('#time', 'U', '+' .. args.upcoming)) local now = os.time local timeCondition = upcoming and "(StartTime BETWEEN NOW AND '%s')" or "('%s' BETWEEN StartTime AND EndTime)" local allMaps = cargo.query('Maps,MapDates', 'Map,MapGroup,Maps._pageName=Page,StartTime,EndTime', {		join = 'Maps._pageName=MapDates._pageName',		where = ("EndTime!='%s' AND MapGroup!='Tempest Trials' AND " .. timeCondition):format( Datetime.MAX_TIME, Datetime.to_cargo(upcoming or now)),		orderBy = 'StartTime,Map',		limit = 100,	}) List.concat_self(allMaps, cargo.query('LimitedMaps=LM,LimitedMaps__Entry=LME', "Map,CONCAT('Limited Hero Battle')=MapGroup,LM._pageName=Page,StartTime,EndTime,GROUP_CONCAT(LME._value SEPARATOR ',')=Entry", { join = 'LM._ID=LME._rowID', where = timeCondition:format(Datetime.to_cargo(upcoming or now)), orderBy = 'StartTime,Map', groupBy = 'LM._ID', limit = 100, }))

for _, v in ipairs(allMaps) do		v.StartTime = Datetime.from_cargo(v.StartTime) v.EndTime = Datetime.from_cargo(v.EndTime) end

local sortedMaps = {} for _, fn in ipairs(MAP_ORDER_FN) do		List.concat_self(sortedMaps, List.delete_if(allMaps, fn)) end List.reverse_self(sortedMaps) if upcoming and #sortedMaps > 0 then sortedMaps = List.sort_by(sortedMaps, function (map, i) return tonumber(('%d.%02d'):format(map.StartTime, i)) end) end

-- existing special map banners local vbanners = Hash.from_ipairs(cargo.query('_pageData', '_pageName', { where = "_pageName RLIKE '^File:Banner V[0-9]{4}\\.(webp|png)$'", limit = 200, }), function (v) return mw.ustring.match(v._pageName, 'Banner (V%d+)'), true end)

return table.concat(List.map(sortedMaps, function (v) local bannerName = nil local limited = nil if mw.ustring.sub(v.Map, 1, 1) == 'V' then bannerName = vbanners[v.Map] and v.Map or 'V0001' elseif v.MapGroup == 'Rival Domains' then bannerName = 'Rival Domains' local num = tonumber(mw.ustring.match(v.Map, '^Q(%d+)$')) if num and num >= 9 then bannerName = ('Q%04d'):format((num - 1) % 4 + 1) end elseif v.MapGroup == 'Relay Defense' then bannerName = 'R0001' elseif v.MapGroup == 'Limited Hero Battle' then limited = v.Entry end local banner = frame:expandTemplate {title = 'Banner HB', args = {v.Page, bannerName = bannerName, limited = limited}} return tostring(eventEntry(banner, upcoming and v.StartTime - now or v.EndTime - now)) end)) end

local loopingMaps = function (args, frame) local allMaps = cargo.query('Maps,MapDates', 'Map,MapGroup,Maps._pageName=Page,StartTime,EndTime,CycleTime,AvailTime', {		join = 'Maps._pageName=MapDates._pageName',		where = "CycleTime IS NOT NULL OR AvailTime IS NOT NULL",		orderBy = "IF(Map LIKE 'V%',1,IF(Map LIKE 'U%',3,2)),Map DESC",		limit = 100,	})

for _, v in ipairs(allMaps) do		v.StartTime = Datetime.from_cargo(v.StartTime) v.EndTime = Datetime.from_cargo(v.EndTime) v.CycleTime = tonumber(v.CycleTime) v.AvailTime = tonumber(v.AvailTime) end

local now = os.time List.keep_if(allMaps, function (v)		v.StartTime = math.max(v.StartTime, v.StartTime + math.floor((now - v.StartTime) / v.CycleTime) * v.CycleTime)		v.EndTime = math.min(v.EndTime, v.StartTime + v.AvailTime - 1)		return now >= v.StartTime and now <= v.EndTime	end)

return table.concat(List.map(allMaps, function (v) local banner = frame:expandTemplate {title = 'Banner HB', args = {v.Page}} return tostring(eventEntry(banner, v.EndTime - now)) end)) end

-----					Events -----

local EVENT_SOURCES = { {'VotingGauntlets', "CONCAT('Voting Gauntlet')=kind,  _pageName=page,Name=text,CONCAT('Voting Gauntlet: ',Name)=name"}, {'TempestTrials',  "CONCAT('Tempest Trials')=kind,    _pageName=page,Name=text,FullName=name"}, {'TapBattles',     "CONCAT('Tap Battle')=kind,        _pageName=page,Name=text,CONCAT('Illusory Dungeon: ',Name)=name"}, {'GrandConquests', "CONCAT('Grand Conquests')=kind,   _pageName=page,          _pageName=name"}, {'ForgingBonds',   "CONCAT('Forging Bonds')=kind,     _pageName=page,Name=text,CONCAT('Forging Bonds: ',Name)=name"}, {'RokkrSieges',    "CONCAT('Røkkr Sieges')=kind,      _pageName=page,          _pageName=name"}, {'LostLore',       "CONCAT('Lost Lore')=kind,         _pageName=page,Name=text,CONCAT('Lost Lore: ',Name)=name,IF(World='World of Heroes',1,0)=isSpoil"}, {'HallOfForms',    "CONCAT('Hall of Forms')=kind,     _pageName=page,          _pageName=name"}, {'MjolnirsStrike', "CONCAT('Mjölnir\\'s Strike')=kind,_pageName=page,          _pageName=name"}, {'FrontlinePhalanx',"CONCAT('Frontline Phalanx')=kind, _pageName=page,         _pageName=name"}, {'PawnsOfLoki',    "CONCAT('Pawns of Loki')=kind,     _pageName=page,          _pageName=name"}, }

local events = function (args, frame) local now = os.time local upcoming = args.upcoming and tonumber(frame:callParserFunction('#time', 'U', '+' .. args.upcoming)) local allEvents = {} local queryArgs = { where = "EndTime > NOW", groupBy = '_pageName', orderBy = 'StartTime', limit = 1, }	for _, v in ipairs(EVENT_SOURCES) do List.concat_self(allEvents, cargo.query(v[1], v[2] .. ',StartTime,EndTime', queryArgs)) end for _, v in ipairs(allEvents) do		v.StartTime = Datetime.from_cargo(v.StartTime) v.EndTime = Datetime.from_cargo(v.EndTime) end if upcoming then allEvents = List.keep_if(allEvents, function (event) return event.StartTime > now and event.StartTime < upcoming end) table.sort(allEvents, function (x, y) return x.StartTime < y.StartTime end) else allEvents = List.keep_if(allEvents, function (event) return event.StartTime <= now end) end

local now = os.time return table.concat(List.map(allEvents, function (v) if v.kind == 'Lost Lore' and v.isSpoil == '1' then v.kind = 'Lost Lore Spoils' end local banner = v.kind == 'Tempest Trials' and frame:expandTemplate {title = 'Banner TT', args = {bannerName = v.text}} or			frame:expandTemplate {title = 'Banner Event', args = {bannerType = v.kind, fontSize = 4, text1 = v.text, link = v.page}} return tostring(eventEntry(('%s %s'):format(banner, v.page, v.name), args.upcoming and v.StartTime - now or v.EndTime - now)) end)) end

local currentEventsSlideshow = function (args, frame) local eventQueryResult = cargo.query(		'SummoningEvents',		"_pageName=Page,Name,EndTime,EventType", {			where = 'NOW BETWEEN StartTime AND EndTime',			groupBy = '_pageName',			orderBy = 'StartTime DESC',		})

if #eventQueryResult == 0 then return '(no values)' end

local now = os.time local galleryparams = table.concat(List.map(eventQueryResult, function (event) -- Get the banner name from Name field local bannerName = event.Name local eventType = event.EventType if List.any({'New Heroes', 'Double Special Heroes', 'Hero Fest'}, function (v) return v == eventType end) then elseif List.any({'Legendary', 'Mythic', 'Legendary Hero Remix'}, function (v) return v == eventType end) then eventType = 'Legendary Mythic Heroes' elseif eventType == 'Free Summon' then eventType = 'Free Summon Random' elseif eventType == 'Special' then eventType = 'Special Heroes' elseif eventType == 'Weekly Revival' then eventType = 'Revival Summon' else eventType = 'Summoning Focus' end

local timediff = Datetime.from_cargo(event.EndTime) - now

-- Add the banner in the format we need. -- Example format below -- File:Banner Focus Choose Your Legends Top 8 Block B.png|Choose Your Legends Top 8 Block B (Focus)|Choose Your Legends Top 8 Block B return ("File:Banner Focus %s.png|link=%s|%s %s%s%s\n"):format(			mf(mw.ustring.gsub(event.Page, ' %(Focus%)', )),			event.Page, eventType, event.Page, bannerName,			timediff <= 172800 and  or , countdown(timediff), timediff <= 172800 and  or '') end))

return frame:extensionTag('gallery', galleryparams, {mode = 'packed'}) end

return require 'Module:MakeMWModule'.makeMWModule { currentQuests = currentQuests, specialMaps = function (args, frame) if args.looping then return loopingMaps(args, frame) else return maps(args, frame) end end, events = events, focuses = currentEventsSlideshow, }