Star Citizen Wiki
Wir laden dich herzlich auf unseren Star Citizen Wiki Discord Server ein! Dein direkter Draht für Fragen, Anmerkungen oder Kritik.

Modul:Fahrzeug

Aus Star Citizen Wiki

Modulinfo[Bearbeiten]

Dieses Modul ist das Grundmodul für Raumschiffe und Fahrzeuge. Es kann nicht alleinig verwendet werden.

Öffentliche Methoden[Bearbeiten]

Das Modul stellt folgende öffentliche Methoden bereit:

  • setVehicleType
    • Setzt den Fahrzeugtyp zum setzen der richtigen Kategorie. Entweder Raumschiff oder Fahrzeug
  • setApiMethod
    • Setzt die Methode zum Abrufen der API Daten. Entweder get_ship oder get_ground_vehicle

local Fahrzeug = {}

local metatable = {}
local methodtable = {}

metatable.__index = methodtable

-- Extensions
local infobox = require( 'Module:Infobox' )
local manufacturer = require( 'Module:Hersteller' )
local vehicleData = require( 'Module:Fahrzeug/Data' )
local common = require( 'Module:Common' )
local quelle = require( 'Module:Quelle' )

-- Checks if Api Request was successful and if the Response is valid
local function checkApiResponse(response )
    if response[ 'status_code' ] ~= nil and response[ 'status_code' ] ~= 200 then
        -- Silently discard != 200 errors
        -- error( 'API Anfrage resultierte in Fehlercode ' .. response[ 'status_code' ] .. '(' .. response[ 'message' ] .. ')', 0 )
    end

    if response[ 'data' ] == nil then
        error( 'API Daten entalten kein "data" Feld', 0 )
    end
end

-- Formats a Number Decimal '.' to ','
function methodtable.formatNum( t, num )
    if num == nil then
        return nil
    end

    if type( num ) == 'string' then
    	num = num:gsub( ",", "." )
    end

	if tonumber( num ) == nil then
		return num
	end

    return mw.getContentLanguage():formatNum( tonumber( num, 10 ) )
end

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

    local setObj = {
        [ 'Länge' ] = t:formatNum( t.frameArgs[ 'Länge' ] or 0 ),
        [ 'Breite' ] = t:formatNum( t.frameArgs[ 'Breite' ] or 0 ),
        [ 'Höhe' ] = t:formatNum( t.frameArgs[ 'Höhe' ] or 0 ),

        [ 'Gewicht' ] = t.frameArgs[ 'Gewicht' ] or 0,

        [ 'SCU' ] = t.frameArgs[ 'SCU' ] or 0,

        [ 'Minimalbesatzung' ] = t.frameArgs[ 'Minimalbesatzung' ] or 0,
        [ 'Maximalbesatzung' ] = t.frameArgs[ 'Maximalbesatzung' ] or 0,

        [ 'Kampfgeschwindigkeit' ] = t.frameArgs[ 'Kampfgeschwindigkeit' ],
        [ 'Reisegeschwindigkeit ' ] = t.frameArgs[ 'Reisegeschwindigkeit ' ],

        [ 'Fokus' ] = t.frameArgs[ 'Fokus' ] or '',

        [ 'Produktionsstatus' ] = t.frameArgs[ 'Produktionsstatus' ] or '',
        [ 'Produktionsnotiz' ] = t.frameArgs[ 'Produktionsnotiz' ] or '',

        [ 'Fahrzeugtyp' ] = t.frameArgs[ 'Fahrzeugtyp' ] or '',

        [ 'Hersteller' ] = manufacturer.getNameFromCode( t.frameArgs[ 'Hersteller' ] ),

        [ 'Fahrzeuggröße' ] = t.frameArgs[ 'Fahrzeuggröße' ] or '',
        [ 'Schiffspreis' ] = t.frameArgs[ 'Schiffspreis' ],
    }

    mw.smw.set( setObj )
end

--- Request Api Data
--- Using current subpage name without vehicle type suffix
--- @return table
function methodtable.getApiDataForCurrentPage( t )
    local name = t.frameArgs[ 'name' ] or common.removeTypeSuffix(
        mw.title.getCurrentTitle().subpageText,
        t.vehicleType
    )

    local config = require( 'Module:Fahrzeug/Data' ).new( name )

    if config.get( 'api_name' ) ~= '' then
        name = config.get( 'api_name' )
    end

    if config.get( 'api_method' ) ~= '' then
        if config.get( 'api_method' ) == 'ship' then
            t.apiMethod = 'get_ship'
        end
        if config.get( 'api_method' ) == 'vehicle' then
            t.apiMethod = 'get_ground_vehicle'
        end
    end

    local json = mw.text.jsonDecode( mw.ext.Apiunto[ t.apiMethod ]( name, {
        locale = 'de_DE',
        include = 'components',
    } ) )

    checkApiResponse( json )

    t.apiData = json[ 'data' ]

    return t.apiData
