Modul:WeaponPersonal

Aus Steel Beasts Wiki
Version vom 24. Juni 2023, 17:21 Uhr von sc>FoXFTW
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Die Dokumentation für dieses Modul kann unter Modul:WeaponPersonal/Doku erstellt werden

require( 'strict' )

local WeaponPersonal = {}

local metatable = {}
local methodtable = {}

metatable.__index = methodtable

-- Extensions
local infobox = require( 'Module:InfoboxNeue' )
local manufacturer = require( 'Module:Hersteller' )
local common = require( 'Module:Common' )
local api = require( 'Module:Common/Api' )
local TNT = require( 'Module:Translate' ):new()
local localized = require( 'Module:Localized' )
local item = require( 'Module:Item' )
local commodity = require( 'Module:Commodity' )
local data = mw.loadData( 'Module:WeaponPersonal/Data' )


--- @param class string
--- @return string
local function translateClass( class )
    return {
        de_DE = ( data.classTranslations[ class ] or class ),
        en_EN = class,
    }
end


--- @param type string
--- @return string
local function translateType( type )
    return {
        de_DE = ( data.typeTranslations[ type ] or type ),
        en_EN = type,
    }
end


--- @param magazine string
--- @return string
local function translateMagazine( magazine )
	if magazine == nil or #magazine == 0 then
		return nil
	end

    return {
        de_DE = ( data.magazineTranslations[ magazine ] or magazine ),
        en_EN = magazine,
    }
end


--- Add manual smw data
function methodtable.addManual( self )
    if self.frameArgs == nil then
        return
    end

    local function addLangCode( key )
        if self.frameArgs[ key ] ~= nil then
            return self.frameArgs[ key ] .. '@de'
        end

        return nil
    end

    local setObj = {
        [ 'Name' ]                 = self.frameArgs[ 'Name' ]                 or nil,
        [ 'Größe' ]                = self.frameArgs[ 'Gewicht' ]              or nil,
        [ 'Hersteller' ]           = self.frameArgs[ 'Hersteller' ]           or nil,
        [ 'Beschreibung' ]         = addLangCode( 'Beschreibung' ),
        [ 'Waffentyp' ]            = self.frameArgs[ 'Waffentyp' ]            or nil,
        [ 'Waffenklasse' ]         = self.frameArgs[ 'Waffenklasse' ]         or nil,
        [ 'Magazingröße' ]         = self.frameArgs[ 'Magazingröße' ]         or nil,
        [ 'Effektive Reichweite' ] = self.frameArgs[ 'Effektive Reichweite' ] or nil,
        [ 'Feuerrate' ]            = self.frameArgs[ 'Feuerrate' ]            or nil,
        [ 'Spielversion' ]         = self.frameArgs[ 'Spielversion' ]         or nil,
    }

    mw.smw.set( setObj )
end


--- Request Api Data
--- Using current subpage name
--- @return table
function methodtable.getApiDataForCurrentPage( self )
    local name = self.frameArgs[ 'name' ] or mw.title.getCurrentTitle().subpageText

    local json = mw.text.jsonDecode( mw.ext.Apiunto.get_raw( 'v2/weapons/' .. name, {
        include = {
            'shops.items',
        }
    } ) )

    api.checkResponseStructure( json, true, false )

    self.apiData = json[ 'data' ]

    return self.apiData
end


--- Queries the SMW Store
--- @return table
function methodtable.getSmwData( self )
    -- Cache multiple calls
    if self.smwData ~= nil then
        return self.smwData
    end

    -- name from args or current page
    local queryName = self.frameArgs[ 'name' ] or localized.getMainTitle()

    local data = mw.smw.ask( {
        '[[' .. queryName .. ']]',
        '?#-=page',
        '?Name#-=name',
        '?Größe#-=size',
        '?Hersteller#-=manufacturer',
        '?Beschreibung=description', '+lang=' .. common.getLocaleForPage(),
        '?Waffentyp=type', '+lang=' .. common.getLocaleForPage(),
        '?Waffentyp=type_de', '+lang=de',
        '?Waffenklasse=class', '+lang=' .. common.getLocaleForPage(),
        '?Waffenklasse=class_de', '+lang=de',
        '?Magazingröße#-=magazine_size',
        '?Magazintyp=magazine_type', '+lang=' .. common.getLocaleForPage(),
        '?Magazintyp=magazine_type_de', '+lang=de',
        '?Effektive Reichweite#-=range',
        '?Schaden pro Schuss#-=dps',
        '?Feuerrate#-=rof',
        '?Länge=length',
        '?Breite=width',
        '?Höhe=height',
        '?Volumen=volume',
        '?Spielversion#-=version',
        'mainlabel=-'
    } )

    if data == nil or data[ 1 ] == nil then
        error( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'msg_no_data', queryName ), 0 )
    end

    self.smwData = data[ 1 ]

    local weaponSubobjects = require( 'Module:WeaponSubobjects' ):new()

    self.smwData.modes = weaponSubobjects:getWeaponModes( queryName )
    self.smwData.defaultAttachments = weaponSubobjects:getDefaultAttachments( queryName )
    self.smwData.attachmentPorts = weaponSubobjects:getAttachmentPorts( queryName )
    self.smwData.damages = weaponSubobjects:getDamages( queryName )
    self.smwData.ammunition = weaponSubobjects:getAmmunition( queryName )

    self.smwData.price = commodity.getPrice( queryName )
    if self.smwData.price ~= nil then
        self.smwData.price = self.smwData.price[ 1 ].price
    end

    return self.smwData
