FANDOM


--[[ LoU - List of Untergangers lua module 
     to improve parsing speed of the List of Untergangers page
     by mfaizsyahmi, 2017
  ]]
local libCtry = require("Dev:Country")
local libFlag = require("Module:iconflags")
local lang = mw.language.new("en")
local p = {}
 
-- constants
local ytPlFmt   = '[https://www.youtube.com/playlist?list=%s pl]'
local ytUserFmt = '[https://www.youtube.com/user/%s yt]'
local ytUcFmt   = '[https://www.youtube.com/channel/%s yt]'
local sbUserFmt = '[https://socialblade.com/youtube/user/%s sb]'
local sbUcFmt   = '[https://socialblade.com/youtube/channel/%s sb]'
local statusTbl = {
	['~'] = 'TBD',
    ['a'] = 'Active',
	['p'] = 'Suspended',
    ['s'] = 'Suicide',
    ['t'] = 'Terminated',
    ['h'] = 'Hiatus',
    ['d'] = 'Dormant',
    ['r'] = 'Retired',
	['x'] = 'Deserted',
    ['c'] = '(Resurrected)',
	['n'] = 'Not Unterganger?'
}
-- changed to numbers so that table sorting work
local sbSortKey = {
    ['A+'] = 100,
    ['A' ] = 110,
    ['A-'] = 120,
    ['B+'] = 200,
    ['B' ] = 210,
    ['B-'] = 220,
    ['C+'] = 300,
    ['C' ] = 310,
    ['C-'] = 320,
    ['D+'] = 400,
    ['D' ] = 410,
    ['D-'] = 420,
    ['TBD']= 900
}
-- maps field position to variable
local colMap = {'name', 'gen', 'reg', 'ctry', 'vids', 'views', 'subs', 'sbgrade', 'status', 'yt', 'note'}
 
-- column definition
   -- direct text: head, class
   -- property names: classvar, text, title, sortkey
local colDef = {
    {head="#", class="index unsortable"},
    {head="Name", class="name", text="namenote"},
	{head="Gen", class="gen", classvar="gen", title="gen"},
    {head="Reg", class="region reg", text="reg", title="regTitle"},
    {head="Ctry", class="country ctry", classvar="ctry", text="ctryText", title="countryName"},
    {head="Vids", class="vids", text="vids"},
    --{head="Views", class="views", text="views"},
    --{head="Subs", class="subs", text="subs"},
    {head="SB", class="sbgrade sb", classvar="sbgrade", text="sbgrade", sortkey="sbkey"},
    {head="Status", class="status", classvar="status", text="status"},
    {head="Links", class="links", text="links"}
    --{head="Links", class="yt", text="ytlink"}
}
 
-- shorthands
local function trim(str) return mw.text.trim(str) end
 
-- if string has parsable number, formats it, otherwise just return
----for vids, views and subs col, which sometimes has "N/A"
local function formatNumCol(str)
    local n = tonumber(str)
    if n ~= nil then
        return lang:formatNum(n)
    else
        return str
    end
end
 
local function empty(a)
	return a==nil or a==""
end
function p.empty(a) return empty(a) end
 
