Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Please sign up or log in to edit the wiki.

Module:ItemVariants: Difference between revisions

From the Star Citizen Wiki, the fidelity™ encyclopedia
Content deleted Content added
No edit summary
No edit summary
Tag: Manual revert
 
(25 intermediate revisions by 2 users not shown)
Line 11: Line 11:
local config = mw.loadJsonData( MODULE_NAME .. '/config.json' )
local config = mw.loadJsonData( MODULE_NAME .. '/config.json' )


local TNT = require( 'Module:Translate' ):new()
local i18n = require( 'Module:i18n' ):new()




--- Wrapper function for Module:Translate.translate
--- Wrapper function for Module:i18n.translate
---
---
--- @param key string The translation key
--- @param key string The translation key
--- @return string If the key was not found, the key is returned
--- @param addSuffix boolean|nil Adds a language suffix if config.smw_multilingual_text is true
local function t( key )
--- @return string If the key was not found in the .tab page, the key is returned
local function translate( key, addSuffix, ... )
return i18n:translate( key )
return TNT:translate( MODULE_NAME .. '/i18n.json', config, key, addSuffix, { ... } ) or key
end
end




--- Escape magic characters in Lua for use in regex
--- Remove all occurances of words from string
--- TODO: This should be move upstream to Module:Common
---
---
--- @param inputString string the string to be removed from
--- @param str string string to escape
--- @param wordsToRemove string the string containing the words to remove
--- @return string
--- @return string
local function removeWordsFromString( inputString, wordsToRemove )
local function escapeMagicCharacters( str )
local magicCharacters = { '%', '^', '$', '(', ')', '.', '[', ']', '*', '+', '-', '?' }
-- Split the input string into individual words
for _, magicChar in ipairs( magicCharacters ) do
local words = {}
str = str:gsub( '%' .. magicChar, '%%' .. magicChar )
for word in inputString:gmatch( '%S+' ) do
table.insert( words, word )
end
end
return str
end


--- Find common words between two strings
-- Create a set of words to remove
--- TODO: This should be move upstream to Module:Common
local wordsSet = {}
---
for word in wordsToRemove:gmatch( '%S+' ) do
--- @param str1 string
wordsSet[ word ] = true
--- @param str2 string
--- @return table
local function findCommonWords( str1, str2 )
local words1 = {}
local words2 = {}
local commonWords = {}

-- Split the first string into words and store in a table
for word in str1:gmatch( '%S+' ) do
words1[ word ] = true
end
end


-- Filter out words that need to be removed
-- Split the second string into words and store in a table
for word in str2:gmatch( '%S+' ) do
local cleanedWords = {}
for _, word in ipairs( words ) do
words2[ word ] = true
if not wordsSet[ word ] then
table.insert( cleanedWords, word )
end
end
end


-- Join the cleaned words back into a string
-- Find common words
for word in pairs( words1 ) do
local cleanedString = table.concat( cleanedWords, ' ' )
if words2[ word ] then
table.insert( commonWords, word )
end
end


return cleanedString
return commonWords
end
end




--- Remove all occurances of words from string
--- Creates the object that is used to query the SMW store
---
---
--- @param page string the item page containing data
--- @param str string the string to be removed from
--- @param wordsToRemove table the table of strings containing the words to remove
--- @return table|string
--- @return string
local function makeSmwQueryObject( self, page )
local function removeWords( str, wordsToRemove )
local itemBaseVariantName = translate( 'SMW_ItemBaseVariantName' )
if type( wordsToRemove ) ~= 'table' or next( wordsToRemove ) == nil then
return str
end


-- HACK: Add some space so that the frontier pattern works
local itemBaseVariant = mw.smw.ask {
str = ' ' .. str .. ' '
mw.ustring.format( '[[-%s::%s]]', itemBaseVariantName, page ),
'?#-=name',
'?Page Image#-=image',
limit = 1
}


for i, word in ipairs( wordsToRemove ) do
if type( itemBaseVariant ) ~= 'table' or #itemBaseVariant ~= 1 then
str = string.gsub( str, '%f[%S]' .. escapeMagicCharacters( word ) .. '%f[%s]', '' )
if itemBaseVariant ~= nil then
return ''
-- This is a base variant page
else
itemBaseVariant = mw.smw.ask {
mw.ustring.format( '[[%s]]', page ),
'?#-=name',
'?Page Image#-=image',
limit = 1
}

-- This should not happen but it did
if itemBaseVariant == nil then
return ''
end
end
end
end


return mw.text.trim( str )
mw.logObject( itemBaseVariant, 'itemBaseVariant' )
end