end

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

    -- name from args or current page
    local queryName = t.frameArgs[ 'name' ] or mw.title.getCurrentTitle().text

    local query = table.concat( {
        '[[ ' .. queryName .. ' ]]',
        '?#-=page',
        '?Fokus',
        '?Fahrzeugtyp',
        '?Minimalbesatzung',
        '?Maximalbesatzung',
        '?Schiffspreis',
        '?Fahrzeuggröße',
        '?Gewicht',
        '?SCU',
        '?Länge',
        '?Breite',
        '?Höhe',
        '?Kampfgeschwindigkeit',
        '?Reisegeschwindigkeit',
        '?Quantengeschwindigkeit',
        '?Neigen',
        '?Gieren',
        '?Rollen',
        '?X-Achse-Beschleunigung',
        '?Y-Achse-Beschleunigung',
        '?Z-Achse-Beschleunigung',
        '?Hersteller#-',
        '?Produktionsstatus',
        '?Produktionsnotiz',
        '?Beschreibung',
        
        '?Reklamationszeit#-p1',
        '?Beschleunigungszeit#-p1',
        '?Beschleunigungskosten',
        'mainlabel=-'
    }, '|' )

    local data = mw.smw.ask( query )

    if data == nil or data[ 1 ] == nil then
        error( 'Seite "' .. queryName .. '" besitzt keine semantischen Daten.', 0 )
    end

    t.smwData = data[ 1 ]

    return t.smwData
end

--- Set Vehicle Semantic Properties
function methodtable.setSemanticProperties( t )
    common.checkSmwResult( t:setBaseSemanticProperties() )
    t:setExtraSemanticProperties()
end

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

    local price = t.apiData[ 'msrp' ]

    if price == nil and t.frameArgs[ 'price' ] ~= nil then
        price = t.frameArgs[ 'price' ]
    end

    local setData = {
        [ 'Länge' ] = t:formatNum( t.apiData.sizes.length ),
        [ 'Breite' ] = t:formatNum( t.apiData.sizes.beam ),
        [ 'Höhe' ] = t:formatNum( t.apiData.sizes.height ),

        [ 'Gewicht' ] = t.apiData.mass,

        [ 'SCU' ] = t.apiData.cargo_capacity,

        [ 'Minimalbesatzung' ] = t.apiData.crew.min,
        [ 'Maximalbesatzung' ] = t.apiData.crew.max,

        [ 'Kampfgeschwindigkeit' ] = t.apiData.speed.scm,
        [ 'Reisegeschwindigkeit ' ] = t.apiData.speed.afterburner,

        [ 'Fokus' ] = t.apiData.foci,

        [ 'Produktionsstatus' ] = t.apiData.production_status,
        [ 'Produktionsnotiz' ] = t.apiData.production_note,

        [ 'Fahrzeugtyp' ] = t.apiData.type,

        [ 'Hersteller' ] = manufacturer.getNameFromCode( t.apiData.manufacturer.code ),

        [ 'Fahrzeuggröße' ] = t.apiData.size,

        [ 'Schiffspreis' ] = price,

        [ 'Beschreibung' ] = t.frameArgs[ 'description' ] or t.apiData.description or nil
    }

	if t.apiData.speed.max ~= nil and t.apiData.speed.max ~= nil then
        setData[ 'Reisegeschwindigkeit' ] = t.apiData.speed.max
	end

    if t.apiData.insurance ~= nil then
		setData[ 'Reklamationszeit' ] = t:formatNum( t.apiData.insurance.claim_time or 0 )
		setData[ 'Beschleunigungszeit' ] = t:formatNum( t.apiData.insurance.expedite_time or 0 )
		setData[ 'Beschleunigungskosten' ] = t:formatNum( t.apiData.insurance.expedite_cost or 0 )
	end

    local result = mw.smw.set( setData )

    if t.apiData.components ~= nil and type( t.apiData.components.data ) == 'table' then
        for _, component in pairs( t.apiData.components.data ) do
            mw.smw.subobject( {
                [ 'Komponentenklasse' ] = vehicleData.getTranslatedComponentClass( component ),
                [ 'Typ' ] = vehicleData.getTranslatedComponentType( component ),
                [ 'Name' ] = vehicleData.getTranslatedComponentName( component ),
                [ 'Anzahl' ] = component.quantity,
                [ 'Komponentenbefestigungen' ] = component.mounts,
                [ 'Größe' ] = component.component_size,
                [ 'Maximalgröße' ] = component.size,
                [ 'Hersteller' ] = vehicleData.getComponentManufacturer( component )
            } )
        end
    end

    return result
end

