Module:FocusTable

local p = {} local cargo = mw.ext.cargo local Datetime = require 'Module:DatetimeUtil' local Util = require 'Module:Util' local List = require 'Module:ListUtil' local Hash = require 'Module:HashUtil' local escq = require 'Module:EscQ'.main1 local superimposeDiv = require 'Module:Superimpose'.div local memoizer = require 'Module:Memoizer'.memoizer

local memoizeHero = memoizer(function (hero)	return cargo.query('Units', "IFNULL(CONCAT(Name,': ',Title),Name)=name,WeaponType,MoveType", { where = ("'%s' IN (WikiName,_pageName)"):format(escq(hero)), groupBy = 'WikiName', })[1] end)

local cacheAllHeroes = function local cache = Hash.from_ipairs(cargo.query('Units', "WikiName,IFNULL(CONCAT(Name,': ',Title),Name)=name,WeaponType,MoveType", { groupBy = 'WikiName', limit = 1000, }), function (v) return v.WikiName, v end) memoizeHero = function (hero) return cache[hero] end end

-- TODO: use UnitType instead (still needs to be lua-only) local makeHeroIconDiv = function (hero) -- We need to query to get the hero's weapon and move type local heroQuery = memoizeHero(hero) if not heroQuery then return mw.html.create('div'):css('width', '120px'):wikitext( .. hero .. ) end

local heroIconDiv = mw.html.create('div'):css('display', 'inline-block'):css('padding', '5px 0') heroIconDiv:node(superimposeDiv(Util.getHeroIcon(heroQuery.name, '90px'), {, 2, 2},		{, 68, 68}))	heroIconDiv:tag('div'):css('width', '140px'):css('margin', 'auto') :wikitext( .. heroQuery.name .. )

return heroIconDiv end

local makeFocusTable = function (focus, extratitle, extratext) local heroes = List.select(mw.text.split(focus.Units, '%s*;%s*'), function (v) return v ~= '' end)

-- Initialize the table local tbl = mw.html.create('table'):addClass('wikitable'):addClass('default'):css('text-align', 'center'):css('width', '100%')

-- Header - Name of Summoning Focus tbl:tag('tr'):tag('th'):attr('colspan', '3'):tag('b'):wikitext(focus.Name)

-- Image of Summoning Focus Banner and text link to focus page local heroTR = tbl:tag('tr') heroTR:tag('td'):css('text-align', 'center'):css('width', '25%'):attr('rowspan', tostring(extratext and 4 or 3)) :wikitext((' %s'):format( Util.mf(mw.ustring.gsub(focus.Page, ' %(Focus%)', '')), focus.Page, focus.Name))

-- Table Cell w/ Summoning Focus Featured Units Label heroTR:tag('th'):css('width', '10%'):wikitext('Featured units')

-- Table Cell w/ Hero Icons of the Featured Units local heroIconTD = heroTR:tag('td'):css('width', '55%') :tag('div'):css('width', '100%'):css('display', 'flex'):css('justify-content', 'space-around'):css('flex-flow', 'wrap') for _, hero in ipairs(heroes) do		heroIconTD:node(makeHeroIconDiv(hero):css('flex-basis', '16.666666%')) end

-- Start Date of Summoning Focus tbl:tag('tr'):tag('th'):wikitext('Start date'):done :tag('td'):wikitext(focus.DateStart)

-- End Date of Summoning Focus tbl:tag('tr'):tag('th'):wikitext('End date'):done :tag('td'):wikitext(focus.DateEnd)

if extratext then tbl:tag('tr'):tag('th'):wikitext(extratitle):done :tag('td'):wikitext(extratext) end

return tbl end

-- Get countdown text local countdownFunc = function (timediff) if timediff > 172800 then return 'Ends in ' .. math.floor(timediff / 86400) .. ' day(s).' elseif timediff > 86400 then return Ends in ' .. math.floor(timediff / 86400) .. ' day(s). elseif timediff > 3600 then return Ends in ' .. math.floor(timediff / 3600) .. ' hr(s). else return Ends in ' .. math.floor(timediff / 60) .. ' min(s). end end

local currentFocusSlideshow = function (args, frame) local now = os.time -- Cargo queries local focusQueryResult = cargo.query(		'SummoningEvents=SE,SummoningEventFocuses=SEF',		"SE._pageName=Page,SE.Name=Name,DATE(SE.StartTime)=DateStart,DATE(SE.EndTime)=DateEnd,SE.EndTime=EndTime,GROUP_CONCAT(DISTINCT SEF.Unit SEPARATOR ';')=Units", {			join = 'SE.WikiName=SEF.WikiName',			where = ("'%s' BETWEEN SE.StartTime AND SE.EndTime"):format(Datetime.to_cargo(now)),			groupBy = 'SE._pageName',			orderBy = 'StartTime DESC',		})

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