itemBaseVariant = itemBaseVariant[ 1 ]
self.itemBaseVariant = itemBaseVariant


--- Creates the object that is used to query the SMW store
---
--- @param page string the item page containing data
--- @return table|string
local function makeSmwQueryObject( page )
local smwItemBaseVariantName = t( 'SMW_ItemBaseVariantName' )
local smwName = t( 'SMW_Name' )

-- 1. On variant page, select variants of base item
-- 2. On variant page, select base item
-- 3. On base item page, select variants of base item
-- 4. On base item page, select base item
local query = {
local query = {
'[[:+]]',
'[[:+]]',
mw.ustring.format(
string.format(
'<q>[[%s::%s]] || [[%s::%s]] || [[-%s::%s]]</q>',
'[[%s::<q>[[-%s::%s]]</q>]] || [[-%s::%s]] || [[%s::%s]] || [[%s::%s]]',
itemBaseVariant.name,
smwItemBaseVariantName,
smwItemBaseVariantName,
page,
page,
itemBaseVariantName,
smwItemBaseVariantName,
itemBaseVariant.name,
page,
itemBaseVariantName,
smwItemBaseVariantName,
itemBaseVariant.name
page,
smwName,
page
),
),
'[[Category:+]]', -- Filter out subobjects, i.e. select pages having a category. Warning, order matters? Dont put this above the variant query
'?#-=name',
'?Page Image#-=image'
'?#-=page',
'?' .. smwName .. '#-=name',
'?Page Image#-=image',
'sort=',
'order=asc',
}
}


Line 123: Line 136:
end
end


local smwData = mw.smw.ask( makeSmwQueryObject( self, page ) )
local smwData = mw.smw.ask( makeSmwQueryObject( page ) )


if smwData == nil or smwData[ 1 ] == nil then
if smwData == nil or smwData[ 1 ] == nil then
Line 129: Line 142:
end
end


--mw.logObject( smwData, 'getSmwData' )
-- Insert base variant back to the table
table.insert( smwData, 1, self.itemBaseVariant )

mw.logObject( smwData, 'getSmwData' )
self.smwData = smwData
self.smwData = smwData


Line 144: Line 154:


if smwData == nil then
if smwData == nil then
local msg = mw.ustring.format( translate( 'error_no_variants_found' ), self.page )
local msg = string.format( t( 'message_error_no_variants_found' ), self.page )
return require( 'Module:Hatnote' )._hatnote( msg, { icon = 'WikimediaUI-Error.svg' } )
return require( 'Module:Hatnote' )._hatnote( msg, { icon = 'WikimediaUI-Error.svg' } )
end
end


local containerHtml = mw.html.create( 'div' ):addClass( 'template-itemVariants' )
local containerHtml = mw.html.create( 'div' ):addClass( 'template-itemVariants' )
local placeholderImage = 'File:' .. config.placeholder_image

local baseVariantWords = {}

if smwData[ 1 ] and smwData[ 1 ].name and smwData[ 2 ] and smwData[ 2 ].name then
baseVariantWords = findCommonWords( smwData[ 1 ].name, smwData[ 2 ].name )
--mw.logObject( baseVariantWords, 'baseVariantWords' )
end


for i, variant in ipairs( smwData ) do
for i, variant in ipairs( smwData ) do
local displayName = removeWordsFromString( variant.name, self.itemBaseVariant.name )
if variant.name then
-- Sometimes base variant does have a variant name
local displayName = ''

if displayName == '' then
if i == 1 then
if next( baseVariantWords ) ~= nil then
displayName = '(Base)'
displayName = removeWords( variant.name, baseVariantWords )
else
displayName = variant.name
end
end
end


mw.log( displayName, variant.name )
-- Sometimes base variant does have a variant name
if displayName == '' then
if i == 1 and smwData[ 2 ] then
displayName = '(Base)'
else
displayName = variant.name
end
end


--mw.log( displayName, variant.name )
local variantHtml = mw.html.create( 'div' ):addClass( 'template-itemVariant' )


local variantHtml = mw.html.create( 'div' ):addClass( 'template-itemVariant' )
if variant.name == self.page then
variantHtml:addClass( 'template-itemVariant--selected' )
end


if variant.name == mw.title.getCurrentTitle().fullText then
variantHtml:tag( 'div' )
:addClass( 'template-itemVariant-fakelink' )
variantHtml:addClass( 'template-itemVariant--selected' )
end
:wikitext( mw.ustring.format( '[[%s]]', variant.name ) )