--- Extra Properties that are Vehicle (Type) Specific
--- @param apiData table
function methodtable.setExtraSemanticProperties( t, apiData )

end

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

    local data = t:getSmwData()

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

    local cleanTitle = common.removeTypeSuffix( data.page, t.vehicleType )

    local desc = table.concat( {
        t.vehicleType,
        cleanTitle,
        'vom Hersteller',
        data.Hersteller,
        '('  .. manufacturer.getCodeFromName( data.Hersteller ) .. ')'
    }, ' ' )

    if t.frameArgs[ 'description' ] == nil or #t.frameArgs[ 'description' ] == 0 then
        if data.Beschreibung ~= nil then
            desc = data.Beschreibung
        end
    else
        desc = t.frameArgs[ 'description' ]
    end

    -- Call to {{#seo:}}
    mw.ext.seo.set{
        author = t.currentFrame:preprocess( '{{SERVER}}/Benutzer:{{urlencode:{{REVISIONUSER}}|WIKI}}' ),
        section = t.vehicleType,
        url = tostring( mw.uri.fullUrl( data.page ) ),
        title = table.concat({
            cleanTitle,
            data.Hersteller,
            t.currentFrame:preprocess( '{{SITENAME}}' )
        }, ' - '),
        title_mode = 'replace',
        keywords = table.concat({
            t.vehicleType,
            cleanTitle,
            data.Fahrzeugtyp or '',
            data.Hersteller,
            manufacturer.getCodeFromName( data.Hersteller ),
        }, ', '),
        description = desc,
        image= t.frameArgs[ 'image' ] or '',
        image_alt = desc,
        locale = 'de_DE',
        type = 'article',
    }
end

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

    if nil == data.Hersteller then
        return 'SMW Daten noch nicht geladen, bitte Seite neu laden.'
    end

    local cleanTitle = common.removeTypeSuffix( data.page, t.vehicleType )

    data.Hersteller = mw.title.new( data.Hersteller, 0 ).subpageText

    table.insert( t.categories, '[[Category:' .. t.vehicleType .. '|' .. cleanTitle .. ' ]]' )
    table.insert( t.categories, '[[Category:' .. data.Hersteller .. '|' .. cleanTitle .. ' ]]' )

    -- Set Title
    common.setDisplayTitle( t.currentFrame, cleanTitle )

    local config = vehicleData.new( cleanTitle )

    local productionStateClass = ''
    if data.Produktionsstatus == 'Flugbereit' then
        productionStateClass = 'ready'
    elseif data.Produktionsstatus == 'Im Konzept' then
        productionStateClass = 'concept'
    elseif data.Produktionsstatus == 'In Produktion' then
        productionStateClass = 'production'
    end

    local box = infobox.create( {
        --title = cleanTitle,
        --top = data.Produktionsstatus,
        --topClass = productionStateClass,
        bodyClass = 'floatright',
        allowReplace = true,
        removeEmpty = true,
        emptyString = '-'
    } )

    local image = common.getImage( {
        t.frameArgs[ 'image' ]
    } )

    -- Image
    if image ~= false then
        box:addImage( image, {
            [ 'alternativtext' ] = 'Bild des ' .. t.vehicleType .. 's ' .. cleanTitle,
            'rahmenlos',
            '600px'
        } )
    end

    box:addTitle( cleanTitle )

    box:addRow(
        'Hersteller',
        '[[' .. data.Hersteller .. ']] (' .. manufacturer.getCodeFromName( data.Hersteller ) .. ')',
        nil,
        'col2'
    )

    local focus = data.Fokus
    if type( data.Fokus ) == 'table' then
        focus = table.concat( data.Fokus, ', ' )
    elseif data.Fokus == nil then
        focus = '-'
    end

    box:addRow( 'Fokus', focus, nil, 'col2' )
       :addRow( 'Typ', data.Fahrzeugtyp, nil, 'col2' )
       :addRow( 'Besatzung', '(Min: ' .. data.Minimalbesatzung .. ' / Max: ' ..data.Maximalbesatzung .. ')', nil, 'col2' )

    local brochure = ''
    if config.get( 'brochure' ) ~= '' then
        brochure = mw.title.new( config.get( 'brochure' ), 6 )
    else
        brochure = mw.title.new( manufacturer.getCodeFromName( data.Hersteller ) .. '_' .. cleanTitle .. '_Broschüre.pdf', 6 )
    end

    box:addRow( 'Status', data.Produktionsstatus, nil, 'col2' )

    if brochure.file.exists == true then
        quelle.setArgs( {
            url = brochure:fullUrl( '', 'https' ),
            title = data.Hersteller .. ' ' .. cleanTitle .. ' Broschüre',
            wrap = true,
            ref_name = 'brochure',
        } )

        box:addRow(
            'Broschüre',
            '[[:' .. brochure.prefixedText .. '|' .. cleanTitle .. ' Broschüre]]' .. quelle.format(),
            nil,
            'col2'
        )
    end

    if data.Schiffspreis ~= nil then
        local dateTable = os.date( '*t' )

        quelle.setArgs( {
            url = 'https://robertsspaceindustries.com/pledge',
            title = 'Preis aus der Ship Upgrade Matrix',
            -- Api updates prices each month, so we'll hardcode the day
            access_date = string.format( "01.%s.%s", dateTable.month, dateTable.year ),
            section = 'Ship Upgrade',
            wrap = true,
            ref_name = 'upgrade_price',
        } )
    end

    box:addHeader( 'Preise' )
       :addRow( 'Pledge', ( data.Schiffspreis or '-' ) .. quelle.format(), nil, 'col3' )

    local queryName = t.frameArgs[ 'name' ] or mw.title.getCurrentTitle().text

    -- Retrieve PU buy price from SMW
    local price = mw.smw.ask( '[[Name::' .. queryName .. ']][[Kaufpreis::+]]|?Kaufpreis|mainlabel=-' )
    if price == nil or price[ 1 ] == nil then
        price = '-'
    else
        price = price[ 1 ][ 'Kaufpreis' ]
    end

    box
        :addRow( 'PU (Kauf)', tostring( price ), nil, 'col3' )

    -- Retrieve PU rental price from SMW
    price = mw.smw.ask( '[[Name::' .. queryName .. ']][[1 Tag::+]]|?1 Tag|mainlabel=-' )
    if price == nil or price[ 1 ] == nil then
        price = '-'
    else
        price = price[ 1 ][ '1 Tag' ]
    end

    box
        :addRow( 'PU (Miete)', tostring( price ), nil, 'col3' )
        
    if data[ 'Reklamationszeit' ] ~= nil then
	    box
	    	:addHeader( 'Versicherung' )
            	:addRow( 'Reklamationszeit', data[ 'Reklamationszeit' ], nil, 'col3' )
            	:addRow( 'Beschleunigt', data.Beschleunigungszeit or '-', nil, 'col3' )
            	:addRow( 'Kosten', data.Beschleunigungskosten or '-', nil, 'col3' )
	end

    box
        :addHeader( 'Basisdaten' )
            :addRow( 'Größe', data[ 'Fahrzeuggröße' ], nil, 'col3' )
            :addRow( 'Leergewicht', data.Gewicht, nil, 'col3' )
            :addRow( 'Frachteinheiten', data.SCU, nil, 'col3' )
            :addRow( 'Länge', data[ 'Länge' ], nil, 'col3' )
            :addRow( 'Breite', data.Breite, nil, 'col3' )
            :addRow( 'Höhe', data[ 'Höhe' ], nil, 'col3' )

	local speedCol = 'col2'
	if data[ 'Quantengeschwindigkeit' ] ~= nil then
		speedCol = 'col3'
	end

	box
        :addHeader( 'Geschwindigkeit' )
            :addRow( 'Kampf', data.Kampfgeschwindigkeit, nil, speedCol )

    if data.Reisegeschwindigkeit ~= nil then
    	if #data.Reisegeschwindigkeit > 1 then
	        box:addRow( 'Reisen', data.Reisegeschwindigkeit[2], nil, speedCol )
        else
        	box:addRow( 'Reisen', data.Reisegeschwindigkeit, nil, speedCol )
    	end
    end

	if data[ 'Quantengeschwindigkeit' ] ~= nil then
		box:addRow( 'Quantum', data.Quantengeschwindigkeit, nil, speedCol )
	end

    if t.frameArgs[ 'equipment' ] ~= nil then
        box:addHeader( 'Sonstiges' )
           :addRow( 'Ausrüstung', t.frameArgs[ 'equipment' ] )
    end

    if t.currentFrame ~= nil then
        box:addRowsFromArgs( require( 'Module:Arguments' ).getArgs( t.currentFrame ), '!' )
    end

    return tostring( box )
end

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

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

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

    local data = t:getApiDataForCurrentPage()

    t:setSemanticProperties()

    return data
end

--- New Instance
function Fahrzeug.new( self, type, apiMethod )
    if type == nil then
        error( 'Required argument "type" missing.' )
    end

    if apiMethod == nil then
        error( 'Required argument "apiMethod" missing.' )
    end

    local instance = {
        vehicleType = type,
        apiMethod = apiMethod,
        categories = {}
    }

    setmetatable( instance, metatable )

    return instance
end

return Fahrzeug
Cookies helfen uns bei der Bereitstellung dieses Wikis. Durch die Nutzung des Star Citizen Wiki erklärst du dich damit einverstanden, dass wir Cookies speichern.