local function readRecordPage(pgName, pgNS, RS, FS, colMap, shift, pop)
    local dataPage = mw.title.new(pgName,pgNS)
    local dataStr = dataPage:getContent()
    -- rmv newlines
    dataStr = mw.ustring.gsub(dataStr,'\n', '')
 
    local recordTbl={}
    for recordStr in mw.ustring.gmatch(dataStr, "([^"..RS.."]+)") do
        -- dropped split method because we want to map the vars immediately
        -- split record fields manually
        local fieldTbl = {}
        local j=1
        --for fieldStr in mw.ustring.gmatch(recordStr, "([^"..FS.."]*)") do
        -- have to use gsplit to get empty fields (those actually exists!)
        for fieldStr in mw.text.gsplit(recordStr, FS) do
            if empty(fieldStr) then --debug
                mw.log('found empty field in'..recordStr) 
            end
            -- try and match key=value pair
            local fn = mw.ustring.gmatch(fieldStr, '[^=]+')
            local s1, s2 = fn(), fn()
            if s2 ~= nil then -- k/v match found
                fieldTbl[trim(s1)] = trim(s2)
            elseif colMap~= nil then --unnamed but mappable value
                fieldTbl[colMap[j]] = trim(fieldStr)
            else -- unnamed value
                fieldTbl[j] = trim(fieldStr)
            end
            j = j + 1
        end
        table.insert(recordTbl, fieldTbl)
    end
    if shift == true then table.remove(recordTbl,1) end
    if pop == true then table.remove(recordTbl) end
    return recordTbl
end
 
-- sorts the record by property prop
-- if map is given will match prop with value of map
-- def is default for missing prop in records
function recordSort(tbl, prop, map, def)
	--set defaults
	if prop=='sbgrade' and empty(def) then def=1000 end
 
	if empty(prop) then 
		return tbl
	elseif type(map)=='table' then
		table.sort(tbl, function(a,b)
			return (map[a[prop]] or def) > (map[b[prop]] or def)
		end)
	else
		table.sort(tbl, function(a,b)
			return a[prop] > b[prop]
		end)
	end
end
 
--[=[ 
Table row builder 
el: the table element
map: the column definition table
tbl: table containing properties to map
header: if not nil build the headers
--]=]
local function buildTableRow(el, map, tbl, header)
    -- create the row builder
    local row= mw.html.create('tr')
    if empty(header) and not empty(tbl.noajax) then
        row:addClass('noAJAX')
    end
    local cellTag = 'td'
    if not empty(header) then cellTag = 'th' end
 
    -- go through every item in the column map
    -- attr: the individual map item
    for i, attr in pairs(map) do
        -- the cell text
        -- pulls from tbl variable as defined in attr.text
        local text = tbl[attr.text] or ""
        -- if building header take the header instead
        if not empty(header)  then text = attr.head end
        -- create cell builder; apply text, class, title
        local cell = mw.html.create(cellTag)
        cell:wikitext(text)
            :attr("class", (attr.class or "")..' '..(tbl[attr.classvar] or "") )
            :attr("title", tbl[attr.title] or "")
        if not empty(attr.sortkey) then
            cell:attr("data-sort-value", tbl[attr.sortkey] or "")
        end
        -- append cell to row
        row:node(cell)
    end
    -- append row to el
    el:node(row)
end
 
