Dead by Daylight Wiki
mNo edit summary
m (Undo revision 119786 by Jouki (talk))
Tag: Undo
(38 intermediate revisions by the same user not shown)
Line 3: Line 3:
 
local mathOps = require("Module:MathOps")
 
local mathOps = require("Module:MathOps")
 
local utils = require("Module:Utils")
 
local utils = require("Module:Utils")
  +
local str = require("Module:Strings")
 
local c = utils -- As there is onlny one function relevant to colors I make only alias to utils Module to convenient naming "c - color"
 
local c = utils -- As there is onlny one function relevant to colors I make only alias to utils Module to convenient naming "c - color"
 
local frame = mw.getCurrentFrame()
 
local frame = mw.getCurrentFrame()
  +
local bar = "|" -- code for |
 
local nl = "\n"
 
local ntl = "|-" -- new table line
 
 
local strings = {
 
local strings = {
  +
the = cstr.the,
 
noDLC = "DLC wasn't found in DLC table in [[Module:datatable|Datatable Module]]",
 
noDLC = "DLC wasn't found in DLC table in [[Module:datatable|Datatable Module]]",
 
noSpecialTheme = "No special Theme Music",
 
noSpecialTheme = "No special Theme Music",
Line 18: Line 18:
 
theme = "Theme Music",
 
theme = "Theme Music",
 
chapter = "CHAPTER",
 
chapter = "CHAPTER",
file = "File",
+
paragraph = "paragraph",
 
retracted = "Retracted",
 
retracted = "Retracted",
dlcLink = "Downloadable Content"
+
dlcLink = "Downloadable Content",
  +
logo = "Logo",
  +
dlc = "DLC",
  +
mainArticle = "Main Article", --DLC page text under chapter title
  +
nSwitch = iclr(4, 'This DLC comes pre-installed on the Nintendo Switch version of the game.'),
  +
xps = iclr(4, 'This DLC comes pre-installed on the Console versions of the game.'),
  +
was = "was",
  +
willBe = "will be",
  +
released = "released",
  +
uknownDate = "unknown date",
  +
forString = "for",
  +
orString = "or",
  +
on = "on", -- was released "on" {date}
  +
inString = "in",
  +
adds = "adds", -- The DLC "adds" {character(s)}
  +
andString = "and",
 
}
 
}
   
fileSuffixes = {
+
local fileSuffixes = {
  +
dlcImage = "_main_header", --DLC Image
"", --Undefined
 
"_main_header", --DLC Image
+
themeMusic = "Theme Music" --DLC Theme music
" Theme Music" --DLC Theme music
 
 
}
 
}
   
Line 35: Line 49:
 
function getShortenedFileName(name)
 
function getShortenedFileName(name)
 
name = utils.RemoveSpecialCharacters(name)
 
name = utils.RemoveSpecialCharacters(name)
return getShortName(name)
+
return p.getShortName(name)
 
end
 
end
   
function getShortName(name)
+
function p.getShortName(name)
 
if name:match(":") ~= nil then
 
if name:match(":") ~= nil then
 
return name:match(".*: *(.+)")
 
return name:match(".*: *(.+)")
Line 44: Line 58:
 
return name
 
return name
 
end
 
end
 
end
  +
  +
function p.getLatestDlcId()
 
result = 0;
  +
for _, dlc in ipairs(dlcs) do
  +
if result < dlc.id then result = dlc.id end
 
end
 
return result
 
end
 
end
   
 
function resolveDlcParameter(dlc)
 
function resolveDlcParameter(dlc)
 
if dlc == nil then
 
if dlc == nil then
return getDlcByName(getShortName(mw.title.getCurrentTitle().text)) or getDlcByName(mw.title.getCurrentTitle().text)
+
return p.getDlcByName(p.getShortName(mw.title.getCurrentTitle().text)) or p.getDlcByName(mw.title.getCurrentTitle().text)
 
elseif type(dlc) == "table" then
 
elseif type(dlc) == "table" then
 
if dlc.args[1] == nil then
 
if dlc.args[1] == nil then
return getDlcByName(getShortName(mw.title.getCurrentTitle().text)) or getDlcByName(mw.title.getCurrentTitle().text) --none parameter, calling from page
+
return p.getDlcByName(p.getShortName(mw.title.getCurrentTitle().text)) or p.getDlcByName(mw.title.getCurrentTitle().text) --none parameter, calling from page
 
end
 
end
 
if type(dlc.args[1]) == nil then
 
if type(dlc.args[1]) == nil then
return getDlcByName(getShortName(mw.title.getCurrentTitle().text))
+
return p.getDlcByName(p.getShortName(mw.title.getCurrentTitle().text))
 
