Modul:Item

Aus Steel Beasts Wiki
Version vom 3. September 2023, 08:02 Uhr von Dr.Thodt (Diskussion | Beiträge) (1 Version importiert)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

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

local Item = {}

local metatable = {}
local methodtable = {}

metatable.__index = methodtable

-- Extensions
local common = require( 'Module:Common' )
local api = require( 'Module:Common/Api' )
local localized = require( 'Module:Localized' )
local TNT = require( 'Module:Translate' ):new()
local log = require( 'Module:Log' )
local commodity = require( 'Module:Commodity' )
local componentData = mw.loadData( 'Module:VehicleComponent/Data' )


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

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

    local success, message = pcall( api.checkResponseStructure, json, true, true )

    if not success then
        return log:error( message )
    end

    self.apiData = json[ 'data' ]
    api.makeAccessSafe( self.apiData )

    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 .. ']][[Hersteller::+]]',
        '?#-=page',
        '?Name#-',
        '?Größe=size',

        '?Hersteller#-',
        '?Beschreibung', '+lang=' .. common.getLocaleForPage(),
        '?SP',
        '?Länge',
        '?Breite',
        '?Höhe',
        '?Volumen',

        '?Grad=grade',
        '?Typ=type', '+lang=' .. common.getLocaleForPage(),
        '?Typ=type_de', '+lang=de',
        '?Klasse=class', '+lang=' .. common.getLocaleForPage(),
        '?Klasse=class_de', '+lang=de',

        '?Infrarotstrahlung#-=ir',
        '?Elektromagnetische Strahlung#-=em',

        '?Spielversion#-=version',
        'mainlabel=-'
    } )

    if data == nil or data[ 1 ] == nil then
        return TNT.formatInLanguage( self.lang, 'Item', 'msg_smw_loading' )
    end

    self.smwData = data[ 1 ]

    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


