Die Dokumentation für dieses Modul kann unter Modul:Sternensystem/Doku erstellt werden
local Sternensystem = {}
local metatable = {}
local methodtable = {}
metatable.__index = methodtable
-- Extensions
local api = mw.ext.Apiunto
local infobox = require( 'Module:InfoboxNeue' )
local systemData = require( 'Module:Sternensystem/Data' )
local common = require( 'Module:Common' )
local localized = require( 'Module:Localized' )
local quelle = require( 'Modul:Quelle' )
--- Filters celestial_objects by type key
--- Returns a table containing only the specified type
---
--- @param apiData table - Json API Data
--- @param objectType string - The type to filter
---
--- @return table
function Sternensystem.getCelestialObjectsForType( apiData, objectType )
if apiData == nil or apiData.celestial_objects == nil then
return {}
end
local objects = {}
for _, object in pairs( apiData.celestial_objects ) do
if object.type == objectType then
table.insert( objects, object )
end
end
return objects
end
--- Extracts the affiliations form api data
---
--- @param affiliationData table
--- @param key string
---
--- @return table
function Sternensystem.extractAffiliations( affiliationData, key )
if type( affiliationData ) ~= 'table' or #affiliationData == 0 then
return {}
end
local affiliations = {}
for _, affiliation in pairs( affiliationData ) do
if key ~= nil and affiliation[ key ] ~= nil then
table.insert( affiliations, affiliation[ key ] )
else
table.insert( affiliations, {
name = affiliation.name,
code = affiliation.code,
})
end
end
return affiliations
end
--- Append 'Mrd. Jahre'
--- @param age number|string
---
--- @return string formatted age
function Sternensystem.formatAge( age )
if age ~= nil and common.formatNum( age ) ~= nil then
if type( age ) == 'string' then
age = tonumber( age, 10 )
end
age = age * 1000000000
return common.formatNum( age ) .. ' Jahre'
end
end
--- Formats a table for sizes and appends 'km'
--- @param sizes table|nil
---
--- @return table|string
function Sternensystem.formatSize( sizes )
if sizes == nil then
return sizes
end
if type( sizes ) == 'table' then
for k, v in pairs( sizes ) do
if k ~= nil and v ~= nil then
local formatted = common.formatNum( v )
if formatted ~= nil then
sizes[ k ] = formatted .. ' km'
end
end
end
return sizes
end
local formatted = common.formatNum( sizes )
if formatted ~= nil then
return formatted .. ' km'
end
end
--- Write celestial objects as subobject
---
--- @param celestialObjects table
function Sternensystem.setSubObjects( celestialObjects )
for _, celestialObject in pairs( celestialObjects ) do
if celestialObject.habitable ~= nil then
if celestialObject.habitable == 1 or celestialObject.habitable == true then
celestialObject.habitable = "Ja"
else
celestialObject.habitable = "Nein"
end
end
local data = {
[ 'ID' ] = celestialObject.id,
[ 'Starmap Code' ] = celestialObject.code,
[ 'Typ' ] = celestialObject.type .. '@en',
[ 'Name' ] = celestialObject.name,
[ 'Bezeichnung' ] = celestialObject.designation,
[ 'Alter' ] = Sternensystem.formatAge( celestialObject.age ),
[ 'Radius' ] = Sternensystem.formatSize( celestialObject.size ),
[ 'Habitabel' ] = celestialObject.habitable,
[ 'Beschreibung' ] = common.mapTranslation( celestialObject.description ),
[ 'Gefahrenlage' ] = common.formatNum( celestialObject.sensor.danger ),
[ 'Wirtschaft' ] = common.formatNum( celestialObject.sensor.economy ),
[ 'Bevölkerungsgröße' ] = common.formatNum( celestialObject.sensor.population ),
[ 'Kontrolle' ] = Sternensystem.extractAffiliations( celestialObject.affiliation, 'name' ),
[ 'Umlaufzeit' ] = common.formatNum( celestialObject.orbit_period ),
[ 'Abstand' ] = common.formatNum( celestialObject.distance ),
[ 'Breitengrad' ] = common.formatNum( celestialObject.latitude ),
[ 'Längengrad' ] = common.formatNum( celestialObject.longitude ),
[ 'Elternid' ] = celestialObject.parent_id,
[ 'Sternensystemid' ] = celestialObject.system_id,
}
if celestialObject.subtype ~= nil and type( celestialObject.subtype ) == 'table' and celestialObject.subtype.id ~= nil then
data[ 'Subtyp' ] = celestialObject.subtype.type .. '@en'
data[ 'Subtypname' ] = systemData.getTranslatedSubtype( celestialObject.subtype.name )
end
if celestialObject.type == 'JUMPPOINT' and celestialObject.jumppoints ~= nil and type( celestialObject.jumppoints ) == 'table' then
local jumppoint = celestialObject.jumppoints
data[ 'Größe' ] = jumppoint.size
data[ 'Richtung' ] = jumppoint.direction
local designation = ''
if jumppoint.entry.system_id == celestialObject.system_id then
designation = jumppoint.entry.designation
elseif jumppoint.exit.system_id == celestialObject.system_id then
designation = jumppoint.exit.designation
end
local destinations = mw.text.split( designation, ' - ', true )
if #destinations == 2 then
data[ 'Sprungpunkt Start' ] = Sternensystem.cleanJumppointDestination( destinations[ 1 ] )
data[ 'Sprungpunkt Ziel' ] = Sternensystem.cleanJumppointDestination( destinations[ 2 ] )
end
end
mw.smw.subobject( data )
--common.checkSmwResult( mw.smw.subobject( data ) )
end
end
--- Returns the 'old' Starsystem name from a format of
--- Starsystem (New Name)
---
--- @param destination string
---
--- @return string
function Sternensystem.cleanJumppointDestination( destination )
local clean = mw.text.split( destination, '(', true )
if clean[ 1 ] ~= nil and type( clean[ 1 ] ) == 'string' then
return mw.text.trim( clean[ 1 ] )
end
return destination
end
--- Returns small logo and link if available
---
--- @param affiliations string|table
---
--- @return string
function Sternensystem.getAffiliationLines( affiliations )
local mapping = {
BANU = '[[Banu]]',
DEV = 'Developing',
DEVELOPING = 'Developing',
UEE = '[[Menschen]]',
UNC = 'Unclaimed',
UNCLAIMED = 'Unclaimed',
VANDUUL = '[[Vanduul]]',
[ 'XI\'AN' ] = '[[Xi\'An]]',
}
if type( affiliations ) == 'string' then
affiliations = { affiliations }
end
local lines = {}
for _, affiliation in pairs( affiliations ) do
local line = '[[Datei:Systemlogo ' .. mw.ustring.upper( affiliation:gsub( '%\'', '' ) ) .. '.svg|frameless|link=|class=noviewer factionlogo|x15px]] '
if mapping[ mw.ustring.upper( affiliation ) ] == nil then
line = line .. mw.ustring.upper( affiliation )
else
line = line .. mapping[ mw.ustring.upper( affiliation ) ]
end
table.insert( lines, line )
end
if #lines == 0 then
return '-'
end
return tostring( table.concat( lines, '<br>' ) )
end
--- Textual Affiliation
---
--- @param affiliations table|string
---
--- @return string
function Sternensystem.getAffiliationsAsText( affiliations )
if affiliations == nil then
return ''
end
if type( affiliations ) == 'string' then
affiliations = { affiliations }
end
local line = ''
for _, affiliation in pairs( affiliations ) do
if #line > 0 then
line = line .. ' und '
end
if affiliation == 'Developing' then
line = line .. 'von niemandem, dieses System entwickelt sich derzeit'
elseif affiliation == 'Unclaimend' then
line = line .. 'von niemandem, keine Fraktion kontrolliert dieses System'
elseif affiliation == 'UEE' then
line = line .. 'des United Earth Empire'
else
line = line .. 'der ' .. affiliation
end
end
return line .. '.'
end
---
--- Public Methods
---
--- 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.Name then
-- Faulty SMW data, don't call #seo
return
end
if type( data.affiliation ) == 'string' then
data.affiliation = { data.affiliation }
end
local cleanTitle = common.removeTypeSuffix( data.page, 'Sternensystem' )
local desc = table.concat( {
'Das',
cleanTitle,
'Sternensystem ist ein System under der Kontrolle',
Sternensystem.getAffiliationsAsText( data.affiliation )
}, ' ' )
-- Image
local image = common.getImage( {
self.pageName .. '_System.jpg',
self.pageName .. '_System.png',
self.frameArgs.image
} )
-- Call to {{#seo:}}
mw.ext.seo.set{
author = self.currentFrame:preprocess( '{{SERVER}}/Benutzer:{{urlencode:{{REVISIONUSER}}|WIKI}}' ),
section = 'Sternensystem',
url = tostring( mw.uri.fullUrl( data.page ) ),
title = table.concat( {
cleanTitle,
'Sternensystem',
self.currentFrame:preprocess( '{{SITENAME}}' )
}, ' - '),
title_mode = 'replace',
keywords = table.concat( {
'Sternensystem',
cleanTitle,
table.concat( data.affiliation, ', '),
}, ', '),
description = self.frameArgs.description or desc,
image = image or '',
image_alt = 'Bild des ' .. data.Name .. ' Systems',
locale = 'de_DE',
type = 'article',
}
end
--- Request Api Data
--- Using current subpage name
---
--- @return table
function methodtable.getApiDataForCurrentPage( self )
local name = self.pageName
local config = systemData.new( self.pageName )
if config.get( 'api_name' ) ~= '' then
name = config.get( 'api_name' )
end
local json = mw.text.jsonDecode( api.get_starsystem( name, {
include = {
'celestialObjects',
},
} ) )
common.checkApiResponse( json )
self.apiData = json.data or nil
return self.apiData
end
--- Returns the highest star age
---
--- @return number
function methodtable.getSystemAge( self )
local stars = Sternensystem.getCelestialObjectsForType( self.apiData, 'STAR' )
local age = 0
for _, star in pairs( stars ) do
if star.age ~= nil and tonumber( star.age, 10 ) >= age then
age = tonumber( star.age, 10 )
end
end
return age
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 mw.title.getCurrentTitle().rootText
local query = {
'[[ ' .. queryName .. ' ]]',
'?#-=page',
'?Name#-=name',
'?Starmap Code=code',
'?Status=status',
'?Typ=type',
'+lang=en',
'?Sternensystem Größe=system_size',
'?Sternensystem Alter=system_age',
'?Kontrolle=affiliation',
'?Bevölkerungsgröße=population_level',
'?Wirtschaft=economic_level',
'?Gefahrenlage=threat_level',
'?Anzahl Sterne=star_count',
'?Anzahl Planeten=planet_count',
'?Anzahl Monde=moon_count',
'?Anzahl Asteroidengürtel=asteroid_belt_count',
'?Anzahl Sprungpunkte=jumppoint_count',
'mainlabel=-'
}
local data = mw.smw.ask( query )
if data == nil or data[ 1 ] == nil then
error( 'Seite "' .. queryName .. '" besitzt keine semantischen Daten.', 0 )
end
self.smwData = data[ 1 ]
return self.smwData
end
--- Queries the SMW Store
function methodtable.setSemanticProperties( self )
-- Api Error, don't set anything
if self.apiData == nil then
return
end
local setData = {
[ 'Name' ] = self.apiData.name,
[ 'ID' ] = self.apiData.id,
[ 'Starmap Code' ] = self.apiData.code,
[ 'Status' ] = self.apiData.status,
[ 'Typ' ] = self.apiData.type .. '@en',
[ 'Sternensystem Größe' ] = common.formatNum( self.apiData.aggregated.size ),
[ 'Sternensystem Alter' ] = common.formatNum( self:getSystemAge() ) .. ' Mrd.Jahre',
[ 'Gefahrenlage' ] = common.formatNum( self.apiData.aggregated.danger ),
[ 'Kontrolle' ] = Sternensystem.extractAffiliations( self.apiData.affiliation, 'name' ),
[ 'Wirtschaft' ] = common.formatNum( self.apiData.aggregated.economy ),
[ 'Bevölkerungsgröße' ] = common.formatNum( self.apiData.aggregated.population ),
[ 'Frostlinie' ] = common.formatNum( self.apiData.aggregated.frost_line ),
-- [ 'Habitable Zone (Innen)' ] = common.formatNum( apiData.aggregated.habitable_zone_inner ),
-- [ 'Habitable Zone (Außen)' ] = common.formatNum( apiData.aggregated.habitable_zone_outer ),
[ 'Anzahl Sterne' ] = self.apiData.aggregated.stars,
[ 'Anzahl Planeten' ] = self.apiData.aggregated.planets,
[ 'Anzahl Monde' ] = self.apiData.aggregated.moons,
[ 'Anzahl Asteroidengürtel' ] = #Sternensystem.getCelestialObjectsForType( self.apiData, 'ASTEROID_BELT' ),
[ 'Anzahl Sprungpunkte' ] = #Sternensystem.getCelestialObjectsForType( self.apiData, 'JUMPPOINT' ),
[ 'Beschreibung' ] = common.mapTranslation( self.apiData.description ),
}
common.checkSmwResult( mw.smw.set( setData ) )
if self.apiData.celestial_objects ~= nil and type( self.apiData.celestial_objects ) == 'table' then
Sternensystem.setSubObjects( self.apiData.celestial_objects )
end
end
--- Creates the infobox
function methodtable.getInfoBox( self )
local data = self:getSmwData()
if data.page == nil then
return 'SMW Daten noch nicht geladen, bitte Seite neu laden.'
end
local astronomicalData = {
star_count = 'Sterne',
system_size = 'Größe (AE)',
system_age = 'Alter',
}
local politicsAndEconomy = {
{
key = 'affiliation',
text = 'Zugehörigkeit',
},
{
key = 'population_level',
text = 'Bevölkerung',
},
{
key = 'economic_level',
text = 'Wirtschaft',
},
{
key = 'threat_level',
text = 'Gefahrenlage',
},
}
local cleanTitle = self.pageName
if cleanTitle == nil then
cleanTitle = common.removeTypeSuffix( localized.getMainTitle(), 'Sternensystem' )
end
local box = infobox:new( {
removeEmpty = true,
emptyString = '-',
} )
-- Image
box:renderImage( common.getImage( {
self.pageName .. '_System.jpg',
self.pageName .. '_System.png',
self.frameArgs.image
} ) )
box:renderHeader( {
title = cleanTitle .. ' System',
} )
local section = {}
for smwKey, value in pairs( astronomicalData ) do
if data[ smwKey ] ~= nil then
table.insert( section, box:renderItem( value, data[ smwKey ] ) )
end
end
table.insert( section, box:renderItem( 'Planeten', data.planet_count or '-' ) )
table.insert( section, box:renderItem( 'Monde', data.moon_count or '-' ) )
table.insert( section, box:renderItem( 'Asteroidengürtel', data.asteroid_belt_count or '-' ) )
table.insert( section, box:renderItem( 'Sprungpunkte', data.jumppoint_count or '-' ) )
box:renderSection( {
title = 'Astronomische Daten' .. (quelle:new()):format( {
url = 'https://robertsspaceindustries.com/starmap?location=' .. ( data.code or '' ),
title = 'Ark Starmap: ' .. self.pageName .. ' System',
wrap = true,
ref_name = 'system_starmap',
} ),
col = 2,
content = section,
} )
section = {}
for _, obj in ipairs( politicsAndEconomy ) do
if data[ obj.key ] ~= nil then
if obj.key == 'affiliation' then
table.insert( section, box:renderItem( obj.text, Sternensystem.getAffiliationLines( data.affiliation ) ) )
else
table.insert( section, box:renderItem( obj.text, data[ obj.key ] ) )
end
end
end
box:renderSection( {
title = 'Politik und Wirtschaft',
col = 2,
content = section
} )
return tostring( box ) .. tostring( common.generateInterWikiLinks( cleanTitle ) )
end
--- Ouput infobox and categories and set seo
--- Entrypoint for Template calls
function Sternensystem.infoBox( frame )
local instance = Sternensystem:new()
instance.currentFrame = frame
instance.frameArgs = frame:getParent().args
instance.pageName = instance.frameArgs.name or common.removeTypeSuffix( localized.getMainTitle(), 'Sternensystem' )
if mw.title.getCurrentTitle().namespace == 0 then
table.insert( instance.categories, '[[Category:Sternensystem|' .. instance.pageName .. ']]' )
end
common.setDisplayTitle( instance.currentFrame, instance.pageName )
if not mw.title.getCurrentTitle().isSubpage then
instance:getApiDataForCurrentPage()
instance:setSemanticProperties()
end
instance:setSeoData()
return tostring( instance:getInfoBox() ) ..
tostring( table.concat( instance.categories ) ) ..
tostring( common.generateInterWikiLinks( instance.pageName ) )
end
--- New instance
function Sternensystem.new( self )
local instance = {
currentFrame = nil,
frameArgs = nil,
pageName = nil,
categories = {},
apiData = nil,
smwData = nil,
}
setmetatable( instance, metatable )
return instance
end
return Sternensystem