elseif type(dlc.args[1]) == "string" then
 
elseif type(dlc.args[1]) == "string" then
 
if tonumber(dlc.args[1]) == nil then
 
if tonumber(dlc.args[1]) == nil then
return getDlcByName(dlc.args[1])
+
return p.getDlcByName(dlc.args[1])
 
else
 
else
return getDlcById(tonumber(dlc.args[1]))
+
return p.getDlcById(tonumber(dlc.args[1]))
 
end
 
end
 
end
 
end
 
elseif type(dlc) == "string" then
 
elseif type(dlc) == "string" then
return getDlcByName(dlc)
+
return p.getDlcByName(dlc)
 
elseif type(dlc) == "number" then
 
elseif type(dlc) == "number" then
return getDlcById(dlc)
+
return p.getDlcById(dlc)
 
end
 
end
 
end
 
end
   
function getDlcByName(name)
+
function p.getDlcByName(name)
for _, dlcItem in ipairs(dlcs) do
+
for _, dlc in ipairs(dlcs) do
if name == dlcItem.name then return dlcItem end
+
if name == dlc.name then return dlc end
 
end
 
end
 
end
 
end
   
function getDlcById(id)
+
function p.getDlcById(id)
for _, dlcItem in ipairs(dlcs) do
+
for _, dlc in ipairs(dlcs) do
if id == dlcItem.id then return dlcItem end
+
if id == dlc.id then return dlc end
 
end
 
end
 
end
 
end
Line 154: Line 176:
 
end
 
end
 
end
 
end
 
function p.resolveThemeMusic() resolveThemeMusic(getDlcById(15)) end --dev remove
 
   
 
--Stranger Things Theme Music.ogg
 
--Stranger Things Theme Music.ogg
 
function resolveThemeMusic(dlc)
 
function resolveThemeMusic(dlc)
local name = strings.file .. ":" .. getShortenedFileName(dlc.name) .. fileSuffixes[3] --remake it -dev TODO
+
local name = cstr.file .. getShortenedFileName(dlc.name) .. space .. fileSuffixes.themeMusic --remake it -dev TODO
 
mw.log(name)
 
mw.log(name)
 
mw.log(mw.title.new( name .. ".ogg").exists)
 
mw.log(mw.title.new( name .. ".ogg").exists)
Line 167: Line 187:
 
for i, theme in ipairs(dlcThemes) do
 
for i, theme in ipairs(dlcThemes) do
 
if theme.id == dlc.id then
 
if theme.id == dlc.id then
if mw.title.new(strings.file .. ":" .. theme.fileName .. ".mp3").exists then return "[[" .. strings.file .. ":" .. theme.fileName .. ".mp3]]" end
+
if mw.title.new(cstr.file .. theme.fileName .. ".mp3").exists then return "[[" .. cstr.file .. theme.fileName .. ".mp3]]" end
if mw.title.new(strings.file .. ":" .. theme.fileName .. ".ogg").exists then return "[[" .. strings.file .. ":" .. theme.fileName .. ".ogg]]" end
+
if mw.title.new(cstr.file .. theme.fileName .. ".ogg").exists then return "[[" .. cstr.file .. theme.fileName .. ".ogg]]" end
 
break
 
break
 
end
 
end
Line 183: Line 203:
   
 
function resolveDlcCategory(dlc)
 
function resolveDlcCategory(dlc)
if dlc.retracted ~= true then
+
if not dlc.retracted and dlc.retracted ~= false then
 
return dlcCategories[dlc.category]
 
return dlcCategories[dlc.category]
 
else
 
else
Line 190: Line 210:
 
end
 
end
   
function p.getImageFileNameByDlc(id) mw.log(getImageFileNameByDlc(getDlcById(id))) end --dev remove
+
function p.getImageFileNameByDlc(id) mw.log(getImageFileNameByDlc(p.getDlcById(id))) end --dev remove
   
 
function getImageFileNameByDlc(dlc)
 
function getImageFileNameByDlc(dlc)
Line 198: Line 218:
 
end
 
end
 
end
 
end
return utils.resolveImageName(utils.resolveFileName(dlc.name) .. fileSuffixes[2])
+
return utils.resolveImageName(utils.resolveFileName(dlc.name) .. fileSuffixes.dlcImage)
 
end
 
end
   
Line 206: Line 226:
 
local result = ""
 
local result = ""
   
result = result .. "{|class=\"wikitable\" style=\"float:right;\"" .. nl
+
result = result ..
result = result .. "|- style=\"font-size: 24px;\"" .. nl
+
'{| class="wikitable" style="float:right;"' .. nl ..
  +