variantHtml:tag( 'div' )
:addClass( 'template-itemVariant-image' )
variantHtml:tag( 'div' )
:addClass( 'template-itemVariant-fakelink' )
:wikitext( mw.ustring.format( '[[%s|128px|link=]]', variant.image or config.placeholder_image ) )
:wikitext( string.format( '[[%s|%s]]', variant.page, variant.name ) )
variantHtml:tag( 'div' )
:addClass( 'template-itemVariant-title' )
variantHtml:tag( 'div' )
:wikitext( displayName )
:addClass( 'template-itemVariant-image' )
:wikitext( string.format( '[[%s|160px|link=]]', variant.image or placeholderImage ) )
containerHtml:node( variantHtml )
variantHtml:tag( 'div' )
:addClass( 'template-itemVariant-title' )
:wikitext( displayName )
containerHtml:node( variantHtml )
end
end
end


return tostring( containerHtml ) .. mw.getCurrentFrame():extensionTag {
return mw.getCurrentFrame():extensionTag {
name = 'templatestyles', args = { src = MODULE_NAME .. '/styles.css' }
name = 'templatestyles', args = { src = MODULE_NAME .. '/styles.css' }
} .. tostring( containerHtml )
}
end
end


Line 202: Line 227:
function ItemVariants.outputTable( frame )
function ItemVariants.outputTable( frame )
local args = require( 'Module:Arguments' ).getArgs( frame )
local args = require( 'Module:Arguments' ).getArgs( frame )
local page = args[ 1 ] or mw.title.getCurrentTitle().rootText
local page = args[ 1 ] or mw.title.getCurrentTitle().text


local instance = ItemVariants:new( page )
local instance = ItemVariants:new( page )

Latest revision as of 06:47, 8 November 2024

Module documentation[view][edit][history][purge]
This documentation is transcluded from Module:ItemVariants/doc. Changes can be proposed in the talk page.
Function list
L 20 — t
L 30 — escapeMagicCharacters
L 44 — findCommonWords
L 75 — removeWords
L 95 — makeSmwQueryObject
L 131 — methodtable.getSmwData
L 152 — methodtable.out
L 216 — ItemVariants.new
L 227 — ItemVariants.outputTable
L 241 — ItemVariants.test

require( 'strict' )

local ItemVariants = {}

local metatable = {}
local methodtable = {}

metatable.__index = methodtable

local MODULE_NAME = 'Module:ItemVariants'
local config = mw.loadJsonData( MODULE_NAME .. '/config.json' )

local i18n = require( 'Module:i18n' ):new()


--- Wrapper function for Module:i18n.translate
---
--- @param key string The translation key
--- @return string If the key was not found, the key is returned
local function t( key )
	return i18n:translate( key )
end


--- Escape magic characters in Lua for use in regex
--- TODO: This should be move upstream to Module:Common
---
--- @param str string string to escape
--- @return string
local function escapeMagicCharacters( str )
    local magicCharacters = { '%', '^', '$', '(', ')', '.', '[', ']', '*', '+', '-', '?' }
    for _, magicChar in ipairs( magicCharacters ) do
        str = str:gsub( '%' .. magicChar, '%%' .. magicChar )
    end
    return str
end

--- Find common words between two strings
--- TODO: This should be move upstream to Module:Common
---
--- @param str1 string
--- @param str2 string
--- @return table
local function findCommonWords( str1, str2 )
    local words1 = {}
    local words2 = {}
    local commonWords = {}

    -- Split the first string into words and store in a table
    for word in str1:gmatch( '%S+' ) do
        words1[ word ] = true
    end

    -- Split the second string into words and store in a table
    for word in str2:gmatch( '%S+' ) do
        words2[ word ] = true
    end

    -- Find common words
    for word in pairs( words1 ) do
        if words2[ word ] then
            table.insert( commonWords, word )
        end
    end

    return commonWords
end


--- Remove all occurances of words from string
---
--- @param str string the string to be removed from
--- @param wordsToRemove table the table of strings containing the words to remove
--- @return string
local function removeWords( str, wordsToRemove )
    if type( wordsToRemove ) ~= 'table' or next( wordsToRemove ) == nil then
        return str
    end

    -- HACK: Add some space so that the frontier pattern works
    str = ' ' .. str .. ' '

    for i, word in ipairs( wordsToRemove ) do
        str = string.gsub( str, '%f[%S]' .. escapeMagicCharacters( word ) .. '%f[%s]', '' )
    end

    return mw.text.trim( str )
end