end


--- Base Properties that are shared across all Vehicles
--- @return table SMW Result
function methodtable.setSemanticProperties( self )
    -- Api Error, don't set anything
    if self.apiData == nil or mw.title.getCurrentTitle().isSubpage then
        return
    end

    local rof = nil
    if self.apiData.personal_weapon ~= nil then
    	rof = self.apiData.personal_weapon.rof
	    if rof ~= nil then
	    	rof = mw.text.split( rof, ' ', true )[ 1 ] or nil
	    	rof = string.gsub( rof, ',', '' )
	    end
	end

	local item = item:new( '', self.apiData )
    --- The base data for the page
    local setData = item:makeSmwObject()

    if type( self.apiData.personal_weapon ) == 'table' then
        setData[ 'Waffentyp' ]            = api.mapTranslation( translateType( self.apiData.personal_weapon.type or nil ) )
        setData[ 'Waffenklasse' ]         = api.mapTranslation( translateClass( self.apiData.personal_weapon.class or nil ) )
        setData[ 'Magazingröße' ]         = self.apiData.personal_weapon.magazine_size or nil
        setData[ 'Magazintyp' ]           = api.mapTranslation( translateMagazine( self.apiData.personal_weapon.magazine_type or nil ) )
        setData[ 'Effektive Reichweite' ] = self.apiData.personal_weapon.effective_range or nil
        setData[ 'Schaden pro Schuss' ]   = common.formatNum( self.apiData.personal_weapon.damage_per_shot, nil )
        setData[ 'Feuerrate' ]            = common.formatNum( rof, nil )
	end

    local result = mw.smw.set( setData )

    local weaponSubobjects = require( 'Module:WeaponSubobjects' ):new()
    weaponSubobjects:setSemanticProperties( self.apiData )

    commodity:new():addShopData( self.apiData )

    return result
end


--- Sets the main categories for this object
function methodtable.setCategories( self, smwData )
	if smwData.manufacturer == nil then
		table.insert( self.categories, '[[Category:Seiten mit Skriptfehlern]]' )
		return
	end

	if self.lang == 'de' then
	    table.insert( self.categories, '[[Category:' .. smwData.manufacturer .. '|' .. smwData.name .. ' ]]' )
	
	    if smwData.type ~= nil then
	        table.insert( self.categories, '[[Category:' .. smwData.type_de .. '|' .. smwData.name .. ' ]]' )
	    end
    else
    	table.insert( self.categories, '[[Category:' .. smwData.name ..'|' .. smwData.name .. ' ]]' )
    end
end