ntl .. 'style="font-size: 24px;"' .. nl ..
result = result .. "! width=\"300px\" align=\"center\" colspan=\"2\" | '''" .. dlc.name .. "'''" .. nl
+
hl .. 'width="350px" align="center" colspan="2"' .. tl .. b(dlc.name) .. nl .. ntl .. nl ..
result = result .. ntl .. nl
 
result = result .. "| align=\"center\" width=\"300px\" height=\"50px\" colspan=\"2\" |[[" .. strings.file .. ":" .. getImageFileNameByDlc(dlc) .. "|300px]]" .. nl
+
tl .. 'class="center" width="350px" height="50px" colspan="2"' .. tl .. link(cstr.file .. getImageFileNameByDlc(dlc) .. tl .. '300px') .. nl .. ntl .. nl ..
 
tl .. 'width="100px"' .. tl .. b(strings.rd) .. '|| width="200px"' .. tl .. utils.resolveDateTime(dlc.rDate) .. nl .. ntl .. nl
result = result .. ntl .. nl
 
  +
if dlc.retracted then
result = result .. "| width=\"100px\" | '''" .. strings.rd .. "'''|| width=\"200px\" | " .. utils.resolveDateTime(dlc.rDate) .. nl
 
result = result .. ntl .. nl
+
result = result .. tl .. b(strings.retracted) .. nl .. tl .. utils.resolveDateTime(dlc.retracted) .. nl .. ntl .. nl
  +
end
result = result .. "| width=\"100px\" | '''" .. strings.cat .. "'''|| width=\"200px\" | " .. resolveDlcCategory(dlc) .. nl
 
result = result .. ntl .. nl
+
result = result ..
result = result .. "| width=\"100px\" rowspan = " .. getCountDlcCosts(dlc) .. " | '''" .. strings.cost .. "''' || width=\"200px\" " .. getCostTable(dlc) .. nl
+
tl .. tl .. b(strings.cat) .. '|| width="200px"' .. tl .. resolveDlcCategory(dlc) .. nl .. ntl .. nl ..
  +
tl .. 'rowspan = ' .. getCountDlcCosts(dlc) .. tl .. b(strings.cost) .. ' || width="200px" ' .. getCostTable(dlc) .. nl .. ntl .. nl ..
result = result .. ntl .. nl
 
result = result .. "| width=\"100px\" | '''" .. strings.theme .. "'''|| width=\"200px\" |" .. resolveThemeMusic(dlc) .. nl
+
tl .. tl .. b(strings.theme) .. '|| width="200px"' .. tl .. resolveThemeMusic(dlc) .. nl .. ntl .. nl ..
 
hl .. 'align="center" colspan="2"' .. tl .. resolveShopLink(dlc) .. nl ..
result = result .. ntl .. nl
 
  +
"|}"
result = result .. "! width=\"300px\" align=\"center\" colspan=\"2\" | " .. resolveShopLink(dlc) .. nl
 
result = result .. "|}"
 
   
mw.log(mw.dumpObject(result))
+
mw.log(result)
 
return result
 
return result
 
end
 
end
Line 241: Line 260:
 
for _, dlcItem in ipairs(dlcs) do
 
for _, dlcItem in ipairs(dlcs) do
 
if dlcItem.category == 1 then
 
if dlcItem.category == 1 then
result = result .. "* [[" .. strings.chapter .. " " .. ToRomanNumerals(counter) .. ": " .. dlcItem.name .. "]]" .. nl
+
result = result .. "* [[" .. strings.chapter .. " " .. utils.toRomanNumerals(counter) .. ": " .. dlcItem.name .. "]]" .. nl
 
counter = counter + 1
 
counter = counter + 1
 
end
 
end
Line 252: Line 271:
 
function p.resolveDlcTableMainPage()
 
function p.resolveDlcTableMainPage()
 
local result = ""
 
local result = ""
local name
+
local name, fileName, linkPage
local fileName
 
 
 
 
utils.sortDlcByCategory(dlcs)
 
utils.sortDlcByCategory(dlcs)
Line 260: Line 278:
 
result = result .. '<div class="heading">[[' .. strings.dlcLink .. ']]</div>'
 
result = result .. '<div class="heading">[[' .. strings.dlcLink .. ']]</div>'
 
result = result .. '<div class="fplinks">'
 
result = result .. '<div class="fplinks">'
  +
  +
local latestId = p.getLatestDlcId()
 
for i, dlc in ipairs(dlcs) do
 
for i, dlc in ipairs(dlcs) do
 
if not dlc.skip then
 
if not dlc.skip then
 
name = dlc.name or strings.noDLc
 
