<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://wiki.iccup.org/index.php?action=history&amp;feed=atom&amp;title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%3AVehicle</id>
	<title>Модуль:Vehicle - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.iccup.org/index.php?action=history&amp;feed=atom&amp;title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C%3AVehicle"/>
	<link rel="alternate" type="text/html" href="https://wiki.iccup.org/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:Vehicle&amp;action=history"/>
	<updated>2026-05-31T02:16:36Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://wiki.iccup.org/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:Vehicle&amp;diff=251&amp;oldid=prev</id>
		<title>DarkMuse в 20:21, 3 сентября 2024</title>
		<link rel="alternate" type="text/html" href="https://wiki.iccup.org/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:Vehicle&amp;diff=251&amp;oldid=prev"/>
		<updated>2024-09-03T20:21:57Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://wiki.iccup.org/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:Vehicle&amp;amp;diff=251&amp;amp;oldid=88&quot;&gt;Внесённые изменения&lt;/a&gt;</summary>
		<author><name>DarkMuse</name></author>
	</entry>
	<entry>
		<id>https://wiki.iccup.org/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:Vehicle&amp;diff=88&amp;oldid=prev</id>
		<title>DarkMuse: Новая страница: «require( &#039;strict&#039; )  local Vehicle = {}  local metatable = {} local methodtable = {}  metatable.__index = methodtable  local i18n = require( &#039;Module:i18n&#039; ):new() local TNT = require( &#039;Module:Translate&#039; ):new() local common = require( &#039;Module:Common&#039; ) local manufacturer = require( &#039;Module:Manufacturer&#039; ):new() local hatnote = require( &#039;Module:Hatnote&#039; )._hatnote local data = mw.loadJsonData( &#039;Module:Vehicle/data.json&#039; ) local config = mw.loadJsonData( &#039;Modu...»</title>
		<link rel="alternate" type="text/html" href="https://wiki.iccup.org/index.php?title=%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D1%8C:Vehicle&amp;diff=88&amp;oldid=prev"/>
		<updated>2024-08-31T13:49:54Z</updated>

		<summary type="html">&lt;p&gt;Новая страница: «require( &amp;#039;strict&amp;#039; )  local Vehicle = {}  local metatable = {} local methodtable = {}  metatable.__index = methodtable  local i18n = require( &amp;#039;Module:i18n&amp;#039; ):new() local TNT = require( &amp;#039;Module:Translate&amp;#039; ):new() local common = require( &amp;#039;Module:Common&amp;#039; ) local manufacturer = require( &amp;#039;Module:Manufacturer&amp;#039; ):new() local hatnote = require( &amp;#039;Module:Hatnote&amp;#039; )._hatnote local data = mw.loadJsonData( &amp;#039;Module:Vehicle/data.json&amp;#039; ) local config = mw.loadJsonData( &amp;#039;Modu...»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require( &amp;#039;strict&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
local Vehicle = {}&lt;br /&gt;
&lt;br /&gt;
local metatable = {}&lt;br /&gt;
local methodtable = {}&lt;br /&gt;
&lt;br /&gt;
metatable.__index = methodtable&lt;br /&gt;
&lt;br /&gt;
local i18n = require( &amp;#039;Module:i18n&amp;#039; ):new()&lt;br /&gt;
local TNT = require( &amp;#039;Module:Translate&amp;#039; ):new()&lt;br /&gt;
local common = require( &amp;#039;Module:Common&amp;#039; )&lt;br /&gt;
local manufacturer = require( &amp;#039;Module:Manufacturer&amp;#039; ):new()&lt;br /&gt;
local hatnote = require( &amp;#039;Module:Hatnote&amp;#039; )._hatnote&lt;br /&gt;
local data = mw.loadJsonData( &amp;#039;Module:Vehicle/data.json&amp;#039; )&lt;br /&gt;
local config = mw.loadJsonData( &amp;#039;Module:Vehicle/config.json&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
local lang&lt;br /&gt;
if config.module_lang then&lt;br /&gt;
	lang = mw.getLanguage( config.module_lang )&lt;br /&gt;
else&lt;br /&gt;
	lang = mw.getContentLanguage()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Wrapper function for Module:i18n.translate&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @return string If the key was not found, the key is returned&lt;br /&gt;
local function t( key )&lt;br /&gt;
	return i18n:translate( key )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Calls TNT with the given key&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @param addSuffix boolean|nil Adds a language suffix if config.smw_multilingual_text is true&lt;br /&gt;
--- @return string If the key was not found in the .tab page, the key is returned&lt;br /&gt;
local function translate( key, addSuffix, ... )&lt;br /&gt;
	return TNT:translate( &amp;#039;Module:Vehicle/i18n.json&amp;#039;, config, key, addSuffix, {...} ) or key&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Check if the current vehicle is a ground vehicle&lt;br /&gt;
---&lt;br /&gt;
--- @param smwData table&lt;br /&gt;
--- @return boolean&lt;br /&gt;
local function isGroundVehicle( smwData )&lt;br /&gt;
	local size = smwData[ t( &amp;#039;SMW_ShipMatrixSize&amp;#039; ) ]&lt;br /&gt;
&lt;br /&gt;
	return ( size ~= nil and size == translate( &amp;#039;Vehicle&amp;#039; ) ) or smwData[ t( &amp;#039;SMW_ReverseSpeed&amp;#039; ) ] ~= nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Creates the object that is used to query the SMW store&lt;br /&gt;
---&lt;br /&gt;
--- @param page string the vehicle page containing data&lt;br /&gt;
--- @return table&lt;br /&gt;
local function makeSmwQueryObject( page )&lt;br /&gt;
    local langSuffix = &amp;#039;&amp;#039;&lt;br /&gt;
    if config.smw_multilingual_text == true then&lt;br /&gt;
        langSuffix = &amp;#039;+lang=&amp;#039; .. ( config.module_lang or mw.getContentLanguage():getCode() )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
	local query = {&lt;br /&gt;
		string.format( &amp;#039;[[%s]]&amp;#039;, page ),&lt;br /&gt;
		&amp;#039;?Page image#-=image&amp;#039;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for _, queryPart in pairs( data.smw_data ) do&lt;br /&gt;
		local smwKey&lt;br /&gt;
		for key, _ in pairs( queryPart ) do&lt;br /&gt;
			if mw.ustring.sub( key, 1, 3 ) == &amp;#039;SMW&amp;#039; then&lt;br /&gt;
				smwKey = key&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local formatString = &amp;#039;?%s&amp;#039;&lt;br /&gt;
&lt;br /&gt;
		if queryPart.smw_format then&lt;br /&gt;
			formatString = formatString .. queryPart.smw_format&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		-- safeguard&lt;br /&gt;
		if smwKey ~= nil then&lt;br /&gt;
			table.insert( query, mw.ustring.format( formatString, t( smwKey ) ) )&lt;br /&gt;
&lt;br /&gt;
			if queryPart.type == &amp;#039;multilingual_text&amp;#039; then&lt;br /&gt;
				table.insert( query, langSuffix )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	table.insert( query, &amp;#039;limit=1&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
	return query&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- FIXME: This should go to somewhere else, like Module:Common&lt;br /&gt;
local function makeTimeReadable( time )&lt;br /&gt;
	if time == nil then return end&lt;br /&gt;
&lt;br /&gt;
	-- Fix for german number format&lt;br /&gt;
	if mw.ustring.find( time, &amp;#039;,&amp;#039;, 1, true ) then&lt;br /&gt;
		time = mw.ustring.gsub( time, &amp;#039;,&amp;#039;, &amp;#039;.&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if type( time ) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		time = tonumber( time, 10 )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	time = lang:formatDuration( time * 60 )&lt;br /&gt;
&lt;br /&gt;
	local regex&lt;br /&gt;
	if lang:getCode() == &amp;#039;de&amp;#039; then&lt;br /&gt;
		regex = {&lt;br /&gt;
			[ &amp;#039;%s?[Tt]agen?&amp;#039; ] = &amp;#039;d&amp;#039;,&lt;br /&gt;
			[ &amp;#039;%s?[Ss]tunden?&amp;#039; ] = &amp;#039;h&amp;#039;,&lt;br /&gt;
			[ &amp;#039;%s?[Mm]inuten?&amp;#039; ] = &amp;#039;m&amp;#039;,&lt;br /&gt;
			[ &amp;#039;%s?[Ss]ekunden?&amp;#039; ] = &amp;#039;s&amp;#039;,&lt;br /&gt;
			[ &amp;#039;,&amp;#039;] = &amp;#039;&amp;#039;,&lt;br /&gt;
			[ &amp;#039;und%s&amp;#039;] = &amp;#039;&amp;#039;&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		regex = {&lt;br /&gt;
			[ &amp;#039;%sdays*&amp;#039; ] = &amp;#039;d&amp;#039;,&lt;br /&gt;
			[ &amp;#039;%shours*&amp;#039; ] = &amp;#039;h&amp;#039;,&lt;br /&gt;
			[ &amp;#039;%sminutes*&amp;#039; ] = &amp;#039;m&amp;#039;,&lt;br /&gt;
			[ &amp;#039;%sseconds*&amp;#039; ] = &amp;#039;s&amp;#039;,&lt;br /&gt;
			[ &amp;#039;,&amp;#039;] = &amp;#039;&amp;#039;,&lt;br /&gt;
			[ &amp;#039;and%s&amp;#039;] = &amp;#039;&amp;#039;&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for pattern, replace in pairs( regex ) do&lt;br /&gt;
		time = mw.ustring.gsub( time, pattern, replace )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return time&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- FIXME: This should go to somewhere else, like Module:Common&lt;br /&gt;
--- TODO: Should we color code this for buff and debuff?&lt;br /&gt;
local function formatModifier( x )&lt;br /&gt;
	if x == nil then return end&lt;br /&gt;
	-- Fix for german number format&lt;br /&gt;
	if mw.ustring.find( x, &amp;#039;,&amp;#039;, 1, true ) then&lt;br /&gt;
		x = mw.ustring.gsub( x, &amp;#039;,&amp;#039;, &amp;#039;.&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if type( x ) == &amp;#039;string&amp;#039; then x = tonumber( x, 10 ) end&lt;br /&gt;
&lt;br /&gt;
	local diff = x - 1&lt;br /&gt;
	local sign = &amp;#039;&amp;#039;&lt;br /&gt;
	if diff == 0 then&lt;br /&gt;
		--- Display &amp;#039;None&amp;#039; instead of 0 % for better readability&lt;br /&gt;
		return translate( &amp;#039;none&amp;#039; )&lt;br /&gt;
	elseif diff &amp;gt; 0 then&lt;br /&gt;
		--- Extra space for formatting&lt;br /&gt;
		sign = &amp;#039;+ &amp;#039;&lt;br /&gt;
	elseif diff &amp;lt; 0 then&lt;br /&gt;
		sign = &amp;#039;- &amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	return sign .. tostring( math.abs( diff ) * 100 ) .. &amp;#039; %&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Request Api Data&lt;br /&gt;
--- Using current subpage name without vehicle type suffix&lt;br /&gt;
--- @return table|nil&lt;br /&gt;
function methodtable.getApiDataForCurrentPage( self )&lt;br /&gt;
	local api = require( &amp;#039;Module:Common/Api&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
	local query = self.frameArgs[ translate( &amp;#039;ARG_UUID&amp;#039; ) ] or self.frameArgs[ translate( &amp;#039;ARG_Name&amp;#039; ) ] or common.removeTypeSuffix(&lt;br /&gt;
        mw.title.getCurrentTitle().text,&lt;br /&gt;
		config.name_suffixes&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    local hardpointFilter = {}&lt;br /&gt;
    for _, filter in pairs( data.hardpoint_filter or {} ) do&lt;br /&gt;
        table.insert( hardpointFilter, &amp;#039;!&amp;#039; .. filter )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
	local success, json = pcall( mw.text.jsonDecode, mw.ext.Apiunto.get_raw( &amp;#039;v2/vehicles/&amp;#039; .. query, {&lt;br /&gt;
		include = data.includes,&lt;br /&gt;
		locale = config.api_locale,&lt;br /&gt;
        [ &amp;#039;filter[hardpoints]&amp;#039; ] = table.concat( hardpointFilter, &amp;#039;,&amp;#039; )&lt;br /&gt;
	} ) )&lt;br /&gt;
&lt;br /&gt;
	if not success or api.checkResponseStructure( json, true, false ) == false then return end&lt;br /&gt;
&lt;br /&gt;
    self.apiData = json[ &amp;#039;data&amp;#039; ]&lt;br /&gt;
    self.apiData = api.makeAccessSafe( self.apiData )&lt;br /&gt;
&lt;br /&gt;
    return self.apiData&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Base Properties that are shared across all Vehicles&lt;br /&gt;
--- @return table SMW Result&lt;br /&gt;
function methodtable.setSemanticProperties( self )&lt;br /&gt;
	local setData = {}&lt;br /&gt;
&lt;br /&gt;
	local smwCommon = require( &amp;#039;Module:Common/SMW&amp;#039; )&lt;br /&gt;
	smwCommon.addSmwProperties(&lt;br /&gt;
		self.apiData,&lt;br /&gt;
		self.frameArgs,&lt;br /&gt;
		setData,&lt;br /&gt;
		translate,&lt;br /&gt;
		config,&lt;br /&gt;
		data,&lt;br /&gt;
		&amp;#039;Vehicle&amp;#039;&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
	setData[ t( &amp;#039;SMW_Name&amp;#039; ) ] = self.frameArgs[ translate( &amp;#039;ARG_Name&amp;#039; ) ] or common.removeTypeSuffix(&lt;br /&gt;
		mw.title.getCurrentTitle().text,&lt;br /&gt;
		config.name_suffixes&lt;br /&gt;
	)&lt;br /&gt;
&lt;br /&gt;
	if type( setData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] ) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		local man = manufacturer:get( setData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] )&lt;br /&gt;
		if man ~= nil then man = man.name end&lt;br /&gt;
&lt;br /&gt;
		setData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] = man or setData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ]&lt;br /&gt;
		setData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] = mw.ustring.format( &amp;#039;[[%s]]&amp;#039;, setData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    -- Set properties with API data&lt;br /&gt;
    if self.apiData ~= nil then&lt;br /&gt;
		-- Flight ready vehicles&lt;br /&gt;
		--- Override template parameter with in-game data&lt;br /&gt;
		if self.apiData.uuid ~= nil then&lt;br /&gt;
			--- Components&lt;br /&gt;
			if self.apiData.hardpoints ~= nil and type( self.apiData.hardpoints ) == &amp;#039;table&amp;#039; and #self.apiData.hardpoints &amp;gt; 0 then&lt;br /&gt;
				local hardpoint = require( &amp;#039;Module:VehicleHardpoint&amp;#039; ):new( self.frameArgs[ translate( &amp;#039;ARG_name&amp;#039; ) ] or mw.title.getCurrentTitle().fullText )&lt;br /&gt;
				hardpoint:setHardPointObjects( self.apiData.hardpoints )&lt;br /&gt;
				hardpoint:setParts( self.apiData.parts )&lt;br /&gt;
&lt;br /&gt;
				if not self.apiData.hardpoints and type( self.apiData.components ) == &amp;#039;table&amp;#039; and #self.apiData.components &amp;gt; 0 then&lt;br /&gt;
					hardpoint:setComponents( self.apiData.components )&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			--- Commodity&lt;br /&gt;
			local commodity = require( &amp;#039;Module:Commodity&amp;#039; ):new()&lt;br /&gt;
			commodity:addShopData( self.apiData )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	mw.logObject( setData, &amp;#039;💾 [Vehicle] Set SMW data&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
	self.setData = setData&lt;br /&gt;
&lt;br /&gt;
	return mw.smw.set( setData )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Queries the SMW Store&lt;br /&gt;
--- @return table&lt;br /&gt;
function methodtable.getSmwData( self )&lt;br /&gt;
	-- Cache multiple calls&lt;br /&gt;
    if self.smwData ~= nil and self.smwData[ t( &amp;#039;SMW_Name&amp;#039; ) ] ~= nil then&lt;br /&gt;
        return self.smwData&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
	local queryName = self.frameArgs[ translate( &amp;#039;ARG_SmwQueryName&amp;#039; ) ] or&lt;br /&gt;
					  self.frameArgs[ translate( &amp;#039;ARG_Name&amp;#039; ) ] or&lt;br /&gt;
					  mw.title.getCurrentTitle().fullText&lt;br /&gt;
&lt;br /&gt;
    local smwData = mw.smw.ask( makeSmwQueryObject( queryName ) )&lt;br /&gt;
&lt;br /&gt;
    if smwData == nil or smwData[ 1 ] == nil then&lt;br /&gt;
		return hatnote( mw.ustring.format(&lt;br /&gt;
				&amp;#039;%s[[%s]]&amp;#039;,&lt;br /&gt;
				t( &amp;#039;message_error_no_data_text&amp;#039; ),&lt;br /&gt;
				t( &amp;#039;category_error_pages_with_script_errors&amp;#039; )&lt;br /&gt;
			),&lt;br /&gt;
			{ icon = &amp;#039;WikimediaUI-Error.svg&amp;#039; }&lt;br /&gt;
		)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    self.smwData = smwData[ 1 ]&lt;br /&gt;
&lt;br /&gt;
    return self.smwData&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Creates the infobox&lt;br /&gt;
function methodtable.getInfobox( self )&lt;br /&gt;
	local smwData = self:getSmwData()&lt;br /&gt;
&lt;br /&gt;
	mw.logObject( smwData, &amp;#039;⌛ [Vehicle] Loaded infobox SMW data&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
	local infobox = require( &amp;#039;Module:InfoboxNeue&amp;#039; ):new( {&lt;br /&gt;
		placeholderImage = config.placeholder_image&lt;br /&gt;
	} )&lt;br /&gt;
	local tabber = require( &amp;#039;Module:Tabber&amp;#039; ).renderTabber&lt;br /&gt;
&lt;br /&gt;
	--- SMW Data load error&lt;br /&gt;
	--- Infobox data should always have Name property&lt;br /&gt;
	if type( smwData ) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		return infobox:renderInfobox( infobox:renderMessage( {&lt;br /&gt;
			title = t( &amp;#039;message_error_no_data_title&amp;#039; ),&lt;br /&gt;
			desc = t( &amp;#039;message_error_no_data_text&amp;#039; ),&lt;br /&gt;
		} ) )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getIndicatorClass()&lt;br /&gt;
		local state = smwData[ t( &amp;#039;SMW_ProductionState&amp;#039; ) ]&lt;br /&gt;
		if state == nil then return end&lt;br /&gt;
&lt;br /&gt;
		local classMap = config.productionstate_map&lt;br /&gt;
&lt;br /&gt;
		for _, map in pairs( classMap ) do&lt;br /&gt;
			if mw.ustring.match( state, translate( map.name ) ) ~= nil then&lt;br /&gt;
				return &amp;#039;infobox__indicator--&amp;#039; .. map.color&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getManufacturer()&lt;br /&gt;
		if smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] == nil then return end&lt;br /&gt;
&lt;br /&gt;
		local mfu = manufacturer:get( smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] )&lt;br /&gt;
		if mfu == nil then return smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] end&lt;br /&gt;
&lt;br /&gt;
		return infobox.showDescIfDiff(&lt;br /&gt;
			table.concat( { &amp;#039;[[&amp;#039;, smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ], &amp;#039;|&amp;#039;, mfu.name , &amp;#039;]]&amp;#039; } ),&lt;br /&gt;
			mfu.code&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getSize()&lt;br /&gt;
		if smwData[ t( &amp;#039;SMW_Size&amp;#039; ) ] == nil then return smwData[ t( &amp;#039;SMW_ShipMatrixSize&amp;#039; ) ] end&lt;br /&gt;
&lt;br /&gt;
		local codes = { &amp;#039;XXS&amp;#039;, &amp;#039;XS&amp;#039;, &amp;#039;S&amp;#039;, &amp;#039;M&amp;#039;, &amp;#039;L&amp;#039;, &amp;#039;XL&amp;#039; }&lt;br /&gt;
		local size = smwData[ t( &amp;#039;SMW_Size&amp;#039; ) ]&lt;br /&gt;
&lt;br /&gt;
		-- For uninitialized SMW properties&lt;br /&gt;
		if type( size ) == &amp;#039;string&amp;#039; then&lt;br /&gt;
			size = tonumber( size, 10 )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		return infobox.showDescIfDiff(&lt;br /&gt;
			smwData[ t( &amp;#039;SMW_ShipMatrixSize&amp;#039; ) ],&lt;br /&gt;
			table.concat( { &amp;#039;S&amp;#039;, size, &amp;#039;/&amp;#039;, codes[ size ] } )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getSeries()&lt;br /&gt;
		local series = smwData[ t( &amp;#039;SMW_Series&amp;#039; ) ]&lt;br /&gt;
		if series == nil then return end&lt;br /&gt;
		return mw.ustring.format(&lt;br /&gt;
			&amp;#039;[[:Category:%s|%s]]&amp;#039;,&lt;br /&gt;
			mw.ustring.format( t( &amp;#039;category_series&amp;#039; ), series ),&lt;br /&gt;
			series&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--- Cost section&lt;br /&gt;
	local function getCostSection()&lt;br /&gt;
		local tabberData = {}&lt;br /&gt;
		local section&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;label1&amp;#039; ] = t( &amp;#039;label_Pledge&amp;#039; )&lt;br /&gt;
		section = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Standalone&amp;#039; ),&lt;br /&gt;
				data = infobox.showDescIfDiff( smwData[ t( &amp;#039;SMW_PledgePrice&amp;#039; ) ], smwData[ t( &amp;#039;SMW_OriginalPledgePrice&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Warbond&amp;#039; ),&lt;br /&gt;
				data = infobox.showDescIfDiff( smwData[ t( &amp;#039;SMW_WarbondPledgePrice&amp;#039; ) ], smwData[ t( &amp;#039;SMW_OriginalWarbondPledgePrice&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Availability&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_PledgeAvailability&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
		}&lt;br /&gt;
		tabberData[ &amp;#039;content1&amp;#039; ] = infobox:renderSection( { content = section, col = 2 }, true )&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;label2&amp;#039; ] = t( &amp;#039;label_Insurance&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
		section = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Claim&amp;#039; ),&lt;br /&gt;
				data = makeTimeReadable( smwData[ translate(&amp;#039;SMW_InsuranceClaimTime&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Expedite&amp;#039; ),&lt;br /&gt;
				data = makeTimeReadable( smwData[ translate(&amp;#039;SMW_InsuranceExpediteTime&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_ExpediteFee&amp;#039; ),&lt;br /&gt;
				data = smwData[ translate(&amp;#039;SMW_InsuranceExpediteCost&amp;#039; ) ],&lt;br /&gt;
				colspan = 2&lt;br /&gt;
			} ),&lt;br /&gt;
		}&lt;br /&gt;
		tabberData[ &amp;#039;content2&amp;#039; ] = infobox:renderSection( { content = section, col = 4 }, true )&lt;br /&gt;
&lt;br /&gt;
		return tabber( tabberData )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Specifications section&lt;br /&gt;
	local function getSpecificationsSection()&lt;br /&gt;
		local tabberData = {}&lt;br /&gt;
		local section&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;label1&amp;#039; ] = t( &amp;#039;label_Dimensions&amp;#039; )&lt;br /&gt;
		section = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Length&amp;#039; ),&lt;br /&gt;
				data = infobox.showDescIfDiff( smwData[ t( &amp;#039;SMW_EntityLength&amp;#039; ) ], smwData[ t( &amp;#039;SMW_RetractedLength&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Width&amp;#039; ),&lt;br /&gt;
				data = infobox.showDescIfDiff( smwData[ t( &amp;#039;SMW_EntityWidth&amp;#039; ) ], smwData[ t( &amp;#039;SMW_RetractedWidth&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Height&amp;#039; ),&lt;br /&gt;
				data = infobox.showDescIfDiff( smwData[ t( &amp;#039;SMW_EntityHeight&amp;#039; ) ], smwData[ t( &amp;#039;SMW_RetractedHeight&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Mass&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_Mass&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;content1&amp;#039; ] = infobox:renderSection( { content =section, col = 3 }, true )&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;label2&amp;#039; ] = t( &amp;#039;label_Speed&amp;#039; )&lt;br /&gt;
		section = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_ScmSpeed&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ScmSpeed&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_0ToScm&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ZeroToScmSpeedTime&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_ScmTo0&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ScmSpeedToZeroTime&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_MaxSpeed&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_MaximumSpeed&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_0ToMax&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ZeroToMaximumSpeedTime&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_MaxTo0&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_MaximumSpeedToZeroTime&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_ReverseSpeed&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ReverseSpeed&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_RollRate&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_RollRate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_PitchRate&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_PitchRate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_YawRate&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_YawRate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
		}&lt;br /&gt;
		tabberData[ &amp;#039;content2&amp;#039; ] = infobox:renderSection( { content = section, col = 3 }, true )&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;label3&amp;#039; ] = t( &amp;#039;label_Fuel&amp;#039; )&lt;br /&gt;
		section = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_HydrogenCapacity&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_HydrogenFuelCapacity&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_HydrogenIntake&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_HydrogenFuelIntakeRate&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_QuantumCapacity&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_QuantumFuelCapacity&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
		}&lt;br /&gt;
		tabberData[ &amp;#039;content3&amp;#039; ] = infobox:renderSection( { content = section, col = 2 }, true )&lt;br /&gt;
&lt;br /&gt;
		tabberData[ &amp;#039;label4&amp;#039; ] = t( &amp;#039;label_Hull&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
		section = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_CrossSection&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_CrossSectionSignatureModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Electromagnetic&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_ElectromagneticSignatureModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Infrared&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_InfraredSignatureModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Physical&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_PhysicalDamageModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Energy&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_EnergyDamageModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Distortion&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_DistortionDamageModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Thermal&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_ThermalDamageModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Biochemical&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_BiochemicalDamageModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Stun&amp;#039; ),&lt;br /&gt;
				data = formatModifier( smwData[ t( &amp;#039;SMW_StunDamageModifier&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Health&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_HealthPoint&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
		}&lt;br /&gt;
		tabberData[ &amp;#039;content4&amp;#039; ] = infobox:renderSection( { content = section, col = 3 }, true )&lt;br /&gt;
&lt;br /&gt;
		return tabber( tabberData )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	--- Other sites&lt;br /&gt;
	local function getOfficialSites()&lt;br /&gt;
		local links = {}&lt;br /&gt;
&lt;br /&gt;
		for _, site in ipairs( data.official_sites ) do&lt;br /&gt;
			local query = smwData[ translate( site.attribute ) ]&lt;br /&gt;
&lt;br /&gt;
			if query ~= nil then&lt;br /&gt;
				table.insert( links, infobox:renderLinkButton( {&lt;br /&gt;
					label = translate( site.label ),&lt;br /&gt;
					link = query&lt;br /&gt;
				} ) )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		return links&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getCommunitySites()&lt;br /&gt;
		local links = {}&lt;br /&gt;
&lt;br /&gt;
		for _, site in ipairs( data.community_sites ) do&lt;br /&gt;
			local query = smwData[ translate( site.data ) ]&lt;br /&gt;
&lt;br /&gt;
			if query ~= nil then&lt;br /&gt;
				if site.data == &amp;#039;SMW_ClassName&amp;#039; or site.data == &amp;#039;SMW_UUID&amp;#039; then&lt;br /&gt;
					query = mw.ustring.lower( query )&lt;br /&gt;
				elseif site.data == &amp;#039;SMW_ShipMatrixName&amp;#039; then&lt;br /&gt;
					query = mw.uri.encode( query, &amp;#039;PATH&amp;#039; )&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				if site.label == &amp;#039;FleetYards&amp;#039; then&lt;br /&gt;
					query = mw.ustring.lower( mw.ustring.gsub( query, &amp;#039;%%20&amp;#039;, &amp;#039;-&amp;#039; ) )&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				table.insert( links, infobox:renderLinkButton( {&lt;br /&gt;
					label = site.label,&lt;br /&gt;
					link = mw.ustring.format( site.format, query )&lt;br /&gt;
				} ) )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		return links&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	local image = self.frameArgs[ translate( &amp;#039;ARG_Image&amp;#039; ) ] or self.frameArgs[ &amp;#039;image&amp;#039; ] or smwData[ &amp;#039;image&amp;#039; ]&lt;br /&gt;
	infobox:renderImage( image )&lt;br /&gt;
&lt;br /&gt;
	infobox:renderIndicator( {&lt;br /&gt;
		data = smwData[ t( &amp;#039;SMW_ProductionState&amp;#039; ) ],&lt;br /&gt;
		desc = smwData[ t( &amp;#039;SMW_ProductionStateDesc&amp;#039; ) ],&lt;br /&gt;
		class = getIndicatorClass()&lt;br /&gt;
	} )&lt;br /&gt;
	infobox:renderHeader( {&lt;br /&gt;
		title = smwData[ t( &amp;#039;SMW_Name&amp;#039; ) ],&lt;br /&gt;
		--- e.g. Aegis Dynamics (AEGS)&lt;br /&gt;
		subtitle = getManufacturer()&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Role, Size, Series and Loaners&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		content = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Role&amp;#039; ),&lt;br /&gt;
				data = infobox.tableToCommaList( smwData[ t( &amp;#039;SMW_Role&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Size&amp;#039; ),&lt;br /&gt;
				data = getSize(),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Series&amp;#039; ),&lt;br /&gt;
				data = getSeries(),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Loaner&amp;#039; ),&lt;br /&gt;
				data = infobox.tableToCommaList( smwData[ t( &amp;#039;SMW_LoanerVehicle&amp;#039; ) ] ),&lt;br /&gt;
			} ),&lt;br /&gt;
		},&lt;br /&gt;
		col = 2&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Capacity&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		title = t( &amp;#039;label_Capacity&amp;#039; ),&lt;br /&gt;
		col = 3,&lt;br /&gt;
		content = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Crew&amp;#039; ),&lt;br /&gt;
				data = infobox.formatRange( smwData[ t( &amp;#039;SMW_MinimumCrew&amp;#039; ) ], smwData[ t( &amp;#039;SMW_MaximumCrew&amp;#039; ) ], true ),&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Cargo&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_CargoCapacity&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Stowage&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_VehicleInventory&amp;#039; ) ],&lt;br /&gt;
			} ),&lt;br /&gt;
		},&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Cost&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		title = t( &amp;#039;label_Cost&amp;#039; ),&lt;br /&gt;
		class = &amp;#039;infobox__section--tabber&amp;#039;,&lt;br /&gt;
		content = getCostSection(),&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Specifications&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		title = t( &amp;#039;label_Specifications&amp;#039; ),&lt;br /&gt;
	 	class = &amp;#039;infobox__section--tabber&amp;#039;,&lt;br /&gt;
		content = getSpecificationsSection(),&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Lore section&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		title = t( &amp;#039;label_Lore&amp;#039; ),&lt;br /&gt;
		col = 2,&lt;br /&gt;
		content = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Released&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_LoreReleaseDate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Retired&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_LoreRetirementDate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
		},&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Development section&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		title = t( &amp;#039;label_Development&amp;#039; ),&lt;br /&gt;
		col = 2,&lt;br /&gt;
		content = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_Announced&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ConceptAnnouncementDate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;label_ConceptSale&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ConceptSaleDate&amp;#039; ) ]&lt;br /&gt;
			} ),&lt;br /&gt;
		},&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Metadata section&lt;br /&gt;
	infobox:renderSection( {&lt;br /&gt;
		class = &amp;#039;infobox__section--metadata infobox__section--hasBackground&amp;#039;,&lt;br /&gt;
		content = {&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;SMW_UUID&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_UUID&amp;#039; ) ],&lt;br /&gt;
				row = true,&lt;br /&gt;
				spacebetween = true&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;SMW_ClassName&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_ClassName&amp;#039; ) ],&lt;br /&gt;
				row = true,&lt;br /&gt;
				spacebetween = true&lt;br /&gt;
			} ),&lt;br /&gt;
			infobox:renderItem( {&lt;br /&gt;
				label = t( &amp;#039;SMW_GameBuild&amp;#039; ),&lt;br /&gt;
				data = smwData[ t( &amp;#039;SMW_GameBuild&amp;#039; ) ],&lt;br /&gt;
				row = true,&lt;br /&gt;
				spacebetween = true&lt;br /&gt;
			} )&lt;br /&gt;
		},&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
	--- Actions section&lt;br /&gt;
	if smwData[ t( &amp;#039;SMW_UUID&amp;#039; ) ] then&lt;br /&gt;
		infobox:renderSection( {&lt;br /&gt;
			class = &amp;#039;infobox__section--actions infobox__section--hasBackground&amp;#039;,&lt;br /&gt;
			content = {&lt;br /&gt;
				infobox:renderItem( {&lt;br /&gt;
					icon = &amp;#039;WikimediaUI-Search.svg&amp;#039;,&lt;br /&gt;
					data = translate( &amp;#039;label_actions_find_item_title&amp;#039; ),&lt;br /&gt;
					desc = t( &amp;#039;label_actions_find_item_text&amp;#039; ),&lt;br /&gt;
					-- FIXME: Make this configurable?&lt;br /&gt;
					link = &amp;#039;https://finder.cstone.space/search/&amp;#039; .. smwData[ t( &amp;#039;SMW_UUID&amp;#039; ) ]&lt;br /&gt;
				} )&lt;br /&gt;
			}&lt;br /&gt;
		} )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
	--- Footer&lt;br /&gt;
	infobox:renderFooter( {&lt;br /&gt;
		button = {&lt;br /&gt;
			icon = &amp;#039;WikimediaUI-Globe.svg&amp;#039;,&lt;br /&gt;
			label = t( &amp;#039;label_OtherSites&amp;#039; ),&lt;br /&gt;
			type = &amp;#039;popup&amp;#039;,&lt;br /&gt;
			content = infobox:renderSection( {&lt;br /&gt;
				content = {&lt;br /&gt;
					infobox:renderItem( {&lt;br /&gt;
						label = t( &amp;#039;label_OfficialSites&amp;#039; ),&lt;br /&gt;
						data = table.concat( getOfficialSites(), &amp;#039;&amp;#039; )&lt;br /&gt;
					} ),&lt;br /&gt;
					infobox:renderItem( {&lt;br /&gt;
						label = t( &amp;#039;label_CommunitySites&amp;#039; ),&lt;br /&gt;
						data = table.concat( getCommunitySites(), &amp;#039;&amp;#039; )&lt;br /&gt;
					} ),&lt;br /&gt;
				},&lt;br /&gt;
				class = &amp;#039;infobox__section--linkButtons&amp;#039;,&lt;br /&gt;
			}, true )&lt;br /&gt;
		}&lt;br /&gt;
	} )&lt;br /&gt;
&lt;br /&gt;
	return infobox:renderInfobox( nil, smwData[ t( &amp;#039;SMW_Name&amp;#039; ) ] )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Set the frame and load args&lt;br /&gt;
--- @param frame table&lt;br /&gt;
function methodtable.setFrame( self, frame )&lt;br /&gt;
	self.currentFrame = frame&lt;br /&gt;
	self.frameArgs = require( &amp;#039;Module:Arguments&amp;#039; ).getArgs( frame )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Sets the main categories for this object&lt;br /&gt;
function methodtable.setCategories( self )&lt;br /&gt;
	if config.set_categories == false then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local size = self.smwData[ t( &amp;#039;SMW_ShipMatrixSize&amp;#039; ) ]&lt;br /&gt;
	local size_cat, pledge_cat&lt;br /&gt;
	local isGroundVehicle = isGroundVehicle( self.smwData )&lt;br /&gt;
&lt;br /&gt;
	if isGroundVehicle then&lt;br /&gt;
		--Ground vehicle has no ship matrix size currently&lt;br /&gt;
		--size_cat = &amp;#039;category_ground_vehicle_size&amp;#039;&lt;br /&gt;
		pledge_cat = &amp;#039;category_ground_vehicle_pledge&amp;#039;&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, t( &amp;#039;category_ground_vehicle&amp;#039; ) )&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		size_cat = &amp;#039;category_ship_size&amp;#039;&lt;br /&gt;
		pledge_cat = &amp;#039;category_ship_pledge&amp;#039;&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, t( &amp;#039;category_ship&amp;#039; ) )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if size ~= nil and size_cat then&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, mw.ustring.format( t( size_cat ), size ) )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if self.smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] ~= nil then&lt;br /&gt;
		local manufacturer = mw.ustring.gsub( self.smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ], &amp;#039;%[+&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
		manufacturer = mw.ustring.gsub( manufacturer, &amp;#039;%]+&amp;#039;, &amp;#039;&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, manufacturer )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if self.smwData[ t( &amp;#039;SMW_ProductionState&amp;#039; ) ] ~= nil then&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, self.smwData[ t( &amp;#039;SMW_ProductionState&amp;#039; ) ] )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if self.smwData[ t( &amp;#039;SMW_Series&amp;#039; ) ] ~= nil then&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, mw.ustring.format( t( &amp;#039;category_series&amp;#039; ), self.smwData[ t( &amp;#039;SMW_Series&amp;#039; ) ] ) )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if pledge_cat and self.smwData[ t( &amp;#039;SMW_PledgePrice&amp;#039; ) ] ~= nil then&lt;br /&gt;
		table.insert(&lt;br /&gt;
			self.categories,&lt;br /&gt;
			string.format( &amp;#039;[[Category:%s]]&amp;#039;, translate( pledge_cat ) )&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Sets the short description for this object&lt;br /&gt;
function methodtable.setShortDescription( self )&lt;br /&gt;
	local shortdesc&lt;br /&gt;
	local vehicleType&lt;br /&gt;
	local isGroundVehicle = isGroundVehicle( self.smwData )&lt;br /&gt;
&lt;br /&gt;
	if isGroundVehicle then&lt;br /&gt;
		vehicleType = t( &amp;#039;shortdesc_ground_vehicle&amp;#039; )&lt;br /&gt;
	else&lt;br /&gt;
		vehicleType = t( &amp;#039;shortdesc_ship&amp;#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if self.smwData[ t( &amp;#039;SMW_Role&amp;#039; ) ] ~= nil then&lt;br /&gt;
		local vehicleRole = self.smwData[ t( &amp;#039;SMW_Role&amp;#039; ) ]&lt;br /&gt;
		if type( vehicleRole ) == &amp;#039;table&amp;#039; then&lt;br /&gt;
			vehicleRole = table.concat( vehicleRole, &amp;#039; &amp;#039; )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		vehicleRole = mw.ustring.lower( vehicleRole )&lt;br /&gt;
		&lt;br /&gt;
		for _, noun in pairs( config.role_suffixes ) do&lt;br /&gt;
			local match = mw.ustring.find( vehicleRole, &amp;#039;%f[%a]&amp;#039; .. noun .. &amp;#039;%f[%A]&amp;#039; )&lt;br /&gt;
			--- Remove suffix from role&lt;br /&gt;
			if match then&lt;br /&gt;
				vehicleRole = mw.text.trim( mw.ustring.gsub( vehicleRole, noun, &amp;#039;&amp;#039; ) )&lt;br /&gt;
				vehicleType = noun&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		shortdesc = mw.ustring.format( &amp;#039;%s %s&amp;#039;, vehicleRole, vehicleType )&lt;br /&gt;
	else&lt;br /&gt;
		shortdesc = vehicleType&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not isGroundVehicle and self.smwData[ t( &amp;#039;SMW_ShipMatrixSize&amp;#039; ) ] ~= nil then&lt;br /&gt;
		local vehicleSize = self.smwData[ t( &amp;#039;SMW_ShipMatrixSize&amp;#039; ) ]&lt;br /&gt;
		--- Special handling for single-seat ship&lt;br /&gt;
		if self.smwData[ t( &amp;#039;SMW_MaximumCrew&amp;#039; ) ] ~= nil and self.smwData[ t( &amp;#039;SMW_MaximumCrew&amp;#039; ) ] == 1 then&lt;br /&gt;
			vehicleSize = t( &amp;#039;shortdesc_single_seat&amp;#039; )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		shortdesc = mw.ustring.format( &amp;#039;%s %s&amp;#039;, vehicleSize, shortdesc )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if self.smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ] ~= nil then&lt;br /&gt;
		local mfuname = self.smwData[ t( &amp;#039;SMW_Manufacturer&amp;#039; ) ]&lt;br /&gt;
		local man = manufacturer:get( mfuname )&lt;br /&gt;
		--- Use short name if possible&lt;br /&gt;
		if man ~= nil and man.shortname ~= nil then mfuname = man.shortname end&lt;br /&gt;
&lt;br /&gt;
		shortdesc = mw.ustring.format( t( &amp;#039;shortdesc_manufactured_by&amp;#039; ), shortdesc, mfuname )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	shortdesc = lang:ucfirst( shortdesc )&lt;br /&gt;
&lt;br /&gt;
	self.currentFrame:callParserFunction( &amp;#039;SHORTDESC&amp;#039;, shortdesc )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Save Api Data to SMW store&lt;br /&gt;
function methodtable.saveApiData( self )&lt;br /&gt;
    self:getApiDataForCurrentPage()&lt;br /&gt;
    self:setSemanticProperties()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Generates debug output&lt;br /&gt;
function methodtable.makeDebugOutput( self )&lt;br /&gt;
	local debug = require( &amp;#039;Module:Common/Debug&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
	self.smwData = nil&lt;br /&gt;
	local smwData = self:getSmwData()&lt;br /&gt;
&lt;br /&gt;
	local queryName = self.frameArgs[ translate( &amp;#039;ARG_SmwQueryName&amp;#039; ) ] or&lt;br /&gt;
					  self.frameArgs[ translate( &amp;#039;ARG_Name&amp;#039; ) ] or&lt;br /&gt;
					  mw.title.getCurrentTitle().fullText&lt;br /&gt;
&lt;br /&gt;
	return debug.collapsedDebugSections({&lt;br /&gt;
		{&lt;br /&gt;
			title = &amp;#039;SMW Query&amp;#039;,&lt;br /&gt;
			content = debug.convertSmwQueryObject( makeSmwQueryObject( queryName ) ),&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			title = &amp;#039;SMW Data&amp;#039;,&lt;br /&gt;
			content = smwData,&lt;br /&gt;
			tag = &amp;#039;pre&amp;#039;,&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			title = &amp;#039;Frame Args&amp;#039;,&lt;br /&gt;
			content = self.frameArgs,&lt;br /&gt;
			tag = &amp;#039;pre&amp;#039;,&lt;br /&gt;
		},&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- New Instance&lt;br /&gt;
function Vehicle.new( self )&lt;br /&gt;
    local instance = {&lt;br /&gt;
        categories = {}&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setmetatable( instance, metatable )&lt;br /&gt;
&lt;br /&gt;
    return instance&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Load data from api.star-citizen.wiki and save it to SMW&lt;br /&gt;
---&lt;br /&gt;
--- @param frame table Invocation frame&lt;br /&gt;
--- @return string|nil&lt;br /&gt;
function Vehicle.loadApiData( frame )&lt;br /&gt;
	local instance = Vehicle:new()&lt;br /&gt;
	instance:setFrame( frame )&lt;br /&gt;
	instance:saveApiData()&lt;br /&gt;
&lt;br /&gt;
	local debugOutput&lt;br /&gt;
	if instance.frameArgs[ &amp;#039;debug&amp;#039; ] ~= nil then&lt;br /&gt;
		local debug = require( &amp;#039;Module:Common/Debug&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
		debugOutput = debug.collapsedDebugSections({&lt;br /&gt;
			{&lt;br /&gt;
				title = &amp;#039;SMW Set Data&amp;#039;,&lt;br /&gt;
				content = mw.getCurrentFrame():callParserFunction( &amp;#039;#tag&amp;#039;, { &amp;#039;nowiki&amp;#039;, mw.dumpObject( instance.setData or {} ) } ),&lt;br /&gt;
			},&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return debugOutput&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Generates an infobox based on passed frame args and SMW data&lt;br /&gt;
---&lt;br /&gt;
--- @param frame table Invocation frame&lt;br /&gt;
--- @return string&lt;br /&gt;
function Vehicle.infobox( frame )&lt;br /&gt;
	local instance = Vehicle:new()&lt;br /&gt;
	instance:setFrame( frame )&lt;br /&gt;
&lt;br /&gt;
	local debugOutput = &amp;#039;&amp;#039;&lt;br /&gt;
	if instance.frameArgs[ &amp;#039;debug&amp;#039; ] ~= nil then&lt;br /&gt;
		debugOutput = instance:makeDebugOutput()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return tostring( instance:getInfobox() ) .. debugOutput&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- &amp;quot;Main&amp;quot; entry point for templates that saves the API Data and outputs the infobox&lt;br /&gt;
---&lt;br /&gt;
--- @param frame table Invocation frame&lt;br /&gt;
--- @return string&lt;br /&gt;
function Vehicle.main( frame )&lt;br /&gt;
	local instance = Vehicle:new()&lt;br /&gt;
	instance:setFrame( frame )&lt;br /&gt;
	instance:saveApiData()&lt;br /&gt;
&lt;br /&gt;
	local debugOutput = &amp;#039;&amp;#039;&lt;br /&gt;
	if instance.frameArgs[ &amp;#039;debug&amp;#039; ] ~= nil then&lt;br /&gt;
		debugOutput = instance:makeDebugOutput()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local infobox = tostring( instance:getInfobox() )&lt;br /&gt;
&lt;br /&gt;
	-- Only set categories and short desc if this is the page that also holds the smw attributes&lt;br /&gt;
	-- Allows outputting vehicle infoboxes on other pages without setting categories&lt;br /&gt;
	if instance.smwData ~= nil then&lt;br /&gt;
		instance:setCategories()&lt;br /&gt;
		instance:setShortDescription()&lt;br /&gt;
		-- FIXME: Is there a cleaner way?&lt;br /&gt;
		infobox = infobox .. common.generateInterWikiLinks( mw.title.getCurrentTitle().text )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return infobox .. debugOutput .. table.concat( instance.categories )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
function Vehicle.test( page )&lt;br /&gt;
	page = page or &amp;#039;300i&amp;#039;&lt;br /&gt;
&lt;br /&gt;
	local instance = Vehicle:new()&lt;br /&gt;
	instance.frameArgs = {}&lt;br /&gt;
	instance.frameArgs[ translate( &amp;#039;ARG_Name&amp;#039; ) ] = page&lt;br /&gt;
&lt;br /&gt;
	instance:saveApiData()&lt;br /&gt;
	instance:getInfobox()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
return Vehicle&lt;/div&gt;</summary>
		<author><name>DarkMuse</name></author>
	</entry>
</feed>