-- Iterate through all the summoning focus results and create Template:Focus tables for them local galleryparams = table.concat(List.map(focusQueryResult, function (focus) -- Get the banner name from Name field local bannerName = focus.Name

local timediff = Datetime.from_cargo(focus.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|%s|%s %s\n"):format(			Util.mf(mw.ustring.gsub(focus.Page, ' %(Focus%)', '')), focus.Page, bannerName, focus.Page, bannerName, countdownFunc(timediff)) end))

return frame:extensionTag('gallery', galleryparams, {mode = 'slideshow', widths = '300px', heights = '300px'}) end

-- for Module:SummoningEvent local table_ = function (args) return tostring(makeFocusTable({ Page = args.page, Name = args.name, DateStart = args.startDate, DateEnd = args.endDate, Units = type(args.heroes) == 'table' and table.concat(args.heroes, ';') or args.heroes, }, args.extratitle, args.extratext)) end

local byName = function (args, frame) local name = args[1] local focus = cargo.query(		'SummoningEvents=SE,SummoningEventFocuses=SEF',		"SE._pageName=Page,SE.Name=Name,DATE(SE.StartTime)=DateStart,DATE(SE.EndTime)=DateEnd,GROUP_CONCAT(DISTINCT SEF.Unit SEPARATOR ';')=Units", {			join = 'SE.WikiName=SEF.WikiName',			where = ("SE.Name='%s'%s"):format(escq(name), args.page and (" AND SE._pageName='%s'"):format(args.page) or ''),			groupBy = 'SE._pageName',			limit = 1,		})[1] if not focus then return require 'Module:Error'.error(('Summoning focus "%s" not found.'):format(name)) end

return tostring(makeFocusTable(focus, args[2], args[3])) end

--Function to create the list of current summoning focus local currentFocusList = function (args) local now = os.time -- Cargo queries local focusQueryResult = cargo.query(		'SummoningEvents=SE,SummoningEventFocuses=SEF',		"SE._pageName=Page,SE.Name=Name,DATE(SE.StartTime)=DateStart,DATE(SE.EndTime)=DateEnd,GROUP_CONCAT(DISTINCT SEF.Unit SEPARATOR ';')=Units", {			join = 'SE.WikiName=SEF.WikiName',			where = ("'%s' BETWEEN SE.StartTime AND SE.EndTime"):format(Datetime.to_cargo(now)),			groupBy = 'SE._pageName',			orderBy = 'StartTime DESC',		})

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

return table.concat(List.map(focusQueryResult, function (focus) return tostring(makeFocusTable(focus)) end)) end

-- Function to create the list of previous summoning focus local archiveFocusList = function (args) cacheAllHeroes

-- Cargo queries local focusQueryResult = List.group_by(cargo.query( 'SummoningEvents=SE,SummoningEventFocuses=SEF', "SE._pageName=Page,SE.Name=Name,DATE(SE.StartTime)=DateStart,DATE(SE.EndTime)=DateEnd,GROUP_CONCAT(DISTINCT SEF.Unit SEPARATOR ';')=Units", { join = 'SE.WikiName=SEF.WikiName', groupBy = 'SE._pageName', orderBy = 'StartTime DESC', limit = 1000, }), function (v) return mw.ustring.match(v.DateStart, '^%d+%-%d+') end)

Hash.map_self(focusQueryResult, function (focuses, ym)		-- focuses is already sorted by StartTime DESC		List.map_self(focuses, function (focus) return tostring(makeFocusTable(focus)) end)		local year, month = mw.ustring.match(ym, '(%d+)%-(%d+)')		return (' %s %s'):format(os.date('%B %Y', os.time {year = year, month = month, day = 1}), table.concat(focuses))	end)

local ordered = {} for ym, v in Hash.sorted_pairs(focusQueryResult) do		ordered[#ordered + 1] = v	end List.reverse_self(ordered) return table.concat(ordered, ' ') end

return (require "Module:Deprecated").module(require 'Module:MakeMWModule'.makeMWModule {	cacheAllHeroes = cacheAllHeroes,	currentFocusSlideshow = currentFocusSlideshow,	table = table_,	byName = byName,	currentFocusList = currentFocusList,	archiveFocusList = archiveFocusList, }, "Module:FocusTable")