name = dlc.name or strings.noDLc
fileName = resolveDlcCapsuleFileNameByDlc(dlc)
+
fileName = resolveDlcCapsuleFileNameByDlc(dlc, latestId)
  +
linkPage = (name .. (dlc.multiName and space .. brackets(strings.dlc) or cstr.empty))
if filename == "" then
 
fileName = "UnknownDLC.png"
 
else
 
fileName = fileName .. '.jpg'
 
end
 
 
 
result = result .. '<div class="fplink dlcMainPageBox plainlinks image"><div class="box"><div class="row"><div class="cell">'
+
result = result .. '<div class="fplink dlcMainPageBox plainlinks image"><div class="box"><div class="row"><div class="cell">' ..
result = result .. '<div class="image">[[File:' .. fileName .. '|link=' .. name .. ']]</div>'
+
'<div class="image">' .. file(fileName .. '|link=' .. linkPage) .. '</div>' ..
result = result .. '<div class="dlcLink link">[[' .. name .. ']]</div></div></div></div></div>'
+
'<div class="dlcLink link">' .. link(linkPage .. tl .. name) .. '</div></div></div></div></div>'
 
end
 
end
 
end
 
end
Line 281: Line 297:
 
end
 
end
   
function resolveDlcCapsuleFileNameByDlc(dlc)
+
function resolveDlcCapsuleFileNameByDlc(dlc, latestId)
 
local fileConst = "_Capsule"
 
local fileConst = "_Capsule"
 
local fileName
 
local fileName
 
 
fileName = getCapsuleFileNameFromTableById(dlc.id) or (utils.resolveFileName(dlc.name) .. fileConst)
+
fileName = utils.resolveFileName(dlc.name) .. fileConst
if fileName == "" or not utils.isValidFileName(fileName, 'jpg') then
 
fileName = ""
 
end
 
 
 
 
if dlc.id == latestId and not utils.isValidFileName(fileName, "jpg") then
return fileName
 
 
return 'UnknownDLC.png'
  +
end
  +
 
return fileName .. '.jpg'
 
end
 
end
   
Line 300: Line 317:
 
end
 
end
 
return nil
 
return nil
  +
end
  +
  +
--If the iconlink for currrency doesn't work, add new field 'plural' in ccy table in Datatable module: plural = "Bloodpoints" (for Bloodpoint currency)
  +
function p.resolveDlcPage(args)
  +
local dlcTypes = resolveDlcTypes(utils.resolveParameter(args))
  +
local header = utils.resolveParameter(args):upper()
  +
local result = cstr.empty
  +
  +
utils.sortDlcByCategory(dlcs)
 
local counter = 1
  +
for _, dlc in ipairs(dlcs) do
  +
for _, dlcType in ipairs(dlcTypes) do
  +
if dlc.category == dlcType then
  +
result = result .. getDlcArticle(dlc, counter, header)
  +
counter = counter + 1
  +
break
  +
end
  +
end
  +
end
  +
  +
mw.log(result)
  +
return result
  +
end
  +
  +
function getDlcArticle(dlc, number, header)
  +
return
  +
'==== ' .. header .. space .. utils.toRomanNumerals(number) .. colon .. space .. dlc.name .. ' ====' .. nl ..
  +
link(cstr.file .. getDlcLogo(dlc) .. '.png|thumb|400x150px') .. nlp ..
  +
i(strings.mainArticle .. colon .. space .. link(dlc.name)) .. nlp ..
  +
strings.the .. space .. b(dlc.name) .. space .. strings.dlc .. space .. getDlcTime(dlc) .. space .. getDlcCosts(dlc) .. space .. getDlcReleaseDate(dlc) .. dot .. nlp ..
  +
strings.the .. space .. strings.dlc .. space .. strings.adds ..space .. getCharacterString(dlc) .. dot .. dnl ..
  +
((dlc.flags and getAdditionalNote(dlc)) or cstr.empty)
  +
end
  +
  +
function getDlcLogo(dlc)
  +
return strings.logo .. space .. utils.FirstLetterLower(utils.resolveFileName(dlc.name, false, true))
  +
end
  +
  +
function getDlcTime(dlc)
  +
result = strings.released
  +
if dlc.rDate ~= nil and utils.IsFullDateTime(dlc.rDate) and utils.toTimestamp(dlc.rDate) < utils.today() then
 
result = strings.was .. space .. result
  +
else
  +
if utils.getDatePart(dlc.rDate, "month") and utils.getMonth(dlc.rDate) < utils.getMonth(utils.today()) then
  +
result = strings.was .. space .. result
 
else
  +
result = strings.willBe .. space .. result
  +
end
  +
end
  +
return result
  +
end
  +
  +
function getDlcReleaseDate(dlc)
  +