--- Entrypoint for {{#seo:}}
function methodtable.setSeoData( self )
    if self.currentFrame == nil then
        error( 'No frame set. Call "setFrame" first.', 0 )
    end

    local data = self:getSmwData()

    if nil == data.manufacturer then
        -- Faulty SMW data, don't call #seo
        return
    end

    require( 'Module:SEO' ).set(
        TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'seo_section' ),
        data.page,
        table.concat({
            data.name,
            data.manufacturer,
            self.currentFrame:preprocess( '{{SITENAME}}' )
        }, ' - '),
        'replace',
        {
            data.name or '',
            data.type or '',
            data.class or '',
            data.manufacturer or '',
            manufacturer.getCodeFromName( data.manufacturer ) or '',
        },
        nil,
        self.frameArgs[ 'image' ],
        data.page
    )
end


--- Creates the infobox
--- TODO: This is a mess ;_;
function methodtable.getInfoBox( self )
    local data = self:getSmwData()

    if nil == data.manufacturer then
        return TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'msg_smw_loading' )
    end

    -- Set Title
    common.setDisplayTitle( self.currentFrame, data.name )

    local box = infobox:new( {
        removeEmpty = true,
        emptyString = '-',
        placeholderImage = 'Platzhalter Waffen.webp',
    } )

	local cleanedImageName = string.gsub( data.name or '', '"', '' )
    -- Image
    box:renderImage( common.getImage( {
        self.frameArgs[ 'image' ],
        cleanedImageName
    } ) )

    box:renderHeader( {
    	title = data.name,
    	subtitle = '[[' .. data.manufacturer .. ']]' .. api.getVersionInfoRef( data.version, self.lang )
    } )

    local weaponType = data.type
    if weaponType ~= nil then
        weaponType = string.format('[[:Kategorie:%s|%s]]', data.type_de, weaponType)
    end

    local weaponClass = data.class
    if weaponClass ~= nil then
        weaponClass = string.format('[[:Kategorie:%s|%s]]', data.class_de, weaponClass)
    end

    local maxRange = '-'
    local muzzleVelocity = '-'
    if type( data.ammunition ) == 'table' then
        maxRange = data.ammunition[ 1 ][ 'Maximalreichweite' ]
        muzzleVelocity = data.ammunition[ 1 ][ 'Mündungsgeschwindigkeit' ]
    end
    
    local section = {}

    table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_type' ), weaponType ) )
	table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_class' ), weaponClass ) )
	table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_price' ), data.price or TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'txt_cant_buy' ) ) )

    if data.magazine_size ~= nil then
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_magazine_size' ), data.magazine_size .. ' ' .. TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_shots' ) ) )
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_dps' ), data.dps ) )
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_magazine_type' ), data.magazine_type ) )
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_rof' ), ( data.rof or '-' ) .. ' ' .. TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_shot_s' ) ) )
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_muzzle_velocity' ), muzzleVelocity ) )
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_effective_range' ), data.range ) )
	       table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_max_range' ), maxRange ) )
    end

	table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_weight' ), data.volume or '-' ) )

	box:renderSection( {
		col = 2,
		content = section,
	} )

    --[[
        Weapon Modes
    ]]--
    if data.modes ~= nil and type( data.modes ) == 'table' then
    	section = {}

        for _, mode in pairs( data.modes ) do
            local dps = mode.dps or nil
            if dps ~= nil then
                dps = string.format("%.2f", dps)
            else
                dps = ' - '
            end

            table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_mode' ), mode.name ) )
            table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_rof' ), (mode.rof or ' - ') .. ' ' .. TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_shot_s' ) ) )
            table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_dps' ), dps ) )
        end
        
        box:renderSection( {
        	title = TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_fire_modes' ),
        	col = 3,
        	content = section
        } )
    end

    --[[
        Weapon Attachments
    ]]--
    if data.attachmentPorts ~= nil and type( data.attachmentPorts ) == 'table' then
    	section = {}

        for _, attachment in pairs( data.attachmentPorts ) do
            if type( attachment ) == 'table' and attachment.position_de ~= 'Magazin' then
                table.insert( section, box:renderItem( attachment.position, 'S' .. attachment.min_size ) )
            end
        end
        
        box:renderSection( {
        	title = TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_attachments' ),
        	col = 3,
        	content = section
        } )
    end

    --[[
        Weapon Default Loadout
    ]]--
    if data.defaultAttachments ~= nil and type( data.defaultAttachments ) == 'table' then
    	section = {}

        for _, attachment in pairs( data.defaultAttachments ) do
            if type( attachment ) == 'table' and attachment.name ~= nil then
                local size = attachment.size
                if size ~= nil and tonumber( size ) > 0 then
                    size = 'S' .. size .. ' '
                end

                table.insert( section, box:renderItem( attachment.position, size .. string.format( '[[%s]]', attachment.name ) ) )
            end
        end
        
        box:renderSection( {
        	title = TNT.formatInLanguage( self.lang, 'Module:WeaponPersonal/i18n.json', 'lbl_standard_equipment' ),
        	content = section
        } )
    end

    return tostring( box ) .. tostring( common.generateInterWikiLinks( data.name ) )
end


--- Set the frame and load args
--- @param frame table
function methodtable.setFrame( self, frame )
    self.currentFrame = frame
    self.frameArgs = require( 'Module:Arguments' ).getArgs( frame )

    if type( self.frameArgs[ 'Bild' ] ) == 'string' then
    	self.frameArgs[ 'image' ] = self.frameArgs[ 'Bild' ]
	end
end


--- Get categories
function methodtable.getCategories( self )
    return tostring( table.concat( self.categories ) )
end


--- Save Api Data to SMW store
function methodtable.saveApiData( self )
    if self.currentFrame == nil then
        error( 'No frame set. Call "setFrame" first.', 0 )
    end

    local data = self:getApiDataForCurrentPage()

	self:setSemanticProperties()

    return data
end


--- Template entry
function WeaponPersonal.main( frame )
    local instance = WeaponPersonal:new()
    instance:setFrame( frame )

	if not localized.isLanguagePage() then
	    if instance.frameArgs[ 'Manuell' ] ~= nil then
	        instance:addManual()
	    else
	        instance:saveApiData()
	    end
    end

    instance:setCategories( instance:getSmwData() )

    instance:setSeoData()

    return tostring( instance:getInfoBox() ) .. instance:getCategories()
end


--- New Instance
function WeaponPersonal.new( self )
    local instance = {
        categories = {},
        lang = require( 'Module:Template translation' )._getLanguageSubpage( mw.title.getCurrentTitle() )
    }

    setmetatable( instance, metatable )

    return instance
end


return WeaponPersonal