Die Dokumentation für dieses Modul kann unter Modul:CelestialObject/Doku erstellt werden
local CelestialObject = {} local metatable = {} local methodtable = {} metatable.__index = methodtable local objectData = mw.loadData( 'Module:CelestialObject/Data' ) -- Extensions local common = require( 'Module:Common' ) local localized = require( 'Module:Localized' ) local quelle = require( 'Module:Quelle' ) local log = require( 'Module:Log' ) --- Sets the star system category --- Checks if a category with (Sternensystem) Suffix exists --- Uses the suffixed name when found local function setSystemCategory( celestialObject ) local systemName = celestialObject.parentObjectData.page local category = mw.title.new( systemName .. ' (Sternensystem)', 14 ) if category.exists then table.insert( celestialObject.categories, '[[Category:' .. category.text .. '|' .. celestialObject.pageName .. ']]' ) else table.insert( celestialObject.categories, '[[Category:' .. systemName .. '|' .. celestialObject.pageName .. ']]' ) end end --- Returns the starmap code for a given name or nil if not found --- @return string|nil function CelestialObject.getStarmapCodeFromName( name ) for _, typeData in pairs( objectData.starmapCodeMap ) do if type( typeData ) == 'table' then for page, object in pairs( typeData ) do if page == name then return object.code end end end end return nil end --- Returns the 'old' name from a celestial object name --- Example: Th.us’ūng (Pallas) II --- Returns: Pallas II --- If param 'new' is true, returns Th.us’ūng II --- --- @param name string The name --- @param new boolean Flag to return old or new name --- @return string function CelestialObject.getName( name, new ) local split = mw.text.split( name, '(', true ) if type( split ) == 'table' and split[ 2 ] ~= nil then -- Form: Lorem) IV local subSplit = mw.text.split( split[ 2 ], ')', true ) if subSplit[ 1 ] ~= nil and subSplit[ 2 ] ~= nil then if new == true then return mw.text.trim( split[ 1 ] ) .. ' ' .. mw.text.trim( subSplit[ 2 ] ) end return mw.text.trim( subSplit[ 1 ] ) .. ' ' .. mw.text.trim( subSplit[ 2 ] ) end end return name end --- Returns an icon for a given object type or nil --- --- @param type string The object type --- @return string|nil function CelestialObject.getIcon( objectType ) if objectData.iconMap[ objectType ] ~= nil then return objectData.iconMap[ objectType ] end return nil end --- Reverse maps a type to text --- @return string|nil function CelestialObject.reverseMapType( type ) for key, value in pairs( objectData.mappings ) do if value == type then return key end end return nil end --- Reverse maps a type to text --- @return string|nil function methodtable.reverseMapType( type ) return CelestialObject.reverseMapType( type ) end --- Output 'Umkreist' if the type orbits, else 'Standort' --- @return string function methodtable.getPositionLabel( self, type ) for _, v in pairs( objectData.orbitables ) do if v == type then return 'Umkreist' end end return 'Standort' end --- Sets the main category for this object function methodtable.setCategories( self ) table.insert( self.categories, '[[Category:' .. self.objectType .. '|' .. self.pageName .. ']]' ) -- Only Celestial Objects have a system_id -- If no systemid is set on the parent, or the object is a planet it gets categorized into the system if self.parentObjectData.system_id == nil or self.celestialObjectData.type == 'PLANET' then setSystemCategory( self ) else -- Designation _MAY_ be buggy table.insert( self.categories, '[[Category:' .. self.parentObjectData.designation .. ']]' ) end end --- Add a singular category --- @param category string function methodtable.addCategory( self, category ) table.insert( self.categories, '[[Category:' .. mw.text.trim( category, '%[%]' ) .. ']]' ) end --- Parent object semantic data --- Either the Starsystem or parent celestial object --- @return table Parent SMW Data function methodtable.getParentObjectData( self ) if self.celestialObjectData == nil then error( 'You need to call "getCelestialObjectData" first.' ) end if self.parentObjectData ~= nil then return self.parentObjectData end local askData = CelestialObject.getSmwBaseAskData() askData.mainlabel = '-' askData.limit = 1 askData.sort = 'Starmap Code' askData.order = 'asc' local id = self.celestialObjectData.parent_id if id == nil then table.insert( askData, 1, '[[Has subobject::<q>[[Starmap Code::' .. self.celestialObjectData.code .. ']]</q>]]' ) else table.insert( askData, 1, '[[ID::' .. self.celestialObjectData.parent_id .. '|+depth=0]]' ) end local data = mw.smw.ask( askData ) if id == nil and (data == nil or data[ 1 ] == nil) then table.remove( askData, 1 ) table.insert( askData, 1, '[[Has subobject::<q>[[Starmap Code::' .. self.celestialObjectData.code .. ']]</q>]]' ) data = mw.smw.ask( askData ) end if data == nil or data[ 1 ] == nil then error( 'Keine Systemdaten für Starmap Code ' .. tostring( id ) .. ' oder Elternid ' .. tostring( self.celestialObjectData.parent_id ) .. ' gefunden.', 0 ) end self.parentObjectData = data[ 1 ] if data[ 1 ].affiliation == nil then self.parentObjectData.affiliation = {} end return self.parentObjectData end --- Queries the SMW Store for the current object --- @param identifier string|number Starmap Code / Name / ID of the object --- @return table SMW Data function methodtable.getCelestialObjectData( self, identifier ) -- Cache multiple calls if self.celestialObjectData ~= nil then return self.celestialObjectData end -- We'll try to get the code by pagename if identifier == nil then identifier = CelestialObject.getStarmapCodeFromName( localized.getMainTitle() ) if identifier == nil and self.frameArgs[ 'Starmap Code' ] ~= nil then identifier = self.frameArgs[ 'Starmap Code' ] end end local selector = { '[[Starmap Code::' .. identifier .. ']]', '[[Bezeichnung::' .. identifier .. ']]', '[[Bezeichnung::' .. localized.getMainTitle() .. ']]', } if type( identifier ) == 'number' then table.insert( selector, '[[ID::' .. identifier .. ']]' ) end local askData = CelestialObject.getSmwBaseAskData() askData.mainlabel = '-' askData.limit = 1 table.insert( askData, 1, table.concat( selector, '||' ) ) local data = mw.smw.ask( askData ) if data == nil or data[ 1 ] == nil then error( 'Semantische Daten zu "' .. identifier .. '" noch nicht geladen. Bei neuen Seiten kann dieser Vorgang mehrere Minuten dauern.' ) end self.celestialObjectData = data[ 1 ] if data[ 1 ].affiliation == nil then self.celestialObjectData.affiliation = {} end return self.celestialObjectData end --- Creates the base infobox for a celestial object --- TODO Clean --- @return string Infobox function methodtable.makeInfoBox( self ) if self.celestialObjectData == nil or self.celestialObjectData.page == nil or self.hideBox == true then -- Faulty SMW data return '' end local system = require( 'Module:Sternensystem' ) if self.celestialObjectData.habitable ~= nil then self.celestialObjectData.habitable = common.booleanToText( self.celestialObjectData.habitable ) end local box = require( 'Module:InfoboxNeue' ):new( { removeEmpty = true, emptyString = '-', placeholderImage = 'Platzhalter Starmap.webp', } ) local boxTitle = localized.getMainTitle() if boxTitle ~= self.pageName then boxTitle = self.pageName end boxTitle = common.removeTypeSuffix( boxTitle, self.typeSuffixes ) -- Image box:renderImage( common.getImage( { common.removeTypeSuffix( localized.getMainTitle(), self.typeSuffixes ), boxTitle, 'Galactapedia_' .. boxTitle .. '.png', self.frameArgs.image, } ) ) local parentPage = '' local starmapRef = '' local subtitle = '' if self.parentObjectData.page ~= nil then parentPage = mw.text.split( self.parentObjectData.page, '#', true )[ 1 ] local systemCode = mw.text.split( ( self.parentObjectData.code or '' ), '.', true )[ 1 ] quelle = quelle:new() starmapRef = quelle:format( { url = 'https://robertsspaceindustries.com/starmap?location=' .. self.celestialObjectData.code .. '&system=' .. systemCode, title = 'Ark Starmap: ' .. self.pageName, wrap = true, ref_name = 'starmap', } ) subtitle = '[[' .. parentPage .. '|' .. common.removeTypeSuffix( parentPage, 'Sternensystem' ) .. ' System]]' end box:renderHeader( { title = boxTitle, subtitle = subtitle, } ) local section = {} for _, data in ipairs( objectData.infoboxAstronomicalDataSmwMappings ) do if self.celestialObjectData[ data.key ] ~= nil then table.insert( section, box:renderItem( data.value, self.celestialObjectData[ data.key ] ) ) end end if self.parentObjectData.type ~= nil and self.parentObjectData.planet_count == nil then local orbits = self.parentObjectData.designation if self.parentObjectData.type == 'STAR' then orbits = orbits .. ' (Stern)' end table.insert( section, box:renderItem( self:getPositionLabel( self.celestialObjectData.type ), '[[' .. orbits .. ']]' ) ) end box:renderSection( { title = 'Astronomische Daten' .. starmapRef, col = 2, content = section }) section = {} for _, data in ipairs( objectData.infoboxPoliticsDataSmwMappings ) do if self.celestialObjectData[ data.key ] ~= nil then if data.key == 'affiliation' then table.insert( section, box:renderItem( data.value, system.getAffiliationLines( self.celestialObjectData.affiliation ) ) ) else table.insert( section, box:renderItem( data.value, self.celestialObjectData[ data.key ] ) ) end end end box:renderSection( { title = 'Politik und Wirtschaft', col = 2, content = section, } ) return tostring( box ) .. tostring( common.generateInterWikiLinks( localized.getMainTitle() ) ) end --- Entrypoint for {{#seo:}} function methodtable.setSeoData( self ) if self.currentFrame == nil then error( 'No frame set.', 0 ) end if self.celestialObjectData == nil or self.celestialObjectData.page == nil then -- Faulty SMW data, don't call #seo return end if type( self.celestialObjectData.affiliation ) == 'string' then self.celestialObjectData.affiliation = { self.celestialObjectData.affiliation } end local image = common.getImage( { common.removeTypeSuffix( localized.getMainTitle(), self.typeSuffixes ), 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( self.celestialObjectData.page ) ), title = table.concat( { self.pageName, self.objectType, self.currentFrame:preprocess( '{{SITENAME}}' ) }, ' - '), title_mode = 'replace', keywords = table.concat( { self.objectType, self.pageName, table.concat( self.celestialObjectData.affiliation, ', '), }, ', '), description = self.frameArgs.description or nil, image = image or '', image_alt = 'Bild des ' .. self.pageName .. ' ' .. self.objectType, locale = 'de_DE', type = 'article', } end --- Creates a settable subobject table from args --- @param args table Frame args --- @return table Subobject function methodtable.getSubObjectData( self, args ) if args[ 'Starmap Code' ] == nil then return end local requiredKeys = { 'Sternensystemid', 'Starmap Code', 'Bezeichnung', 'Typ', 'ID', 'Elternid', } local setObj = { [ 'Sternensystemid' ] = args[ 'Sternensystemid' ] or nil, [ 'Starmap Code' ] = args[ 'Starmap Code' ] or nil, [ 'Bezeichnung' ] = args[ 'Bezeichnung' ] or nil, [ 'Typ' ] = args[ 'Typ' ] or nil, [ 'Kontrolle' ] = args[ 'Kontrolle' ] or nil, [ 'ID' ] = args[ 'ID' ] or nil, [ 'Elternid' ] = args[ 'Elternid' ] or nil, [ 'Wirtschaft' ] = args[ 'Wirtschaft' ] or nil, [ 'Bevölkerungsgröße' ] = args[ 'Bevölkerungsgröße' ] or nil, [ 'Gefahrenalge' ] = args[ 'Gefahrenalge' ] or nil, [ 'Habitabel' ] = args[ 'Habitabel' ] or nil, } for _, v in pairs( requiredKeys ) do if setObj[ v ] == nil then error( 'Eingegebene Daten nicht valide.' ) return end if v == 'Typ' then setObj[ v ] = setObj[ v ] .. '@en' end end if setObj[ 'ID' ] ~= nil then setObj[ 'ID' ] = mw.ustring.gsub( setObj[ 'ID' ], '%.', '' ) end if setObj[ 'Elternid' ] ~= nil then setObj[ 'Elternid' ] = mw.ustring.gsub( setObj[ 'Elternid' ], '%.', '' ) end return setObj end --- WIP: Create a manual subobject --- See: Vorlage:CelestialObject --- @param args table - The frame arguments --- @param typeOverride string|nil - Optional type override used in modules function methodtable.addManual( self, args, typeOverride ) if args[ 'Starmap Code' ] == nil then return end local setObj = self:getSubObjectData( args ) if setObj == nil then return end if typeOverride ~= nil then setObj[ 'Typ' ] = typeOverride end setObj[ 'Typ' ] = mw.text.trim( mw.ustring.upper( setObj[ 'Typ' ] ) ) .. '@en' mw.smw.subobject( setObj ) end --- Load data and output the infobox --- @param frame table The current frame --- @return string Infobox and categories function methodtable.run( 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 self.frameArgs[ 1 ] ~= nil then self.objectType = self.frameArgs[ 1 ] end -- Add manual submodule if code is set self:addManual( self.frameArgs, self.frameArgs[ 'Typ' ] or objectData.mappings[ self.objectType ] or self.objectType ) local dataSuccess, coE = pcall( self.getCelestialObjectData, self, self.frameArgs.code or self.frameArgs.name or self.frameArgs[ 'Starmap Code' ] ) local parentSuccess, poE = pcall(self.getParentObjectData, self) if not dataSuccess or not parentSuccess then --errors = '<span style="display:none;">' .. ( coE or '' ) .. '<br>' .. ( poE or '' ) .. '</span>' local errors= '' return log.info( 'Daten werden im semantic Wiki aktualisiert, dies kann mehrere Minuten dauern.' .. errors ) end self.pageName = common.removeTypeSuffix( localized.getMainTitle(), self.typeSuffixes ) if self.celestialObjectData.name ~= nil and self.pageName ~= self.celestialObjectData.name then self.pageName = self.pageName .. ': ' .. self.celestialObjectData.name end if mw.title.getCurrentTitle().namespace == 0 then self:setCategories() end common.setDisplayTitle( self.currentFrame, self.pageName ) self:setSeoData() return tostring( self:makeInfoBox() ) .. tostring( table.concat( self.categories ) ) end --- Wrapper to allow method calls --- @see CelestialObject.getSmwBaseAskData function methodtable.getSmwBaseAskData( self ) return CelestialObject.getSmwBaseAskData() end --- Returns a copy of data that is queried for each object from the smw store --- @return table function CelestialObject.getSmwBaseAskData() local askData = {} for k, v in pairs( objectData.smwAskData ) do askData[ k ] = v end return askData end --- WIP: Create a manual subobject --- See: Vorlage:CelestialObject --- @param frame table - The current frame --- @param typeOverride string|nil - Optional type override used in modules function CelestialObject.addManualFromFrame( frame, typeOverride ) local instance = CelestialObject:new( '' ) instance:addManual( require( 'Module:Arguments' ).getArgs( frame ), typeOverride ) end --- New Instance --- @return table CelestialObject function CelestialObject.new( self, objectType ) local instance = { objectType = '', parentType = '', currentFrame = {}, frameArgs = {}, pageName = {}, categories = {}, celestialObjectData = nil, parentObjectData = nil, typeSuffixes = { 'Sternensystem', 'Stern', 'Planet', 'Mond', 'Raumstation', 'Stadt', 'Lagrange Punkt', }, } setmetatable( instance, metatable ) if objectType == nil then error( 'Required argument "objectType" missing.' ) end instance.objectType = objectType table.insert( instance.typeSuffixes, objectType ) return instance end --- For direct invocation function CelestialObject.newFromFrame( frame ) local instance = CelestialObject:new( frame.args[ 'type' ] ) return instance:run( frame ) end return CelestialObject