result = cstr.empty
  +
if dlc.rDate ~= nil then
  +
result = ((utils.IsFullDateTime(dlc.rDate) and strings.on) or strings.inString) .. space .. utils.resolveDateTime(dlc.rDate, true)
  +
end
  +
return result
  +
end
  +
  +
function getDlcCosts(dlc)
  +
if type(dlc.cost) == "string" then return strings.forString .. space .. dlc.cost end
  +
local result = cstr.empty
  +
if dlc.cost ~= nil then
 
if #dlc.cost > 0 then
 
result = result .. strings.forString .. space
  +
end
  +
  +
utils.sortRealCcyFirst(dlc.cost)
  +
for i, cost in ipairs(dlc.cost) do
  +
local currency = utils.getCcyById(cost.ccy)
  +
if not currency.gc then --real currency
 
result = result .. currency.symbol .. cost.value
  +
else --game currency
  +
result = result .. utils.commaFormat(cost.value) .. space .. utils.IconLink(currency.plural or currency.name .. 's')
  +
end
  +
if i < #dlc.cost then --add ' or ' if there will be more currencies
  +
result = result .. space .. strings.orString .. space
  +
end
  +
end
  +
end
  +
return result
  +
end
  +
  +
function getCharacterString(dlc)
  +
local characters = utils.getCharsByDlc(dlc)
  +
local result = cstr.empty
  +
  +
utils.sortCharsKillersFirst(characters)
  +
for i, character in ipairs(characters) do
  +
result = result .. utils.IconLink((not character.power and character.shortName or character.name) or character.name)
  +
  +
if i + 1 == #characters then
  +
result = result .. space .. strings.andString .. space
  +
elseif i < #characters then --add comma if there will be more currencies
 
result = result .. comma .. space
  +
end
  +
end
  +
return result
  +
end
  +
  +
function getAdditionalNote(dlc)
  +
local result = cstr.empty
  +
for _, flag in ipairs(dlc.flags) do
  +
if flag == "xps" then result = result .. strings.xps .. dnl
  +
elseif flag == "switch" then result = result .. strings.nSwitch .. dnl
  +
end
  +
end
  +
return result
  +
end
  +
  +
function resolveDlcTypes(dlcTypeString)
  +
if dlcTypeString == strings.chapter:lower() then return {1, 7}
  +
elseif dlcTypeString == strings.paragraph:lower() then return {2}
  +
--elseif dlcTypeString == "clothing pack" then return {3}
  +
--elseif dlcTypeString == "soundtrack" then return {4}
  +
--elseif dlcTypeString == "character pack" then return {5}
  +
elseif dlcTypeString == "other" then return {6}
  +
end
  +
return {0} --not found
 
end
 
end
   

Revision as of 19:24, 13 May 2022


local p = {}
local data = require("Module:Datatable")
local mathOps = require("Module:MathOps")
local utils = require("Module:Utils")
local str = require("Module:Strings")
local c = utils -- As there is onlny one function relevant to colors I make only alias to utils Module to convenient naming "c - color"
local frame = mw.getCurrentFrame()

local strings = {
	the = cstr.the,
	noDLC = "DLC wasn't found in DLC table in [[Module:datatable|Datatable Module]]",
	noSpecialTheme = "No special Theme Music",
	noSteamLink = "No linked Store Page",
	sp = "Store Page",
	rd = "Release Date",
	cat = "Category",
	cost = "Cost",
	theme = "Theme Music",
	chapter = "CHAPTER",
	paragraph = "paragraph",
	retracted = "Retracted",
	dlcLink = "Downloadable Content",
	logo = "Logo",
	dlc = "DLC",
	mainArticle = "Main Article", --DLC page text under chapter title
	nSwitch = iclr(4, 'This DLC comes pre-installed on the Nintendo Switch version of the game.'),
	xps = iclr(4, 'This DLC comes pre-installed on the Console versions of the game.'),
	was = "was",
	willBe = "will be",
	released = "released",
	uknownDate = "unknown date",
	forString = "for",
	orString = "or",
	on = "on", -- was released "on" {date}
	inString = "in",
	adds = "adds", -- The DLC "adds" {character(s)}
	andString = "and",
}

local fileSuffixes = {
		dlcImage = "_main_header", --DLC Image
		themeMusic = "Theme Music" --DLC Theme music
	}

function p.getCallTable(parameter)
	return mw.dumpObject(parameter)
end

function getShortenedFileName(name)
	name = utils.RemoveSpecialCharacters(name)
	return p.getShortName(name)
end

function p.getShortName(name)
	if name:match(":") ~= nil then
		return name:match(".*: *(.+)")
	else
		return name
	end
