Модуль:Infoboxes/Patch
Перейти к навигации
Перейти к поиску
Для документации этого модуля может быть создана страница Модуль:Infoboxes/Patch/doc
local Arkitecture = require( 'Module:Arkitecture' )
local ColumnTypes = Arkitecture.Cargo.ColumnTypes
local ParameterTypes = Arkitecture.ParameterTypes
local ParameterConstraint = Arkitecture.ParameterConstraints
local Text = require( 'Module:Infoboxes/Patch/strings' )
-- TODO: publish via Module:Version
local function parseVersion( str, defaultGame, defaultPlatform )
if str == nil then
return nil
end
local game, platform, major, minor = str:match( '([%w :]+)/Патч/(%w+) (%d+)%.(%d+)' )
if major == nil then
game, major, minor = str:match( '([%w :]+)/Патч/(%d+)%.(%d+)' )
end
if major == nil then
platform, major, minor = str:match( '(%w+) (%d+)%.(%d+)' )
end
if major == nil then
major, minor = str:match( '(%d+)%.(%d+)' )
end
if major == nil or minor == nil then
return nil
end
return game or defaultGame, platform or defaultPlatform or 'PC', major, minor
end
return Arkitecture.makeInfoboxRenderer{
RequiredLibraries = {
'Module:Arkitecture/Common library',
},
PrivateComponents = {
GameBar = Arkitecture.Component{
render = function ( self, ctx )
return Arkitecture.Html.Element{
tag = 'div',
classes = 'arkitect-game-bar',
Arkitecture.File{
name = ctx.instance.Game .. '.png',
width = 16,
link = ctx.instance.Game,
},
Arkitecture.Html.NonBreakingSpace,
Arkitecture.Link( ctx.instance.Game ),
}
end
},
TargetCell = Arkitecture.Component{
render = function ( self, ctx, instance )
if instance.Date == nil then
return ctx:expandComponent{
Component = 'Checkmark',
Value = false,
}
end
return {
ctx:expandComponent{
Component = 'Checkmark',
CheckedLabel = instance.UseNoUnofficialWording
and Text.SECTION_AVAILABILITY_ROW_SERVER_OFFICIALS_ONLY
or nil,
Value = true,
},
Arkitecture.Html.NewLine,
Arkitecture.Date( instance.Date ),
}
end
},
},
CargoSetup = {
Patch = {
Unprefixed = true,
{ 'Game',
ColumnTypes.STRING,
Values = ParameterTypes.GAME.AllowedValues,
},
{ 'Major', ColumnTypes.INTEGER, },
{ 'Minor', ColumnTypes.INTEGER, },
{ 'ClientReleaseDate',
ColumnTypes.DATE,
Optional = true,
},
{ 'ServerReleaseDate',
ColumnTypes.DATE,
Optional = true,
},
{ 'Platform',
ColumnTypes.STRING,
Values = {
'PC',
'Xbox',
'PlayStation',
'Switch',
},
},
},
},
Parameters = {
game = ParameterTypes.GAME,
platform = ParameterTypes.STRING,
major = ParameterTypes.INTEGER,
minor = ParameterTypes.INTEGER,
type = {
ParameterTypes.STRING,
AllowedValues = { 'major', 'minor', 'initial' },
},
changelist = {
ParameterTypes.INTEGER,
Optional = true,
},
date = {
ParameterTypes.DATE,
Optional = true,
},
client = {
ParameterTypes.DATE,
Optional = true,
},
server = {
ParameterTypes.DATE,
Optional = true,
},
unofficials = {
ParameterTypes.BOOL,
Default = true,
},
clientNumber = {
ParameterTypes.STRING,
Optional = true,
},
nintendoVersion = {
ParameterTypes.STRING,
Optional = true,
},
previous = ParameterTypes.GAME_VERSION,
next = ParameterTypes.GAME_VERSION,
},
_makeVersionStringFromRecord = function ( self, record )
if record.Platform == 'PC' then
return string.format( '%s/Патч/%d.%d', record.Game, record.Major, record.Minor )
end
return string.format( '%s/Патч/%s %d.%d', record.Game, record.Platform, record.Major, record.Minor )
end,
_makeShortVersionStringFromRecord = function ( self, record )
return string.format( '%d.%d', record.Major, record.Minor )
end,
_LinkVersion = function ( self, ctx, record )
if record then
if type( record ) == 'string' then
local game, platform, major, minor = parseVersion( record, ctx:getParameter( 'game' ), ctx:getParameter( 'platform' ) )
record = {
Game = game,
Platform = platform,
Major = major,
Minor = minor,
}
end
return string.format( '[[%s|%d.%d]]', self:_makeVersionStringFromRecord( record ), record.Major, record.Minor )
end
return nil
end,
injectParameters = function ( self, ctx )
local title = mw.title.getCurrentTitle().text
local game, platform, major, minor = parseVersion( title )
if major == nil or minor == nil then
error( 'Titles of patch articles should follow either of these formats: "[.../]major.minor", '
.. '"[.../]platform major.minor".' )
end
local out = {
game = game,
platform = platform,
major = major,
minor = minor,
}
if ctx:getParameter( 'date' ) ~= nil then
out.client = ctx:getParameter( 'date' )
out.server = ctx:getParameter( 'date' )
end
-- Fetch previous and next version from Cargo
-- TODO: forced chronology needs to be exported
if not ctx:hasParameterValueUnchecked( 'previous' ) then
local results = mw.ext.cargo.query( ctx:getCargoTablePrefix() .. 'Patch', 'Game, Platform, Major, Minor', {
where = string.format(
'Game = \'%s\' AND Platform = \'%s\' AND ( ( Major < %d ) OR ( Major = %d AND Minor < %d ) )',
game, platform, major, major, minor
),
orderBy = 'GREATEST( COALESCE( ClientReleaseDate, 0 ), COALESCE( ServerReleaseDate, 0 ) ) DESC, '
.. 'Major DESC, Minor DESC',
limit = 1
} )
if #results ~= 0 then
out.previous = self:_makeVersionStringFromRecord( results[1] )
end
end
if not ctx:hasParameterValueUnchecked( 'next' ) then
local results = mw.ext.cargo.query( ctx:getCargoTablePrefix() .. 'Patch', 'Game, Platform, Major, Minor', {
where = string.format(
'Game = \'%s\' AND Platform = \'%s\' AND ( ( Major > %d ) OR ( Major = %d AND Minor > %d ) )',
game, platform, major, major, minor
),
orderBy = 'GREATEST( COALESCE( ClientReleaseDate, 0 ), COALESCE( ServerReleaseDate, 0 ) ) ASC, '
.. 'Major ASC, Minor ASC',
limit = 1
} )
if #results ~= 0 then
out.next = self:_makeShortVersionStringFromRecord( results[1] )
end
end
out.__NEXT = ( function ()
local out = {}
-- If not specified already, determine type
if not ctx:hasParameterValueUnchecked( 'type' ) then
local _, _, prevMajor, prevMinor = parseVersion( ctx:getParameter( 'previous' ), game, platform )
out.type = prevMajor == nil and 'initial'
or prevMajor == major and 'minor'
or 'major'
end
return out
end )
return out
end,
---
--- @class PatchInfo
--- @field platform string
--- |"'PC'"
--- |"'Xbox'"
--- |"'PS'"
--- |"'Switch'"
--- @field major integer
--- @field minor integer
---
---
--- Packs all information identifying a patch into a single structure. Ideally, we'd retrieve it from the title
--- directly rather than relying on wikitext-end to give it to us. But this is easier (... and faster) than parsing
--- the title in Lua...
--- @param ctx Arkitecture.RendererContext
--- @return PatchInfo
_packPatchInfo = function ( self, ctx )
return {
game = ctx:getParameter( 'game' ),
platform = ctx:getParameter( 'platform' ),
major = ctx:getParameter( 'major' ),
minor = ctx:getParameter( 'minor' ),
}
end,
PLATFORM_ICONS = {
PS = 'PS.svg',
Switch = 'Nintendo Switch.svg',
TSOTF = 'TSotF_Logo.png'
},
_makePlatformIcons = function ( self, pInfo )
local width = 22
if self.PLATFORM_ICONS[pInfo.platform] then
return Arkitecture.File{
name = self.PLATFORM_ICONS[pInfo.platform],
width = width,
link = false
}
elseif pInfo.platform == 'Xbox' then
return table.concat( {
Arkitecture.File{
name = 'Microsoft Store.svg',
width = width,
link = false
},
Arkitecture.File{
name = 'Xbox One.svg',
width = width,
link = false
}
}, Arkitecture.Html.NonBreakingSpace )
elseif pInfo.platform == 'PC' then
-- Steam, always
local icons = {
Arkitecture.File{
name = 'Steam.svg',
width = width,
link = false
}
}
-- EOS, at or after 311.74
if pInfo.major > 311 or ( pInfo.major == 311 and pInfo.minor >= 74 ) then
icons[#icons + 1] = Arkitecture.File{
name = 'Epic Games.svg',
width = width,
link = false
}
end
-- Stadia, at 678 or after 337, but before 355.16 (January 18th, 2022)
if pInfo.major == 678 or ( pInfo.major > 337 and not ( pInfo.major > 355 or pInfo.major == 355
and pInfo.minor >= 16 ) ) then
icons[#icons + 1] = Arkitecture.File{
name = 'Stadia.svg',
width = width,
link = false
}
end
return table.concat( icons, Arkitecture.Html.NonBreakingSpace )
end
error( 'Platform not recognised in _makePlatformIcons, someone did not update it when adding a platform: '
.. pInfo.platform )
end,
getSetup = function ( self, ctx )
local pInfo = self:_packPatchInfo( ctx )
local gameCode = ctx:getGameId()
return {
{
{
Component = 'GameBar',
Game = ctx:getParameter( 'game' ),
},
{
Component = 'SegmentedHeader',
LeftValue = self:_makePlatformIcons( pInfo ),
Name = string.format( '%d.%d', pInfo.major, pInfo.minor ),
},
{
Component = 'NamedDataRow',
Dimensions = '25x75',
Name = Text.ROW_CLIENT_BUILD_NUMBER,
Value = ctx:getParameter( 'clientNumber' ),
},
{
Component = 'NamedDataRow',
Dimensions = '25x75',
Name = Text.ROW_P4_CHANGELIST,
Tooltip = Text.ROW_P4_CHANGELIST_TOOLTIP,
Value = ctx:getParameter( 'changelist' ),
},
{
Component = 'NamedDataRow',
Dimensions = '25x75',
Name = Text.ROW_TYPE,
Value = ( {
initial = Text.ROW_TYPE_INITIAL_RELEASE,
major = Text.ROW_TYPE_MAJOR,
minor = Text.ROW_TYPE_MINOR,
} )[ctx:getParameter( 'type' )],
},
{
Component = 'FloatingNote',
Value = ctx:getParameter( 'nintendoVersion' )
and string.format( Text.NOTE_NINTENDO_VERSION_F, ctx:getParameter( 'nintendoVersion' ) )
or nil,
},
},
{
Caption = Text.SECTION_AVAILABILITY,
Component = 'NamedDataTable2x2',
{
Name = Text.SECTION_AVAILABILITY_ROW_CLIENT,
Value = ctx:expandComponent{
Component = 'TargetCell',
Date = ctx:getParameter( 'client' )
},
},
{
Name = Text.SECTION_AVAILABILITY_ROW_SERVER,
Value = ctx:expandComponent{
Component = 'TargetCell',
UseNoUnofficialWording = not ctx:getParameter( 'unofficials' ),
Date = ctx:getParameter( 'server' )
},
},
},
{
Caption = Text.SECTION_CHRONOLOGY,
gameCode == 'ASA' and {
Component = 'NamedDataRow',
Name = Text.SECTION_CHRONOLOGY_ROW_PREVIOUS,
Value = self:_LinkVersion( ctx, ctx:getParameter( 'previous' ) ),
} or '',
gameCode == 'ASA' and {
Component = 'NamedDataRow',
Name = Text.SECTION_CHRONOLOGY_ROW_NEXT,
Value = self:_LinkVersion( ctx, ctx:getParameter( 'next' ) ),
} or '',
},
{
SideEffect = true,
Arkitecture.JoinCategory( Text['CATEGORY_' .. gameCode .. '_' .. ctx:getParameter( 'platform' ):upper()]
or Text['CATEGORY_' .. gameCode .. '_FALLBACK'] ),
},
{
Component = 'NewCargoRow',
Table = 'Patch',
Game = ctx:getParameter( 'game' ),
Platform = ctx:getParameter( 'platform' ),
Major = ctx:getParameter( 'major' ),
Minor = ctx:getParameter( 'minor' ),
ClientReleaseDate = ctx:getParameter( 'client' ),
ServerReleaseDate = ctx:getParameter( 'server' ),
}
}
end
}