Modul:Food

Aus Steel Beasts Wiki
Version vom 6. Juli 2023, 21:26 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:Food/Doku erstellt werden

local Food = {}

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 item = require( 'Module:Item' )
local commodity = require( 'Module:Commodity' )



-- TODO: Refactor into Data module
local subTypeTranslations = {
    ['Bottle'] = 'Flasche',
    ['Box'] = 'Box',
    ['Bar'] = 'Bar',
    ['Tin'] = 'Dose',
    ['Plant'] = 'Pflanze',
    ['Junk'] = 'Junkfood',
    ['Sachet'] = 'Päckchen',
    ['Consumable'] = 'Verbrauchsmaterial',
    ['Can'] = 'Dose',
}

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

    local setObj = {
        [ 'Name' ]                                = self.frameArgs.Name                                    or nil,
        [ 'Beschreibung' ]                        = self.frameArgs.Beschreibung                            or nil,
        [ 'Nährwert' ]                            = self.frameArgs[ 'Größe' ]                              or nil,
        [ 'Hydrationswirkung' ]                   = self.frameArgs[ 'Hersteller' ]                         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[ 'uuid' ] or self.frameArgs[ 'name' ] or mw.title.getCurrentTitle().text

    local json = mw.text.jsonDecode( mw.ext.Apiunto.get_raw( 'v2/food/' .. 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( {
        '[[Name::' .. queryName .. ']][[Hersteller::+]]',
        '?#-=page',
        '?Name#-',
        '?Größe#-',
        '?Hersteller#-',
        '?Beschreibung', '+lang=' .. common.getLocaleForPage(),
        '?Subtyp=type', '+lang=' .. common.getLocaleForPage(),
        '?Nährwert#-=ndi',
        '?Hydrationswirkung#-=hei',
        '?Effekt#-=effects',
        '?Länge',
        '?Breite',
        '?Höhe',
        '?Volumen',
        '?Inventarvolumen',
        '?Spielversion#-=version',
        '?Wiederverschließbar#-=resealable',
        '?Anwendungen#-=uses',
        'mainlabel=-'
    } )

    if data == nil or data[ 1 ] == nil then
        return TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', '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

--- 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 then
        return
    end

    local uses = nil
    if self.apiData.food.one_shot_consume == true then
    	uses = 1
    elseif self.apiData.food.one_shot_consume == false then
		uses = -1
    end

	local item = item:new( '', self.apiData )
    local setObj = item:makeSmwObject()

    setObj[ 'Nährwert' ]            = self.apiData.food.nutritional_density_rating or nil
    setObj[ 'Hydrationswirkung' ]   = self.apiData.food.hydration_efficacy_index or nil
    setObj[ 'Anwendungen' ]         = uses or nil
    setObj[ 'Wiederverschließbar' ] = self.apiData.food.can_be_reclosed or nil
    setObj[ 'Effekt' ]              = self.apiData.food.effects or nil
    setObj[ 'Typ' ] = api.mapTranslation( Food.translateType( self.apiData.type ) )
	setObj[ 'Subtyp' ] = api.mapTranslation( Food.translateSubType( self.apiData.sub_type ) )

    local result = mw.smw.set( setObj )

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

    return result
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.Hersteller then
        -- Faulty SMW data, don't call #seo
        return
    end

    require( 'Module:SEO' ).set(
        TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'seo_section' ),
        data.page,
        table.concat({
            data.Name,
            data.Hersteller,
            self.currentFrame:preprocess( '{{SITENAME}}' )
        }, ' - '),
        'replace',
        {
            data.Name,
            'Lebensmittel',
            data.Hersteller,
            require( 'Module:Hersteller' ).getCodeFromName( data.Hersteller ),
            TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', '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+", ' ' )
	nameNormalized, _ = mw.ustring.gsub( nameNormalized, "%(", '' )
	nameNormalized, _ = mw.ustring.gsub( nameNormalized, "%)", '' )
	nameNormalized = mw.text.trim( nameNormalized )

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

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

	box:renderSection( {
		col = 2,
		content = {
			box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_type' ), '[[:Kategorie:Lebensmittel|Lebensmittel]]' ),
			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' ) ),
			box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Common/i18n.json', 'lbl_weight' ), data.Inventarvolumen or data.Volumen or '-' ),
		}
	} )

	local uses = data.uses or '-'
	if uses == -1 then
		uses = 'Mehrfach'
	end
	
	local section = {}

	if data.type ~= nil then
		table.insert( section, box:renderItem( 'Container', data.type ) )
	end

	table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'lbl_uses' ), uses ) )
	table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'lbl_resealable' ), tostring( data.resealable ) ) )

	if data.ndi ~= nil then
    	table.insert( section, box:renderItem( '[[Nährwert|' .. TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'lbl_ndi' ) .. ']]', data.ndi ) )
	end

	if data.hei ~= nil then
    	table.insert( section, box:renderItem( '[[Hydration|' .. TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'lbl_hei' ) .. ']]', data.hei ) )
	end

	if type( data.effects ) == 'string' then
		data.effects = { data.effects }
	end

	if type( data.effects ) == 'table' then
		local effects = {}
		for _, v in pairs( data.effects ) do
			if v ~= 'None' then
				table.insert( effects, string.format( '[[%s]]', v ) )
			end
		end

		if #effects > 0 then
			table.insert( section, box:renderItem( TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'lbl_effects' ), table.concat( effects, ', ') ) )
		end
	end

	box:renderSection( {
		title = TNT.formatInLanguage( self.lang, 'Module:Food/i18n.json', 'lbl_consumable' ),
		col = 3,
		content = section
	} )

    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
end

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

--- Set categories
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, string.format('[[Category:%s|%s]]', smwData.Hersteller, smwData.Name ) )
    	table.insert( self.categories, string.format('[[Category:Lebensmittel|%s]]', smwData.Name ) )
	else
		table.insert( self.categories, string.format('[[Category:%s]]', smwData.Name ) )
	end
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

--- @param type string
--- @return table
function Food.translateType( type )
	local foodType = 'Lebensmittel'
	if type == 'Drink' then
		foodType = 'Getränk'
	end

    return {
        de_DE = foodType or type,
        en_EN = type
    }
end

--- @param type string
--- @return table
function Food.translateSubType( subType )
	local trans = subType
	if type( subTypeTranslations[ subType ] ) == 'string' then
		trans = subTypeTranslations[ subType ]
	end

    return {
        de_DE = trans,
        en_EN = type
    }
end

--- Template entry
function Food.main( frame )
    local instance = Food: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 Food.new( self, name )
    local instance = {
        categories = {},
        frameArgs = {
            [ 'name' ] = name
        },
        lang = require( 'Module:Template translation' )._getLanguageSubpage( mw.title.getCurrentTitle() )
    }

    setmetatable( instance, metatable )

    return instance
end

return Food