end

function p.getLatestDlcId()
	result = 0;
	for _, dlc in ipairs(dlcs) do
		if result < dlc.id then result = dlc.id end
	end
	return result
end

function resolveDlcParameter(dlc)
	if dlc == nil then
		return p.getDlcByName(p.getShortName(mw.title.getCurrentTitle().text)) or p.getDlcByName(mw.title.getCurrentTitle().text)
	elseif type(dlc) == "table" then
		if dlc.args[1] == nil then 
			return p.getDlcByName(p.getShortName(mw.title.getCurrentTitle().text)) or p.getDlcByName(mw.title.getCurrentTitle().text) --none parameter, calling from page
		end
		if type(dlc.args[1]) == nil then 
			return p.getDlcByName(p.getShortName(mw.title.getCurrentTitle().text))
		elseif type(dlc.args[1]) == "string" then
			if tonumber(dlc.args[1]) == nil then 
				return p.getDlcByName(dlc.args[1])
			else 
				return p.getDlcById(tonumber(dlc.args[1]))
			end
		end
	elseif type(dlc) == "string" then
		return p.getDlcByName(dlc)
	elseif type(dlc) == "number" then
		return p.getDlcById(dlc)
	end
end

function p.getDlcByName(name)
	for _, dlc in ipairs(dlcs) do
		if name == dlc.name then return dlc end
	end
end

function p.getDlcById(id)
	for _, dlc in ipairs(dlcs) do
		if id == dlc.id then return dlc end
	end
end

function p.getCountOfDlcs()
	return utils.getCount("dlc")
end

function p.getCountOfChapters()
	return utils.getCount("chapter")
end

function p.getCountOfParagraphs()
	return utils.getCount("paragraph")
end

function p.getCountOfClothingDlcs()
	return utils.getCount("clothing")
end

function p.getCountOfSoundtracks()
	return utils.getCount("ost")
end

function p.getCountOfCharacterDlcs()
	return utils.getCount("character")
end

function getCountOfCosts(dlc)
	for i, _ in ipairs(dlc.cost) do end
	return i
end

function getCostTable(dlc)
	local result = ""
	
	if type(dlc.cost) == "string" then
		return "| " .. dlc.cost	
	end
	for i, cost in ipairs(dlc.cost) do
		local ccy = getCurrencyById(cost.ccy)
		
		if cost.value == 0 then
			cost.value = "-"
		end
		result = result .. "| " 
		if ccy.gc then
			result = result .. utils.commaFormat(cost.value) .. " " .. frame:expandTemplate{ title = "IconLink", args = { ccy.name  .. "s"} } -- #1: calling IconLink template #2: the 's' makes plural version of currency,
		else
			result = result .. ccy.symbol .. cost.value
		end
		if dlc.cost[i + 1] ~= nil then
			result = result .. nl .. ntl .. nl
		end
	end
	
	return result
end

function getCountDlcCosts(dlc)
	if type(dlc.cost) == "string" then return 1 end
	return #dlc.cost
end

function getCurrencyById(id)
	for _, ccyItem in ipairs(ccy) do
		if ccyItem.id == id then return ccyItem end
	end
end

function resolveCurrency(ccy)
	if ccy.gc then
		return 
	else
		
	end
end

--Stranger Things Theme Music.ogg
function resolveThemeMusic(dlc)
	local name = cstr.file .. getShortenedFileName(dlc.name) .. space .. fileSuffixes.themeMusic --remake it -dev TODO
	mw.log(name)
	mw.log(mw.title.new( name .. ".ogg").exists)
	if mw.title.new( name .. ".mp3").exists then return "[[" .. name .. ".mp3]]" end
	if mw.title.new( name .. ".ogg").exists then return "[[" .. name .. ".ogg]]" end
	
	for i, theme in ipairs(dlcThemes) do
		if theme.id == dlc.id then
			if mw.title.new(cstr.file .. theme.fileName .. ".mp3").exists then return "[[" .. cstr.file .. theme.fileName .. ".mp3]]" end
			if mw.title.new(cstr.file .. theme.fileName .. ".ogg").exists then return "[[" .. cstr.file .. theme.fileName .. ".ogg]]" end
			break
		end
	end
	return strings.noSpecialTheme
end

function resolveShopLink(dlc)
	if dlc.link ~= nil then
		return "[https://store.steampowered.com/app/" .. dlc.link .. " " .. strings.sp .. "]"
	end
	return strings.noSteamLink
end

function resolveDlcCategory(dlc)
	if not dlc.retracted and dlc.retracted ~= false then
		return dlcCategories[dlc.category]
	else
		return strings.retracted .. " " .. dlcCategories[dlc.category]
	end
