Module:LoU/dev

-- 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  = 'pl' local ytUserFmt = 'yt' local ytUcFmt  = 'yt' local sbUserFmt = 'sb' local sbUcFmt  = 'sb' local statusTbl = { ['a'] = ' Active ', ['h'] = ' Hiatus ', ['d'] = ' Dormant ', ['r'] = ' Retired ', ['s'] = ' Suicide ', ['t'] = ' Terminated ', ['x'] = ' Resurrected ', ['na']= ' Not Unterganger? ',   ['a?']= ' Active (?) ', ['h?']= ' Hiatus (?) ', ['d?']= ' Dormant (?) ', ['r?']= ' Retired (?) ', ['s?']= ' Suicide (?) ', ['t?']= ' Terminated (?) ', ['x?']= ' Resurrected (?) ', } -- 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','reg','ctry','vids','views','subs','sbgrade','status','yt','note'} -- column definition -- direct text: head, class -- property names: text, title, sortkey local colDef = { {head="#", class="index unsortable"}, {head="Name", class="name", text="namenote"}, {head="Reg", class="region", text="reg", title="regTitle"}, {head="Ctry", class="country", 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", text="sbgrade", sortkey="sbkey"}, {head="Status", class="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 --[=[ 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 "") :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 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 mw.log('found empty field') 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

function p.main(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 -- 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) --deriving values from the variables name and note if not empty(t.note) then t.namenote = t.name ..' ('.. t.note ..') ' 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 --else --t.countryName = "" --t.region = "" --t.subregion = "" --t.flag = "" end -- numbers t.vids = formatNumCol(t.vids) t.views = formatNumCol(t.views) t.subs = formatNumCol(t.subs) -- status and grade t.status = statusTbl[t.status] or t.status t.sbkey = sbSortKey[t.sbgrade] or 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.ytlink = mw.ustring.format(ytPlFmt, t.pl) t.sblink = '' 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.ytlink = mw.ustring.format(ytUcFmt, t.yt) t.sblink = mw.ustring.format(sbUcFmt, t.yt) elseif not empty(t.yt) then -- old username t.ytlink = mw.ustring.format(ytUserFmt, t.yt) t.sblink = mw.ustring.format(sbUserFmt, t.yt) else -- absent t.ytlink = '' t.sblink = '' end t.links = t.ytlink..' '..t.sblink -- 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