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