FANDOM


--  <pre>
--  Module for {{Set list}},
--  to be used like {{#invoke:Set list|main}}.
--  @@@ for ideas.
-------------------
local SetList = {};
 
-----------------
--  Load modules:
-----------------
local getArgs       = require( 'Dev:Arguments' ).getArgs;
local getCardType   = require( 'Module:Card type' ).main;
 
--------------
--  Load data:
--------------
local _D            = {};
local data          = mw.loadData( 'Module:Set list/data' );
local rg_list       = data.rg_list;         --  Region code table.
local region_list   = data.region_list;     --  Region name table.
local ln_list       = data.ln_list;         --  Language code table.
local language_list = data.language_list;   --  Language name table.
local rarity_list   = data.rarity_list;     --  Rarity name table.
local abbr_list     = data.abbr_list;       --  Abbr disable codes table.
 
----------------------
--  Utility functions:
----------------------
--  mw functions:
local split = mw.text.split;
local HTML  = mw.html.create;
 
--  Trim function:
--  Trims white space from front and tail of string.
--  If the input is only white space, returns nil.
local function _trim( s )
    if s and not s:match( '^%s*$' ) then
        return mw.text.trim( s ); -- If not nil nor empty.
    end
end
 
--  Link function:
--  If a string is passed, links it;
--  uses a label, when given.
--  If a table is passed, links every instance of it;
--  uses a table of labels, respectively for each entry, when given.
local function _link( v, ... )
    local labels = type( ... or nil ) == 'table' and ... or  { ... };  --  Make sure it's a table.
    local function __link( v, label )
        return ('[[%s|%s]]'):format( v:gsub( '#', '' ), _trim( label ) or split( v, '%s*%(' )[1] );
    end
    if type( v ) == 'string' then
        return __link( v, labels[1] );
    elseif type( v ) == 'table' then
        local t = {};
        for key, value in ipairs( v ) do
            table.insert( t, __link( value, labels[key] ));
        end
        return t;
    else
        return v; -- @@@ error()
    end
end
 
--  Table count function:
--  Given a table, counts how many valuee it has.
local function _count( t ) -- @@@ error() for wrong type()
    local counter = 0;
    for key, value in pairs( t ) do
        counter = counter + 1;
    end
    return counter;
end
 
local function _error( message, default, category ) -- @@@ input list of categories.
    local err   = HTML( 'div' ):css( 'padding-left', '1.6em' )
                    :tag( 'strong' ):addClass( 'error' ):wikitext( ('Error: %s'):format( message ) ):done()
                :allDone();
    local cat   = ('[[Category:%s]]'):format( category or '((Set list)) transclusion to be checked' );
    table.insert( _D.errors, table.concat( { tostring( err ), cat } ) );
    return default or '';
end
 
-------------------------------
--  Getter/generator functions:
-------------------------------
--  Info function:
--  Handles region/language info and flags.
local function getInfo()
    _D.rg       = _D.args['region'] and _D.args['region']:lower() or _error( 'A «region» is always needed!', 'en' );
    _D.region   = region_list[_D.rg];
    _D.ln       = ln_list[_D.rg];
    _D.language = language_list[_D.ln];
    --  Flags:
    _D.flags    = {};
    _D.flags.qty        = _D.args['qty'] and true;
    _D.flags.noAbbr     = _D.args['abbr'] and abbr_list[_D.args['abbr']:lower()] and true;
    _D.flags.column     = _D.args['col'] and true;
    _D.flags.notEnglish = _D.ln ~= 'en';
    _D.flags.italics    = ((_D.ln == 'ja') or (_D.ln == 'zh') or (_D.ln == 'ko')) and 'normal' or 'italic'; 
end
 
--  Local name function:
--  Returns the localized name.
local function getNameLocal( name )
    if not mw.smw then
        return _error( 'mw.smw module not found' );
    end
    local _page = name:gsub( '#', '' );
    local _query = { ('[[%s]]'):format( _page ), ('?%s name='):format( _D.language ), limit = 1, mainlabel = '-' };
    local query = mw.smw.ask( _query );
    if not query or _count( query ) == 0 or _count( query[1] ) == 0 then
        return;
    end
    return query[1][1];
end
 
--  Name function:
--  Returns two values:
--  The English name; the localized name.
local function getSetName( name )
    local t = split( name, '%s*%(' );
    local _name = _D.args['set'] or _trim( t[3] ) and table.concat( t, ' (', 1, 2 ) or t[1];
    local _nameLocal = _D.flags['notEnglish'] and getNameLocal( _name );
    return _name, _nameLocal;
end
 
--  Quotes function:
--  Wraps a name with quotes.
local function wrapQuotes( name, std )
    if not _trim( name ) then
        return '';  --  Return empty string.
    end
    return (std or (_D.ln ~= 'ja' and _D.ln ~= 'zh')) and table.concat( { '"', name, '"' } )
        or table.concat( { '「', name, '」' } );
end
 
--  Rarity function:
--  Receives a string of rarities.
local function getRarity( s )
    local t = s and split( s, ',' ) or {};
    local rarities = {};
    for _, rarity in ipairs( t ) do
        _rarity = _trim( rarity:lower():gsub( ' rare$', '' ) );
        if _rarity and rarity_list[_rarity] then
            table.insert( rarities, _link( rarity_list[_rarity] ) );
        end
    end
    return table.concat( rarities, '<br />' );
end
 
--  Page header function:
--  Builds page header (HTML).
local function getHeader( setName, setNameLocal )
    local CSS = {
                    {   --  First «span» tag (set name).
                        ['font-size']   = '120%',
                        ['font-weight'] = 'bold',
                        ['font-style']  = 'italic'
                    },
                    {   --  Second «span» tag (local set name).
                        ['font-weight'] ='bold',
                        ['font-style']  = _D.flags['italics']
 
                    }
                };
 
    local header = HTML( 'div' ):css( 'text-align', 'center' )
        :tag( 'span' ):css( CSS[1] )
            :wikitext( _link( setName, (setName:match( '%(2011%)' ) or setName:match( '%(series%)' )) and setName ) )
        :done();
    if _trim( setNameLocal ) then
        header:tag( 'br' ):done()
        :tag( 'span' ):css( CSS[2] )
            :wikitext( setNameLocal )
        :done();
    end
    header:tag( 'br' ):done()
        :wikitext( _D.region )
    :allDone();
 
    return tostring( header );
end
 
--  Categories function:
--  Generates categories.
local function getCategory( ns )
    --  @@@ Make it similar to _link.
    return ('[[Category:%s %s]]'):format( _D.region, ns );
end
 
local function tracking( frameArgs )
    local _parameters = {
        1,
        ['region']  = 'region',
        ['set']     = 'set',
        ['abbr']    = 'abbr',
        ['rarity']  = 'rarity',
        ['qty']     = 'qty',
        ['col']     = 'col'
    }
    for key, value in pairs( frameArgs ) do
       if not( _parameters[key] ) or not( _trim( value ) ) then
           --  There are parameters not being used or used empty.
           return _error( 'Instance of unsupported or empty parameters!' , nil, '((Set list)) transclusion with parameters to be checked' )
        end
    end
    return '';
end
 
-----------------------
--  Set list functions:
-----------------------
--  Header entry function:
--  Builds the section header.
--  Fetches section info.
local function getSetListHeader( entry )
    local _header            = entry:match('header::(.-);')
                            or entry:match('header::(.+)' );
    local _sectionNoAbbr     = entry:match(  'abbr::(.-);')
                            or entry:match(  'abbr::(.+)' );
    local _sectionRarityList = entry:match('rarity::(.-);')
                            or entry:match('rarity::(.+)' );
    local _sectionQty        = entry:match(   'qty::(.-);')
                            or entry:match(   'qty::(.+)' );
    local _sectionColumn     = entry:match(   'col::(.-);')
                            or entry:match(   'col::(.+)' );
    local sectionNoAbbr = _trim( _sectionNoAbbr ) and abbr_list[_trim( _sectionNoAbbr )] and true;
 
    return _trim( _header ), sectionNoAbbr, _sectionRarityList, _sectionQty, _trim( _sectionColumn );
end
 
--  Card entry function:
--  Builds the card row.
local function getSetListCard( entry, sectionNoAbbr, sectionRarityList, sectionQty, sectionColumn )
    --  Intialize vars:
    local _number, _name, _rarityList, _qty;
    local _nameAlt, _nameLocalAlt, _rarityAlt, _typeAlt, _description, _column;
    --  General values (from args or section):
    local noAbbr     = sectionNoAbbr or _D.flags['noAbbr'];
    local rarityList = sectionRarityList or _D.args['rarity'];
    local qty        = (sectionQty or _D.flags['qty']) and (tonumber( sectionQty or _D.args['qty'] ) or 1);
    local column     = sectionColumn or _D.args['col'];
 
    --  Local values:
    --  # Split info:
    local valuesStandard    = split( split( entry, '//' )[1] , ';');
    local valuesAlternate   =        split( entry, '//' )[2];
 
    --  # Deal with standard values:
    if noAbbr then
        _name       = _trim( valuesStandard[1] );
        _rarityList = _trim( valuesStandard[2] );
        _qty        = _trim( valuesStandard[3] );
    else
        _number     = _trim( valuesStandard[1] );
        _name       = _trim( valuesStandard[2] );
        _rarityList = _trim( valuesStandard[3] );
        _qty        = _trim( valuesStandard[4] );
    end
 
    --  # Deal with alternate values:
    if valuesAlternate then
        _nameAlt      = valuesAlternate:match(       'name::(.-);')
                     or valuesAlternate:match(       'name::(.+)' );
        _nameLocalAlt = valuesAlternate:match('name%-local::(.-);')
                     or valuesAlternate:match('name%-local::(.+)' );
        _rarityAlt    = valuesAlternate:match(     'rarity::(.-);')
                     or valuesAlternate:match(     'rarity::(.+)' );
        _typeAlt      = valuesAlternate:match(   'category::(.-);')
                     or valuesAlternate:match(   'category::(.+)' );
        _description  = valuesAlternate:match('description::(.-);')
                     or valuesAlternate:match('description::(.+)' );
        _column       = column and
                        (valuesAlternate:match(table.concat( { column:lower(), '::(.-);' } )) 
                      or valuesAlternate:match(table.concat( { column:lower(), '::(.+)'  } )));
    end
 
    --  Build table row:
    --  # Initialize:
    local row = HTML( 'tr' );
    --  # Card number:
    if not noAbbr then
        row:tag( 'td' ):wikitext( _number and (_number:match( '?' ) and _number or _link( _number )) ):done();
    end
    --  # Card name:
    row:tag( 'td' )
        :wikitext( _trim( table.concat( { _nameAlt or wrapQuotes( _link( _name, (_name or ''):match( 'Token %(' ) and _name ), true ), _description or '' }, ' ' ) ) )
    :done();
    --  # Card local name:
    if _D.flags['notEnglish'] then
        row:tag( 'td' ):attr( 'lang', _D.ln ):wikitext( _nameLocalAlt or _name and wrapQuotes( getNameLocal( _name ) ) ):done();
    end
    --  # Card rarity:
    row:tag( 'td' ):wikitext( _rarityAlt or getRarity( _rarityList or rarityList ) ):done();
    --  # Card type:
    row:tag( 'td' ):wikitext( _typeAlt or _name and getCardType( _name ) ):done();
    --  # Card qty:
    if qty then
        row:tag( 'td' ):wikitext( tonumber( _qty ) or qty or 1 ):done();
    end
    --  # Extra column:
    if column then
        row:tag( 'td' ):wikitext( _column ):done();
    end
    row:allDone();
 
    return tostring( row );
end
 
--  Wrap function.
--  Given HTML table rows,
--  wraps it with «table» tags and builds the table header.
local function wrapTable( header, t, noAbbr, qty, column )
    local noAbbr    = noAbbr or _D.flags['noAbbr'];
    local qty       = qty or _D.flags['qty'];
    local column    = column or _D.flags['column'];
 
    --  Build HTML table:
    --  # Initialize:
    local HTMLtableHeader   = HTML( 'table' ):attr( 'id', header or 'Top_table' ):addClass( 'wikitable' ):addClass( 'sortable' ):addClass( 'card-list' );
    local HTMLtableCaption  = header and HTML( 'caption' ):wikitext( header ):done();
    local HTMLtableRow      = HTML( 'tr' );
    --  # Card number:
    if not noAbbr then
        HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( 'Card number' ):done();
    end
    --  # Card name:
    HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( _D.flags['notEnglish'] and 'English name' or 'Name' ):done();
    --  # Card local name:
    if _D.flags['notEnglish'] then
        HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( table.concat( { _D.language, ' name' } ) ):done();
    end
    --  # Card rarity:
    HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( 'Rarity' ):done();
    --  # Card type:
    HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( 'Category' ):done();
    --  # Card qty:
    if qty then
        HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( 'Qty' ):done();
    end
    --  # Extra column:
    if column then
        HTMLtableRow:tag( 'th' ):attr( 'scope', 'col' ):wikitext( _trim( _D.args['col'] ) ):done();
    end
    HTMLtableRow:done();    --  Close the </tr>.
 
    --  Concat everything:
    local HTMLtable = (header and HTMLtableHeader:node( tostring( HTMLtableCaption ) ) or HTMLtableHeader)
        :node( tostring( HTMLtableRow ) )
        :node( table.concat( t ) )  --  Add the table content (all card rows).
        :allDone();    --  Close table (</table>).
 
    return tostring( HTMLtable );
end
 
--  Main set list function:
--  Designs the card table.
local function getSetList()
    local sections  = _D.args[1] and split( _D.args[1], '!:' ) or _error( 'No list info given!', { ';' } );
    local SetListTable = {};    --  Contains list of processed sections.
    for _, section in ipairs( sections ) do
        local _section;
        local sectionSetListTable = {}; --  Contains list of processed card entries.
        local _header, _sectionNoAbbr, _sectionRarityList, _sectionQty;  --  Store section info, applied to all section entries.
        if not _trim( section ) then
            --  Empty section; skip.
        else
            --  It's a section.
            local entries = split( section, '\n' );
            for index, entry in ipairs( entries ) do
                if not _trim( entry ) then
                    --  Emtpy entry; skip.
                elseif index == 1 and entry:match( 'header::' ) then
                    --  Contains header info.
                    _header, _sectionNoAbbr, _sectionRarityList, _sectionQty, _sectionColumn = getSetListHeader( entry );
                else
                    --  Card info.
                    table.insert( sectionSetListTable, getSetListCard( entry, _sectionNoAbbr, _sectionRarityList, _sectionQty, _sectionColumn ) );
                end
            end
            --  Process table for each section.
            _section = wrapTable( _header, sectionSetListTable, _sectionNoAbbr, _sectionQty, _sectionColumn );
        end
        table.insert( SetListTable, _section );
    end
    return table.concat( SetListTable, '\n' );
end
 
-------------------
--  Main functions:
-------------------
--  Main function:
--  To be called through #invoke.
function SetList.main( frame )
    _D.errors       = {};
    _D.args         = getArgs( frame, { trim = true, removeBlanks = true, parentOnly = true } );
    local PAGENAME  = mw.title.getCurrentTitle().text;     --  {{PAGENAME}}
    local NAMESPACE = mw.title.getCurrentTitle().nsText;   --  {{NAMESPACE}}
 
    getInfo();
    local _setName, _setNameLocal = getSetName( PAGENAME );
    local header    = getHeader( _setName, _setNameLocal );
    local category  = getCategory( NAMESPACE )
    local setList   = getSetList();
    local track     = tracking( frame:getParent().args );
 
    --  Return value:
    local ret = {};
    if _trim( NAMESPACE ) then
        if _count( _D.errors ) > 0 then 
            for key, value in ipairs( _D.errors ) do
                table.insert( ret, value );
            end
        end
        table.insert( ret, header );
        table.insert( ret, category );
        table.insert( ret, setList );
    else
        --  When on the set page.
        return setList;
    end
 
    return table.concat( ret );
end
 
 
return SetList;
--  </pre>

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.