end

function p.getImageFileNameByDlc(id) mw.log(getImageFileNameByDlc(p.getDlcById(id))) end --dev remove

function getImageFileNameByDlc(dlc)
	for _, dlcImage in ipairs(dlcImages) do
		if dlc.id == dlcImage.id then
			return utils.resolveImageName(dlcImage.cover)
		end
	end
	return utils.resolveImageName(utils.resolveFileName(dlc.name) .. fileSuffixes.dlcImage)
end

function p.resolveDlcTable(dlc)
	dlc = resolveDlcParameter(dlc)
	if dlc == nil then return "'''" .. frame:expandTemplate{title = "clr", args = { "gold", strings.noDlc}} .. "'''" .. nl end
	local result = ""

	result = result .. 
		'{| class="wikitable" style="float:right;"' .. nl ..
		ntl .. 'style="font-size: 24px;"' .. nl ..
		hl .. 'width="350px" align="center" colspan="2"' .. tl .. b(dlc.name) .. nl .. ntl .. nl ..
		tl .. 'class="center" width="350px" height="50px" colspan="2"' .. tl .. link(cstr.file .. getImageFileNameByDlc(dlc) .. tl .. '300px') .. nl .. ntl .. nl ..
		tl .. 'width="100px"' .. tl .. b(strings.rd) .. '|| width="200px"' .. tl .. utils.resolveDateTime(dlc.rDate) .. nl .. ntl .. nl
	if dlc.retracted then
		result = result .. tl .. b(strings.retracted) .. nl .. tl .. utils.resolveDateTime(dlc.retracted) .. nl .. ntl .. nl
	end
	result = result ..
		tl .. tl .. b(strings.cat) .. '|| width="200px"' .. tl .. resolveDlcCategory(dlc) .. nl .. ntl .. nl ..
		tl .. 'rowspan = ' .. getCountDlcCosts(dlc) .. tl .. b(strings.cost) .. ' || width="200px" ' .. getCostTable(dlc) .. nl .. ntl .. nl ..
		tl .. tl .. b(strings.theme) .. '|| width="200px"' .. tl .. resolveThemeMusic(dlc) .. nl .. ntl .. nl ..
		hl .. 'align="center" colspan="2"' .. tl .. resolveShopLink(dlc) .. nl ..
		"|}"

	mw.log(result)
	return result
end

--DEV
function try(f, catch_f)
	local status, exception = pcall(f)
	if not status then
		catch_f(exception)
	end
end

function p.getListOfDlcChapters()
	local result = "";
	local counter = 1;
	
	for _, dlcItem in ipairs(dlcs) do
		if dlcItem.category == 1 then
			result = result .. "* [[" .. strings.chapter .. " " .. utils.toRomanNumerals(counter) .. ": " .. dlcItem.name .. "]]" .. nl
			counter = counter + 1
		end
	end
	
	mw.log(result)
	return result
end

function p.resolveDlcTableMainPage()
	local result = ""
	local name, fileName, linkPage
	
	utils.sortDlcByCategory(dlcs)

	result = result .. '<div class="fpbox" id="fpDlcs" style="text-align: center;">'
	result = result .. '<div class="heading">[[' .. strings.dlcLink .. ']]</div>'
	result = result .. '<div class="fplinks">'
	
	local latestId = p.getLatestDlcId()
	for i, dlc in ipairs(dlcs) do
		if not dlc.skip then
			name = dlc.name or strings.noDLc
			fileName = resolveDlcCapsuleFileNameByDlc(dlc, latestId)
			linkPage = (name .. (dlc.multiName and space .. brackets(strings.dlc) or cstr.empty))
			
			result = result .. '<div class="fplink dlcMainPageBox plainlinks image"><div class="box"><div class="row"><div class="cell">' ..
				'<div class="image">' .. file(fileName .. '|link=' .. linkPage) .. '</div>' ..
				'<div class="dlcLink link">' .. link(linkPage .. tl .. name) .. '</div></div></div></div></div>'
		end
	end
	result = result .. '</div>'
	result = result .. '</div>'

	return result
end

function resolveDlcCapsuleFileNameByDlc(dlc, latestId)
	local fileConst = "_Capsule"
	local fileName
	
	fileName = utils.resolveFileName(dlc.name) .. fileConst
	
	if dlc.id == latestId and not utils.isValidFileName(fileName, "jpg") then
		return 'UnknownDLC.png'
	end

	return fileName .. '.jpg'
end

function getCapsuleFileNameFromTableById(id)
	for j, image in ipairs(dlcCapsuleImages) do
		if image.id == id then
			return image.image
		end
	end
	return nil
end