--- Creates the object that is used to query the SMW store
---
--- @param page string the item page containing data
--- @return table|string
local function makeSmwQueryObject( page )
    local smwItemBaseVariantName = t( 'SMW_ItemBaseVariantName' )
    local smwName = t( 'SMW_Name' )

    -- 1. On variant page, select variants of base item
    -- 2. On variant page, select base item
    -- 3. On base item page, select variants of base item
    -- 4. On base item page, select base item
    local query = {
        '[[:+]]',
        string.format(
            '[[%s::<q>[[-%s::%s]]</q>]] || [[-%s::%s]] || [[%s::%s]] || [[%s::%s]]',
            smwItemBaseVariantName,
            smwItemBaseVariantName,
            page,
            smwItemBaseVariantName,
            page,
            smwItemBaseVariantName,
            page,
            smwName,
            page
        ),
        '[[Category:+]]', -- Filter out subobjects, i.e. select pages having a category. Warning, order matters? Dont put this above the variant query
        '?#-=page',
        '?' .. smwName .. '#-=name',
        '?Page Image#-=image',
        'sort=',
        'order=asc',
    }

    return query
end


--- Queries the SMW Store
--- @return table|nil
function methodtable.getSmwData( self, page )
    --mw.logObject( self.smwData, 'cachedSmwData' )
    -- Cache multiple calls
    if self.smwData ~= nil then
        return self.smwData
    end

    local smwData = mw.smw.ask( makeSmwQueryObject( page ) )

    if smwData == nil or smwData[ 1 ] == nil then
        return nil
    end

    --mw.logObject( smwData, 'getSmwData' )
    self.smwData = smwData

    return self.smwData
end

--- Generates wikitext needed for the template
--- @return string
function methodtable.out( self )
    local smwData = self:getSmwData( self.page )

    if smwData == nil then
        local msg = string.format( t( 'message_error_no_variants_found' ), self.page )
        return require( 'Module:Hatnote' )._hatnote( msg, { icon = 'WikimediaUI-Error.svg' } )
    end

    local containerHtml = mw.html.create( 'div' ):addClass( 'template-itemVariants' )
    local placeholderImage = 'File:' .. config.placeholder_image

    local baseVariantWords = {}

    if smwData[ 1 ] and smwData[ 1 ].name and smwData[ 2 ] and smwData[ 2 ].name then
        baseVariantWords = findCommonWords( smwData[ 1 ].name, smwData[ 2 ].name )
        --mw.logObject( baseVariantWords, 'baseVariantWords' )
    end

    for i, variant in ipairs( smwData ) do
        if variant.name then
            local displayName = ''

            if next( baseVariantWords ) ~= nil then
                displayName = removeWords( variant.name, baseVariantWords )
            end

            -- Sometimes base variant does have a variant name
            if displayName == '' then
                if i == 1 and smwData[ 2 ] then
                    displayName = '(Base)'
                else
                    displayName = variant.name
                end
            end

            --mw.log( displayName, variant.name )

            local variantHtml = mw.html.create( 'div' ):addClass( 'template-itemVariant' )

            if variant.name == mw.title.getCurrentTitle().fullText then
                variantHtml:addClass( 'template-itemVariant--selected' )
            end

            variantHtml:tag( 'div' )
                :addClass( 'template-itemVariant-fakelink' )
                :wikitext( string.format( '[[%s|%s]]', variant.page, variant.name ) )
            variantHtml:tag( 'div' )
                :addClass( 'template-itemVariant-image' )
                :wikitext( string.format( '[[%s|160px|link=]]', variant.image or placeholderImage ) )
            variantHtml:tag( 'div' )
                :addClass( 'template-itemVariant-title' )
                :wikitext( displayName )
            containerHtml:node( variantHtml )
        end
    end

    return  mw.getCurrentFrame():extensionTag {
        name = 'templatestyles', args = { src = MODULE_NAME .. '/styles.css' }
    } .. tostring( containerHtml )
end

--- New Instance
---
--- @return table ItemVariants
function ItemVariants.new( self, page )
    local instance = {
        page = page or nil
    }

    setmetatable( instance, metatable )

    return instance
end

--- Parser call for generating the table
function ItemVariants.outputTable( frame )
    local args = require( 'Module:Arguments' ).getArgs( frame )
    local page = args[ 1 ] or mw.title.getCurrentTitle().text

    local instance = ItemVariants:new( page )
    local out = instance:out()

    return out
end

--- For debugging use
---
--- @param page string page name on the wiki
--- @return string
function ItemVariants.test( page )
    local instance = ItemVariants:new( page )
    local out = instance:out()

    return out
end

return ItemVariants