--- Creates a base item object settable to SMW
--- @return table|nil
function methodtable.makeSmwObject( self )
    -- Api Error, don't set anything
    if self.apiData == nil then
        return nil
    end

    api.makeAccessSafe( self.apiData )

    -- Base data found on any v2/items/* output
    local setObj = {
        [ 'UUID' ]         = self.apiData.uuid,
        [ 'Name' ]         = self.apiData.name,
        [ 'Beschreibung' ] = api.mapTranslation( self.apiData.description ),
        [ 'Größe' ]        = self.apiData.size,
        [ 'Hersteller' ]   = api.getManufacturerName( self.apiData ),
        [ 'SP' ]           = api.getFormattedCarryingCapacity( self.apiData ),
        [ 'Länge' ]        = common.formatNum( self.apiData:get( 'dimension.length' ), nil ),
        [ 'Breite' ]       = common.formatNum( self.apiData:get( 'dimension.width' ), nil ),
        [ 'Höhe' ]         = common.formatNum( self.apiData:get( 'dimension.height' ), nil ),
        [ 'Volumen' ]      = common.formatNum( api.getVolume( self.apiData ) or nil, nil ),
        [ 'Spielversion' ] = self.apiData.version,
    }

    self:setHeatData( setObj )
    self:setPowerData( setObj )
    self:setDistortionData( setObj )
    self:setDurabilityData( setObj )
    self:setVehicleItemData( setObj )

    setObj = api.setBaseObject( self.apiData, setObj )

    return setObj
end


---
--- @return table SMW Result
function methodtable.setSemanticProperties( self )
    -- Api Error, don't set anything
    if self.apiData == nil then
        return
    end

    local setObj = self:makeSmwObject()

    local result = mw.smw.set( setObj )

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

    return result
end


function methodtable.setHeatData( self, setObj )
    if self.apiData == nil or type( self.apiData.heat ) ~= 'table' then
        return
    end

    local heat = self.apiData.heat

    setObj[ 'Masse' ] = common.formatNum( heat.mass, nil )
    setObj[ 'Infrarotstrahlung' ] = common.formatNum( heat.ir_emission, nil )
    local energyBase = common.formatNum( heat.thermal_energy_base, nil )
    local energyDraw = common.formatNum( heat.thermal_energy_draw, nil )
    setObj[ 'Kühllast' ] = { energyBase, energyDraw }

    --[[
    setObj[ '' ] = common.formatNum( heat.overpower_heat, nil )
    setObj[ '' ] = common.formatNum( heat.overclock_threshold_min, nil )
    setObj[ '' ] = common.formatNum( heat.overclock_threshold_max, nil )
    setObj[ '' ] = common.formatNum( heat.thermal_energy_base, nil )
    setObj[ '' ] = common.formatNum( heat.thermal_energy_draw, nil )
    setObj[ '' ] = common.formatNum( heat.thermal_conductivity, nil )
    setObj[ '' ] = common.formatNum( heat.specific_heat_capacity, nil )
    setObj[ '' ] = common.formatNum( heat.surface_area, nil )
    setObj[ '' ] = common.formatNum( heat.start_cooling_temperature, nil )
    setObj[ '' ] = common.formatNum( heat.max_cooling_rate, nil )
    setObj[ '' ] = common.formatNum( heat.max_temperature, nil )
    setObj[ '' ] = common.formatNum( heat.min_temperature, nil )
    setObj[ '' ] = common.formatNum( heat.overheat_temperature, nil )
    setObj[ '' ] = common.formatNum( heat.recovery_temperature, nil )
    setObj[ '' ] = common.formatNum( heat.misfire_min_temperature, nil )
    setObj[ '' ] = common.formatNum( heat.misfire_max_temperature, nil )
    ]]--
end


function methodtable.setPowerData( self, setObj )
    if self.apiData == nil or type( self.apiData.power ) ~= 'table' then
        return
    end

    local power = self.apiData.power

    setObj[ 'Grundverbrauch' ] = common.formatNum( power.power_base, nil )
    setObj[ 'Leistungsaufnahme' ] = common.formatNum( power.power_draw, nil )

    local emMin = common.formatNum( power.em_min, nil )
    local emMax = common.formatNum( power.em_max, nil )
    setObj[ 'Elektromagnetische Strahlung' ] = { emMin, emMax }

    --[[
    setObj[ '' ] = common.formatNum( power.throttleable, nil )
    setObj[ '' ] = common.formatNum( power.overclockable, nil )
    setObj[ '' ] = common.formatNum( power.overclock_threshold_min, nil )
    setObj[ '' ] = common.formatNum( power.overclock_threshold_max, nil )
    setObj[ '' ] = common.formatNum( power.overclock_performance, nil )
    setObj[ '' ] = common.formatNum( power.overpower_performance, nil )
    setObj[ '' ] = common.formatNum( power.decay_rate_em, nil )
    ]]--
end


function methodtable.setDistortionData( self, setObj )
    if self.apiData == nil or type( self.apiData.distortion ) ~= 'table' then
        return
    end

    local distortion = self.apiData.distortion

    --[[
    setObj[ '' ] = common.formatNum( distortion.decay_rate, nil )
    setObj[ '' ] = common.formatNum( distortion.maximum, nil )
    setObj[ '' ] = common.formatNum( distortion.overload_ratio, nil )
    setObj[ '' ] = common.formatNum( distortion.recovery_ratio, nil )
    setObj[ '' ] = common.formatNum( distortion.recovery_time, nil )
    ]]--
end


function methodtable.setDurabilityData( self, setObj )
    if self.apiData == nil or type( self.apiData.durability ) ~= 'table' then
        return
    end

    local durability = self.apiData.durability

    setObj[ 'Schadenspunkte' ] = common.formatNum( durability.health, nil )
    setObj[ 'Reparierbar' ] = durability.repairable
    setObj[ 'Bergbar' ] = durability.salvageable
    --setObj[ '' ] = common.formatNum( durability.max_lifetime, nil )
end


function methodtable.setVehicleItemData( self, setObj )
    if self.apiData == nil and self.apiData.class == nil and componentData.mappings[ self.apiData.type or '' ] == nil then
        return
    end

    local grade = self.apiData.grade
    if grade ~= nil and grade == 'Bespoke' then
        grade = 'Sonderanfertigung'
    end

    setObj[ 'Grad' ] = grade
    setObj[ 'Typ' ] = {
        ( componentData.mappings[ self.apiData.type or '' ] or self.apiData.type ) .. '@de',
        ( self.apiData.type ) .. '@en'
    }

	if self.apiData.class ~= nil then
	    setObj[ 'Klasse' ] = {
	        ( componentData.classMaps[ self.apiData.class or '' ] or self.apiData.class ) .. '@de',
	        ( self.apiData.class ) .. '@en'
	    }
    end
end


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

    if self.lang == 'de' then
        table.insert( self.categories, '[[Category:' .. smwData.Hersteller .. '|' .. smwData.Name .. ' ]]' )
        table.insert( self.categories, '[[Category:Item|' .. smwData.Name .. ' ]]' )

        if smwData.type ~= nil then
            table.insert( self.categories, '[[Category:' .. smwData.type_de .. '|' .. smwData.Name .. ' ]]' )
        end

        if smwData.class ~= nil then
            table.insert( self.categories, '[[Category:' .. smwData.class_de .. ' Komponente' .. '|' .. smwData.Name .. ' ]]' )
        end

        if smwData.grade ~= nil then
            table.insert( self.categories, '[[Category:Grad ' .. smwData.grade .. ' Komponente' .. '|' .. smwData.Name .. ' ]]' )
        end
    else
        table.insert( self.categories, '[[Category:' .. smwData.Name ..'|' .. smwData.Name .. ' ]]' )
    end
end


--- Entrypoint for {{#seo:}}
function methodtable.setSeoData( self )
    --[[
    local data = self:getSmwData()

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

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


--- Creates the infobox
function methodtable.getInfoBox( self )
    local data = self:getSmwData()

    if type( data ) == 'string' then
        return log.info( data )
    end

    if nil == data.Hersteller then
        data.Hersteller = 'Unbekannter Hersteller'
    end

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

    local box = require( 'Module:InfoboxNeue' ):new( {
    	removeEmpty = true,
    	emptyString = '-',
    } )

    local nameNormalized, _ = mw.ustring.gsub( data.Name, "[^%w-]", ' ' )
    nameNormalized, _ = mw.ustring.gsub( nameNormalized, "%s+", ' ' )

    local nameCleaned, _ = mw.ustring.gsub( nameNormalized, "%(", '' )
    nameCleaned, _ = mw.ustring.gsub( nameCleaned, "%)", '' )

    box:renderImage( common.getImage( {
        self.frameArgs[ 'image' ],
        mw.text.trim( nameNormalized ) .. '.jpg',
        mw.text.trim( nameCleaned ) .. '.jpg',
    } ) )

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

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

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

        if data.grade ~= nil then
            itemClass = itemClass .. string.format(' ([[:Kategorie:Grad %s Komponente|%s]])', data.grade, data.grade)
        end
    end
    
    box:renderSection( {
    	content = {
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'Item', 'lbl_type' ), data = itemType } ),
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'Item', 'lbl_class' ), data = itemClass } ),
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'Item', 'lbl_price' ), data = data.price or TNT.formatInLanguage( self.lang, 'Item', 'txt_cant_buy' ) } ),
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'Item', 'lbl_carrying_capacity' ), data = data[ 'SP' ] or '-' } ),
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'Item', 'lbl_weight' ), data = data.Volumen } ),
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'VehicleComponent', 'lbl_ir' ), data = data.ir or '-' } ),
    		box:renderItem( { label = TNT.formatInLanguage( self.lang, 'VehicleComponent', 'lbl_em' ), data = data.em or '-' } ),
    	},
		col = 2
    } )

    return tostring( box )
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

    if type( self.frameArgs[ 'Name' ] ) == 'string' then
        self.frameArgs[ 'name' ] = self.frameArgs[ 'name' ]
    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 Item.main( frame )
    local instance = Item:new()
    instance:setFrame( frame )

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

            if type( message ) == 'string' then
                instance.categories = {
                    '[[Category:Seiten mit Skriptfehlern]]',
                }

                -- Could not retrieve API data, show an error and set the error category
                return message .. instance:getCategories()
            end
        end
    end

    instance:setCategories( instance:getSmwData() )

    instance:setSeoData()

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


--- New Instance
function Item.new( self, name, apiData )
    local instance = {
        categories = {},
        frameArgs = {
            [ 'name' ] = name
        },
        apiData = apiData or nil,
        lang = require( 'Module:Template translation' )._getLanguageSubpage( mw.title.getCurrentTitle() )
    }

    setmetatable( instance, metatable )

    return instance
end


return Item