--If the iconlink for currrency doesn't work, add new field 'plural' in ccy table in Datatable module: plural = "Bloodpoints" (for Bloodpoint currency)
function p.resolveDlcPage(args)
	local dlcTypes = resolveDlcTypes(utils.resolveParameter(args))
	local header = utils.resolveParameter(args):upper()
	local result = cstr.empty
	
	utils.sortDlcByCategory(dlcs)
	local counter = 1
	for _, dlc in ipairs(dlcs) do
		for _, dlcType in ipairs(dlcTypes) do
			if dlc.category == dlcType then
				result = result .. getDlcArticle(dlc, counter, header)
				counter = counter + 1
				break	
			end
		end
	end
	
	mw.log(result)
	return result	
end

function getDlcArticle(dlc, number, header)
	return
		'==== ' .. header .. space ..  utils.toRomanNumerals(number) .. colon .. space .. dlc.name .. ' ====' .. nl ..
		link(cstr.file .. getDlcLogo(dlc) .. '.png|thumb|400x150px') .. nlp ..
		i(strings.mainArticle .. colon .. space .. link(dlc.name)) .. nlp ..
		strings.the .. space .. b(dlc.name) .. space .. strings.dlc .. space .. getDlcTime(dlc) .. space .. getDlcCosts(dlc) .. space .. getDlcReleaseDate(dlc) .. dot .. nlp ..
		strings.the .. space .. strings.dlc .. space .. strings.adds ..space .. getCharacterString(dlc) .. dot .. dnl ..
		((dlc.flags and getAdditionalNote(dlc)) or cstr.empty)
end

function getDlcLogo(dlc)
	return strings.logo .. space .. utils.FirstLetterLower(utils.resolveFileName(dlc.name, false, true))
end

function getDlcTime(dlc)
	result = strings.released
	if dlc.rDate ~= nil and utils.IsFullDateTime(dlc.rDate) and utils.toTimestamp(dlc.rDate) < utils.today() then
		result = strings.was .. space .. result
	else
		if utils.getDatePart(dlc.rDate, "month") and utils.getMonth(dlc.rDate) < utils.getMonth(utils.today()) then
			result = strings.was .. space .. result
		else
			result = strings.willBe .. space .. result
		end
	end
	return result
end

function getDlcReleaseDate(dlc)
	result = cstr.empty
	if dlc.rDate ~= nil then
		result = ((utils.IsFullDateTime(dlc.rDate) and strings.on) or strings.inString) .. space .. utils.resolveDateTime(dlc.rDate, true)
	end
	return result
end

function getDlcCosts(dlc)
	if type(dlc.cost) == "string" then return strings.forString .. space .. dlc.cost end
	local result = cstr.empty
	if dlc.cost ~= nil then
		if #dlc.cost > 0 then
			result = result .. strings.forString .. space
		end
		
		utils.sortRealCcyFirst(dlc.cost)
		for i, cost in ipairs(dlc.cost) do
			local currency = utils.getCcyById(cost.ccy)
			if not currency.gc then --real currency
				result = result .. currency.symbol .. cost.value
			else --game currency
				result = result .. utils.commaFormat(cost.value) .. space .. utils.IconLink(currency.plural or currency.name .. 's')
			end
			if i < #dlc.cost then --add ' or ' if there will be more currencies
				result = result .. space .. strings.orString .. space
			end
		end
	end
	return result
end

function getCharacterString(dlc)
	local characters = utils.getCharsByDlc(dlc)
	local result = cstr.empty
	
	utils.sortCharsKillersFirst(characters)
	for i, character in ipairs(characters) do
		result = result .. utils.IconLink((not character.power and character.shortName or character.name) or character.name)

		if i + 1 == #characters then
			result = result .. space .. strings.andString .. space
		elseif i < #characters then --add comma if there will be more currencies
			result = result .. comma .. space
		end
	end
	return result
end

function getAdditionalNote(dlc)
	local result = cstr.empty
	for _, flag in ipairs(dlc.flags) do
		if		flag == "xps" then result = result .. strings.xps .. dnl
		elseif	flag == "switch" then result = result .. strings.nSwitch .. dnl
		end
	end
	return result
end

function resolveDlcTypes(dlcTypeString)
	if		dlcTypeString == strings.chapter:lower() then return {1, 7}
	elseif	dlcTypeString == strings.paragraph:lower() then return {2}
	--elseif	dlcTypeString == "clothing pack" then return {3}
	--elseif	dlcTypeString == "soundtrack" then return {4}
	--elseif	dlcTypeString == "character pack" then return {5}
	elseif	dlcTypeString == "other" then return {6}
	end
	return {0} --not found
end

return p