function p.main(frame)
    -- retrieve arguments
    local fArgs = frame.args--.getParent()
    local LoUNS = fArgs.ns or 0
    local LoUPage = fArgs.name or "List of Untergangers/data"
    local RS = fArgs.rs or "§" -- record separator
    local FS = fArgs.fs or "‖" -- field separator
 
    -- read the record file and extract record table
    local recordTbl = readRecordPage(LoUPage,LoUNS,RS,FS,colMap,true,true)
 
    -- create the table builder
    local tableEl = mw.html.create('table')
    tableEl:attr("class", "wikitable sortable fullwidth hilight untergangers floatheader")
    -- build the header
    buildTableRow(tableEl, colDef, {}, true)
 
    -- iterate each record to build the table entry rows
    --for _, record in pairs(recordTbl) do
    for _, t in pairs(recordTbl) do
        -- extract record fields into table
        --[[now that we mapped arrays to vars in readRecordPage the whole
            block below is skipped. hopefully this would speed up parsing.]]
        --[[local t = {
            name = record.name or record[1] or "",
            reg  = record.reg or record[2] or "",
            ctry = trim(record.ctry or record[3] or ""),
            vids = record.vids or record[4] or "",
            views= record.views or record[5] or "",
            subs = record.subs or record[6] or "",
            sbgrade = trim(record.rank or record[7] or ""),
            status = record.status or record[8] or "",
            yt = record.yt or record[9] or "",
            pl = record.pl or "",
            noajax = record.noAjax or "",
            note = record.note or record[10] or "",
            -- initialize other vars
            namenote = "",
            regTitle = "",
            ctryText = "",
            sbkey = "",
            ytlink = "",
            sblink = "",
            links  = ""
        }
        ]]
        --mw.log(t.name)
		local expandedStatus = {}
 
        --deriving values from the variables
        ----name and note
        if not empty(t.note) then
            t.namenote = t.name ..' <small>('.. t.note ..')</small>'
        else
            t.namenote = t.name
        end
 
        ----country and region
        t.ctry = t.ctry or '' --fix nil
        t.countryCode = mw.ustring.lower(t.ctry)
        ----HPW accepts uk as synonym for gb
        if t.countryCode == 'uk' then t.countryCode = 'gb' end
 
        if not empty(t.countryCode) then
            --mw.log(libCtry.main{t.countryCode,'name'})
            t.countryName = libCtry.main{t.countryCode,'name'}
            t.region = libCtry.main{t.countryCode,'region'}
            t.subregion = libCtry.main{t.countryCode,'sub-region'}
            t.flag = libFlag.flag{t.countryCode, useemoji='om'}
            if empty(t.reg) then
                t.reg = ".."
            end
            ----the title for region cell
            t.regTitle = t.region .." – ".. t.subregion
            ----text for ctry cell
            t.ctryText = t.flag .. t.ctry
        end
 
        -- numbers
        t.vids = formatNumCol(t.vids)
        t.views = formatNumCol(t.views)
        t.subs = formatNumCol(t.subs)
 
        -- status and grade
		--t.status = t.status or ""
		if not empty(t.status) and #t.status <=3 then
			t.status:gsub(".", function(c)
				    table.insert(expandedStatus, statusTbl[c] or "?")
				end
			)
			--t.status = mw.text.listToText(expandedStatus)
			t.status = table.concat(expandedStatus, ", ")
		end
        --t.status = statusTbl[t.status] or t.status
        t.sbkey = sbSortKey[t.sbgrade] or 1000 --defaults to 1000
 
        -- yt link
        t.yt = t.yt or '' -- fix nil
        -- tilde means take the name argument
        if t.yt == '~' then
            _, _, t.yt = mw.ustring.find(t.name,'%[?%[?([^%]]*)%]?%]?')
        end
        if not empty(t.pl) then -- playlist defined
            t.links = mw.ustring.format(ytPlFmt, t.pl)
        elseif mw.ustring.len(t.yt)==24 
            and mw.ustring.sub(t.yt,1,2)=='UC' then
            -- yt matches channel ID (string of 24 char length begin w/ UC)
            t.links = mw.ustring.format(ytUcFmt, t.yt) ..' ' 
                      ..mw.ustring.format(sbUcFmt, t.yt)
        elseif not empty(t.yt) then -- old username
            t.links = mw.ustring.format(ytUserFmt, t.yt) ..' '
                      ..mw.ustring.format(sbUserFmt, t.yt)
        else -- absent
            --t.links = ''
        end
 
        -- finally build the row given the table of variables
        buildTableRow(tableEl, colDef, t)
    end
 
    -- return the text returned by the html builder
    return tableEl:done()
end
 
--WIP
function p.item(frame)
    -- retrieve arguments
    local fArgs = frame.args--.getParent()
    local LoUNS = fArgs.ns or "User"
    local LoUPage = fArgs.name or "Mfaizsyahmi/testdata"
    local RS = fArgs.rs or "§" -- record separator
    local FS = fArgs.fs or "‖" -- field separator
    local dataPage = mw.title.new(LoUPage,LoUNS)
    local dataStr = dataPage:getContent()
    dataStr = mw.ustring.gsub(dataStr,'\n', '')
 
end
 
return p

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.