Modul:Musikcharts

Modul:Musikcharts

Modul:Musikcharts
Vorlagenprogrammierung Diskussionen Lua Test Unterseiten
Modul Deutsch English

Modul: Dokumentation

Diese Seite enthält Code in der Programmiersprache Lua. Einbindungszahl Cirrus


local p = {}
	
	-- require all country-related functions and data
	local countryfunctions = require ("Module:Musikcharts/countries")
	-- require formatted certification icons
	local certicon = require ("Module:Musikcharts/certifications")
	-- require local labels
	local label = require ("Module:Musikcharts/locallabels")
	-- require local parameter names
	local param = require ("Module:Musikcharts/localparameters")
	-- require local css classes
	local cssclass = require ("Module:Musikcharts/localclasses")
	
	-- require date-related functions
	local luckier, DateTime = pcall( require, "Module:DateTime" )
	if type( DateTime ) == "table" then
    	DateTime = DateTime.DateTime()
	else
    	-- DateTime contains error
    	return "<span class='error'>" .. DateTime .. "</span>"
	end
	
	-- require parameter check
	local lucky, TemplatePar = pcall( require, "Modul:TemplatePar" )
	if type( TemplatePar ) == "table" then
	    TemplatePar = TemplatePar.TemplatePar()
	else
	    -- TemplatePar contains error
	    return "<span class='error'>" .. TemplatePar .. "</span>"
	end
	
	local templatestyles = "Vorlage:Charttabelle/styles.css"


-- Charttabelle - chart table
p.charttablehead = function (frame, christmas)
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- service links
	local slnosources = "<span style='display:none'>[[Template:Charttabelle/Wartung/ohne Quellen]]</span>"
	local sltoomanycountries = "<span style='display:none'>[[Template:Charttabelle/Wartung/zu viele Länder]]</span>"
	local slwrongrformat = "<span style='display:none'>[[Template:Charttabelle/Wartung/falsche Art]]</span>"
	local slmonths = "<span style='display:none'>[[Template:Charttabelle/Wartung/Monatsdaten]]</span>"
	local slchartsnonexist = "<span style='display:none'>[[Template:Charttabelle/Wartung/Charts inexistent]]</span>"
	local slparameterissue = "<span style='display:none'>[[Template:Charttabelle/Wartung/Parameterfehler]]</span>"
	-- /
	
	-- get countries
	local countries = {}
	local i = 0
	for k, v in ipairs (parameters) do
		v = mw.text.trim( v )
		if #v > 0 then
			i = i + 1
			countries[i] = v
		end
	end
	
	if #countries > 8 then return "<span class='error'>" .. label.toomanycountries .. "</span>" .. sltoomanycountries end
	-- /
	
	-- direct template parameters
	local source				= parameters[param.sources]
	if source then
		source = mw.text.trim (source)
			:gsub ("\n", "")
	end
	local rformat				= parameters[param.rformat]
	local sortable				= parameters[param.sortable]
	local grey					= parameters[param.grey]
	local extra 				= parameters[param.extra]
	local titleaddition 		= parameters[param.titleadd]
	local givenwidth			= parameters[param.width]
	local content				= parameters[param.content] or ""
	-- /
	
	-- headers
	local headerclass			= cssclass.headerrow
	local mobheaderclass		= cssclass.headercell
	if grey then
		headerclass 			= cssclass.headerrowgrey
		mobheaderclass			= cssclass.headercellgrey
	end
	-- /
	
	-- parameter check
	local templatename
	if christmas then
		templatename			= "[[Vorlage:Weihnachtscharttabelle|Weihnachtscharttabelle]]"
	else
		templatename			= "[[Vorlage:Charttabelle|Charttabelle]]"
	end
	local parametercheck = {
		["mandatory"]			= {param.content, "1"},
		["optional"]			= {param.sources, param.rformat, param.sortable, param.grey, "2", "3", "4", "5", "6", "7", "8"},
		["template"]			= templatename
	}
	if not christmas then
		table.insert (parametercheck["optional"], param.extra)
		table.insert (parametercheck["optional"], param.titleadd)
		table.insert (parametercheck["optional"], param.width)
	end
	local parameterissue		= TemplatePar.check(parametercheck)
	-- /
	
	-- table width
	local tablewidth = {
		["1"]  = { "250", "320" },
		["1e"] = { "245", "220", "175" },
		["2"]  = { "300", "320" },
		["2e"] = { "285", "220", "175" },
		["3"]  = { "350", "300" },
		["3e"] = { "315", "210", "160" },
		["4"]  = { "400", "270" },
		["4e"] = { "345", "200", "160" }
	}
	local width = "1" -- default width
	local colnumber = 1 + #countries
	if not christmas then
		colnumber = colnumber + 2
	end
	if tablewidth[givenwidth] then
		width = givenwidth
	end
	if extra then
		width = width .. "e"
		colnumber = colnumber + 1
	end
	-- /
	
	-- test for monthly chart data
	local months
	if string.match (content, label.mt .. "%)") then
		months = true
	end
	-- /
	
	-- check number of rows
	local rownumber
	content, rownumber = string.gsub (content, "class='newcharttablerow' ", "")
	-- /
	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	
	-- parameter check error
	if parameterissue then
		ret = ret .. "\n" .. parameterissue .. slparameterissue
	end
	-- /
	
	-- start building table
	ret = ret .. "\n{| class='wikitable charts-table"
	if sortable then
		ret = ret .. " sortable"
	end
	if rownumber > 8 then
		ret = ret .. " charts-stickyhead"
	end
	if grey then
		ret = ret .. " charts-zebra"
	else
		ret = ret .. " charts-zebragrey"
	end
	if christmas then
		ret = ret .. " charts-xmas"
	end
	ret = ret .. "' style='text-align:center;"
	ret = ret .. "'\n|-\n! style='width:25px;' class='" .. mobheaderclass .. " " .. headerclass .. "' rowspan='2' | "
	if christmas then
		ret = ret .. label.period
	else
		ret = ret .. label.year
		ret = ret .. "\n! style='width:" .. tablewidth[width][1] .. "px;' class='" .. mobheaderclass .. " " .. headerclass .. "' rowspan='2'| " .. label.title
		if titleaddition then
			ret = ret .. "<br /><span style='font-size:smaller;font-style:italic;'>" .. titleaddition .. "</span>"
		elseif rformat == label.singles then
			ret = ret .. "<br /><span style='font-size:smaller;font-style:italic;'>" .. label.album .. "</span>"
		end
	end
	ret = ret .. "\n! class='" .. mobheaderclass .. "' colspan='" .. #countries .. "'| "
	ret = ret .. "<span style='white-space:nowrap;'><span class='" .. cssclass.hidemobile .. " " .. cssclass.certcontainer .. "'><span class='" .. cssclass.certtooltip .. "'>Höchstplatzierung, Gesamtwochen"
	if months then
		ret = ret .. "/&#8203;&#8209;monate" -- zero-width space + nonbreaking hyphen
	end
	if not christmas then
		ret = ret .. ", Auszeichnung"
	end
	ret = ret .. "<i></i></span>"
	if #countries > 1 then
		ret = ret .. label.chartpositions
	else
		ret = ret .. label.charts
	end
	ret = ret .. "</span><span class='" .. cssclass.mobileonly .. "'>" .. label.chartpositions .. "</span>"
	
	-- sources
	ret = ret .. (source or slnosources) .. "</span>"
	-- /
	
	-- insert service links
	if rformat then
		if not rformat == "" and not rformat == label.singles and not rformat == label.albums then
			ret = ret .. slwrongrformat
		end
	end
	if months then
		ret = ret .. slmonths
	end
	-- /
	
	-- mobile header
	ret = ret .. "<span class='" .. cssclass.mobileonly .. " charts-mh'><br />"
	if christmas then
		ret = ret .. "(Periode, "
	else
		ret = ret .. "(Jahr, Titel, "
		if titleaddition then
			if string.match (titleaddition, "<br") then
				titleaddition = string.gsub (titleaddition, "%s?<br%s?/?>%s?", " / ")
			end
			if string.match (titleaddition, "%(") then
				titleaddition = titleaddition
					:gsub ("%(", "[")
					:gsub ("%)", "]")
			end
			ret = ret .. "<i>" .. titleaddition .. "</i>, "
		elseif rformat == label.singles then
			ret = ret .. "<i>Album</i>, "
		end
	end
	ret = ret .. "Plat&shy;zie&shy;rungen, Wo&shy;chen"
	if months then
		ret = ret .. "/Mo&shy;nate"
	end
	if not christmas then
		ret = ret .. ", Aus&shy;zeich&shy;nungen, Anmer&shy;kungen"
		if extra then
			local mobileextra = extra
			if string.match (mobileextra, "<br") then
				mobileextra = string.gsub (mobileextra, "%s?<br%s?/?>%s?", " / ")
			end
			if string.match (mobileextra, "%(") then
				mobileextra = mobileextra
					:gsub ("%(", "[")
					:gsub ("%)", "]")
			end
			ret = ret .. ", " .. mobileextra
		end
	end
	ret = ret .. ")</span>"
	-- /

	if not christmas then
		ret = ret .. "\n! style='width:" .. tablewidth[width][2] .. "px;' class='" .. mobheaderclass .. " " .. headerclass
		if sortable then
			ret = ret .. " unsortable"
		end
		ret = ret .. "' rowspan='2' | " .. label.notes
		if extra then
			ret = ret .. "\n! style='width:" .. tablewidth[width][3] .. "px;' rowspan='2' class='"
			if sortable then
				ret = ret .. "unsortable "
			end
			ret = ret .. mobheaderclass .. " " .. headerclass .. "' |" .. extra
		end
	end
	
	-- mobile header for colspans/rowspans
	if string.match (content, "class%='charts%-moa'") then
		ret = ret .. "\n! style='font-style:italic;border:none;margin-top:-1px;' class='" .. cssclass.mobileonlycell .. " charts-mh' |" .. "[&uarr;]: gemeinsam behandelt mit vorhergehendem Eintrag;<br />[&larr;]: in beiden Charts platziert"
	end
	-- /
	
	-- country columns
	ret = ret .. "\n|- class='" .. headerclass .. "'"
	ret = ret .. countryfunctions.countryhead( {countries = countries}, rformat, sortable, grey )
	
	-- / end of table
	
	-- content substitutions
	for c = 1, #countries do
		local country = countries[c]
		
		-- correct no1 links for US R&B and Country singles
		if rformat == label.singles then
			if country == "US-RB" then
				content = string.gsub (content, "%[%[Liste der Nummer%-eins%-R&B%-Alben in den USA %(%d%d%d%d%)|<b>1</b>]]<!%-%-Albumcharts%-%->", "<b>1</b>")
			elseif country == "US-C" then
				content = string.gsub (content, "%[%[Liste der Nummer%-eins%-Country%-Alben in den USA %(%d%d%d%d%)|<b>1</b>]]<!%-%-Albumcharts%-%->", "<b>1</b>")
			end
		end
		-- /
		
		-- link individual country names in mobile countrydisplay
		country = country:gsub("</?small>", ""):gsub("%[%[Datei:.-]]", "")
		if string.match (country, "]]") then
			local indivcountry, indivcountrysuffix = string.match (country, "%[%[(.+)]](.*)")
	--		if string.match (indivcountry, "<br\s?/?>") then
	--			indivcountry, indivcountrysuffix = string.match (indivcountry, "(.+)<br\s?/?>(.+)")
	--		end
			if string.match (indivcountry, "%[%[") then
				indivcountry = string.match (indivcountry, "%[%[(.+)")
			end
			if indivcountrysuffix == ")" then indivcountrysuffix = "" end
			local indivcountrynolink = string.match (indivcountry, "|(.+)") or ""
			
			local indivcountrymatch = "<span class='indivcountry" .. c .. "'>.-</span>"
			local indivcountrynolinkmatch = "<span class='indivcountrynolink" .. c .. "'>.-</span>"
			
			content = content
				:gsub (indivcountrymatch, "[[" .. indivcountry .. "]]" .. indivcountrysuffix)
				:gsub (indivcountrynolinkmatch, indivcountrynolink .. indivcountrysuffix)
		end
		-- /
	end

	-- correct chart links for singles in mobile countrydisplay
	if rformat == label.singles then
		content = countryfunctions.singlechartlink (content)
	end
	
	-- correct marking of non-existing charts
	if string.match (content, "charts%-nxa") or string.match (content, "charts%-nxs") then
		if rformat == label.singles then
			content = content
				:gsub ("charts%-nxa", "")
				:gsub ("<!%-%- Albumcharts inexistent %-%->", "")
		else
			content = content
				:gsub ("charts%-nxs", "")
				:gsub ("<!%-%- Singlecharts inexistent %-%->", "")
		end
		if string.match (content, "<!%-%- Albumcharts inexistent %-%->") then
			content = string.gsub (content, "<!%-%- Albumcharts inexistent %-%->", "")
			ret = ret .. slchartsnonexist
		end
		if string.match (content, "<!%-%- Singlecharts inexistent %-%->") then
			content = string.gsub (content, "<!%-%- Singlecharts inexistent %-%->", "")
			ret = ret .. slchartsnonexist
		end
	end
	
	-- correct colours for grey styles
	if grey then
		content = content
			:gsub ("charts%-redst", "charts-redstg")
			:gsub ("charts%-mc'", "charts-mcg'")
			:gsub (" charts%-yelst", "")
	end
	-- /
	
	-- delete empty class arguments and single row/colspans
	content = content
		:gsub (" class=''", "")
		:gsub (" rowspan='1'", "")
		:gsub (" colspan='1'", "")
	-- /
	
	-- correct full-width colspans
	if colnumber ~= 12 then -- Charthinweis
		content = content
			:gsub ('colspan="12"', 'colspan="' .. colnumber .. '"')
			:gsub ("colspan='12'", "colspan='" .. colnumber .. "'")
	end
	if not extra then -- Chartauswertung
		content = content
			:gsub ("rowspan='3' colspan='2'", "rowspan='3'")
	end
	-- /
	
	-- delete unused sortkeys
	if not sortable then
		content = content
			:gsub ("data%-sort%-value='.-'", "")
		end
	-- /
	
	-- better explain colspans in mobile view
	local function replacer(text)
		return (string.gsub (text, "(\n|.-colspan=.-|.-<span class='charts%-mo.-<span.-class='charts%-)moa'>%[(.-)&uarr;(%]</span>)", "%1mo' style='font-size:smaller;font-style:italic;'> %[%2&larr;%3"))
	end
	if string.match (content, "&uarr;%]") then
		content = string.gsub (content, "\n|[^\n]*charts%-mo[^\n]*<span[^\n]*charts%-moa[^\n]*", replacer)
	end
		-- visibility in hidden cells
		content = string.gsub (content, "(\n|[^\n]*)charts%-hm([^\n]*)' | &mdash;([^\n]*<span[^\n]*charts%-moa)", "%1charts-aup%2' | <span class='" .. cssclass.hidemobile .. "'>&mdash;</span>%3")
	-- /

	ret = ret .. "\n|- \n" .. content .. "\n|- \n|}"
	
	-- add explanation for non-existing charts
	if string.match (content, "charts%-nxa") or string.match (content, "charts%-nxs") then
		ret = ret .. "<span style='font-size:smaller;' class='" .. cssclass.hidemobile .. " charts-hidp'><span class='charts-nxa' style='padding:2px;border:solid .5px grey;font-style:italic;'>" .. label.greyhatch .. "</span>: " .. label.nonexistingcharts .. "</span>"
	end
	-- /

	return frame:preprocess (ret)
end



-- Chartauswertung - chart statistics
p.chartstatistics = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- service links
	local sltoomanycountries = "<span style='display:none'>[[Template:Charttabelle/Wartung/zu viele Länder]]</span>"
	local slwrongrformat = "<span style='display:none'>[[Template:Charttabelle/Wartung/falsche Art]]</span>"
	local slparameterissue = "<span style='display:none'>[[Template:Charttabelle/Wartung/Parameterfehler]]</span>"
	-- /
	
	-- get countries
	local countries = {}
	local i = 0
	for k, v in ipairs (parameters) do
		v = mw.text.trim( v )
		if #v > 0 then
			i = i + 1
			countries[i] = v
		end
	end
	
	if #countries > 8 then return "|-\n| colspan='12' | <span class='error'>Chartauswertung: Zu viele Länder definiert!</span>" .. sltoomanycountries end
	-- /
	
	-- direct template parameters
	local rformat = parameters[param.rformat]
	local comment = parameters[param.comment]
	local istable = parameters[param.istable]
	local grey = parameters[param.grey]
	-- /
	
	local greycountry
	if grey then
		greycountry = "g"
	else
		greycountry = ""
	end
	
	-- parameter check
	local parametercheck = {
		["mandatory"] = { "1" },
		["optional"] = { param.rformat, param.comment, param.extra, param.istable, param.grey, "2", "3", "4", "5", "6", "7", "8" },
		["template"] = "Chartauswertung"
	}
	-- /
	
	-- start building table
	local ret
	if istable then
		ret = "{| class='wikitable charts-table"
		if grey then
			ret = ret .. " charts-zebra"
		else
			ret = ret .. " charts-zebragrey2"
		end
		ret = ret .. "' style='text-align:center;break-inside:avoid;'\n |- class='"
		if grey then
			ret = ret .. "charts-trhg"
		else
			ret = ret .. "charts-trh"
		end
		ret = ret .. "' \n ! style='width:200px;'"
		if grey then
			ret = ret .. " class='charts-thg' |"
		else
			ret = ret .. " class='charts-th' |"
		end
		
		-- country columns
		ret = ret .. countryfunctions.countryhead( {countries = countries }, rformat, nil, grey )
		-- /
		
		ret = ret .. "\n|- style='border-top:none;'"
	else
		ret = "|- class='sortbottom charts-redst'\n| class='" .. cssclass.hidemobile .. "' rowspan='3'|"
	end

	ret = ret .. "\n| style='text-align:left;'"
	if istable then
		ret = ret .. " class='charts-sth" .. greycountry .. "'"
	end
	ret = ret .. " |"
	if rformat then
		ret = ret .. "Nummer-eins-" .. rformat
	else
		ret = ret .. "Nummer eins"
	end
	for c = 1, #countries do
		local country = countries[c]
		local n = param.no1 .. "_" .. country
		table.insert (parametercheck["optional"], n)
		local No1 = parameters[n]
		if No1 == "" or No1 == nil then
			No1 = "&mdash;"
		end
		
		-- mobile country display
		ret = ret .. "\n| "
		if No1 == "&mdash;" and not istable then
			ret = ret .. "class='" .. cssclass.hidemobile .. "' | "
		end
		ret = ret .. "<span class='charts-mc" .. greycountry .. "'>" .. countryfunctions.countrycol (country, c, nil, nil, rformat) .. "</span>"
		-- /
		
		ret = ret .. No1
		
		-- mobile country display width balance
		ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true, nil, rformat) .. "</span>"
		-- /
	end

	if not istable then
		ret = ret .. "\n| rowspan='3' colspan='2' style='text-align:left; font-size:smaller;' "
		if comment then
			ret = ret .. "| " .. comment
		else
			ret = ret .. "class='" .. cssclass.hidemobile .. "' |"
		end
	end

	ret = ret .. "\n|- "
	if not istable then
		ret = ret .. "class='sortbottom charts-redst' "
	end
	ret = ret .. "\n| style='text-align:left;'"
	if istable then
		ret = ret .. " class='charts-sth" .. greycountry .. "'"
	end
	ret = ret .. " |"
	if rformat then
		ret = ret .. "Top-10-" .. rformat
	else
		ret = ret .. "in den Top 10"
	end
	for c = 1, #countries do
		local country = countries[c]
		local t = param.t10 .. "_" .. country
		table.insert (parametercheck["optional"], t)
		local Top10 = parameters[t]
		if Top10 == "" or Top10 == nil then
			Top10 = "&mdash;"
		end
		ret = ret .. "\n| "
		if Top10 == "&mdash;" and not istable then
			ret = ret .. "class='" .. cssclass.hidemobile .. "' | "
		end
		
		-- mobile country display
		ret = ret .. "<span class='charts-mc" .. greycountry .. "'>" .. countryfunctions.countrycol (country, c) .. "</span>"
		-- /
		
		ret = ret .. Top10
		
		-- mobile country display width balance
		ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true) .. "</span>"
		-- /
	end

	ret = ret .. "\n|- "
	if istable then
		ret = ret .. "style='font-weight:bold;'"
		if not grey then ret = ret .. " class='charts-yelst'" end
	else
		ret = ret .. "class='sortbottom charts-redst'"
	end
	ret = ret .. "\n| style='text-align:left;'"
	if istable then
		ret = ret .. " class='charts-sth" .. greycountry .. "'"
	end
	ret = ret .. " |" .. ((rformat .. " ") or "") .. "in den Charts"
	for c = 1, #countries do
		local country = countries[c]
		local g = param.tot .. "_" .. country
		table.insert (parametercheck["optional"], g)
		local Total = parameters[g]
		if Total == "" or Total == nil then
			Total = "&mdash;"
		end
		ret = ret .. "\n| "
		if Total == "&mdash;" and not istable then
			ret = ret .. "class='" .. cssclass.hidemobile .. "' | "
		end
		
		-- mobile country display
		ret = ret .. "<span class='charts-mc" .. greycountry .. "'>" .. countryfunctions.countrycol (country, c) .. "</span>"
		-- /
		
		ret = ret .. Total
		
		-- mobile country display width balance
		ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true) .. "</span>"
		-- /
	end
	
	-- insert service links
	if rformat then
		if not rformat == "" and not rformat == "Singles" and not rformat == "Alben" then
			ret = ret .. slwrongrformat
		end
	end
	-- /

	if istable then
		ret = ret .. "\n|}"
	end
	
	-- parameter check error
	local parameterissue = TemplatePar.check(parametercheck)
	if parameterissue then
		if not istable then 
			ret = ret .. "\n|-\n| colspan='12' class='charts-redst' | " 
		else 
			ret = ret .. "\n" 
		end
		ret = ret .. parameterissue .. slparameterissue
	end
	-- /

	return frame:preprocess (ret)
end



-- Weihnachtscharttabelle - x-mas chart table
p.xcharttablehead = function (frame)
	
	return p.charttablehead (frame, true)
end



-- Charteintrag - chart table entry
p.charttablerow = function (frame, christmas)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- get countries
	local countries = {}
	local i = 0
	for k, v in ipairs (parameters) do
		v = mw.text.trim( v )
		if #v > 0 then
			i = i + 1
			countries[i] = v
		end
	end
	-- /
	
	-- direct template parameters and x-mas distinction
	local year
	if christmas then
		year = parameters[param.period]
	else
		year = parameters[param.year]
	end
	local colour = parameters[param.colour]
	local unnumberedtitle
	if christmas then
		unnumberedtitle = "title"
	else
		unnumberedtitle = parameters[param.title]
	end
	-- /
	
	-- parameter check
	local templatename
	if christmas then
		templatename = "[[Vorlage:Weihnachtscharteintrag|Weihnachtscharteintrag]]"
	else
		templatename = "[[Vorlage:Charteintrag|Charteintrag]]"
	end
	local parametercheck = {
		["mandatory"] = { "1" },
		["optional"] = { "2", "3", "4", "5", "6", "7", "8" },
		["template"] = templatename
	}
	if christmas then
		table.insert (parametercheck["optional"], param.period)
	else
		table.insert (parametercheck["optional"], param.year)
	end
	-- /
	
	-- row numbering
	if unnumberedtitle then
		parameters[param.colour .. "1"] = parameters[param.colour]
		table.insert (parametercheck["optional"], param.colour)
		parameters[param.title .. "1"] = unnumberedtitle
		parameters[param.album .. "1"] = parameters[param.album]
		parameters[param.titleadd .. "1"] = parameters[param.titleadd]
		for c = 1, #countries do
			local ps = param.position .. "_" .. countries[c]
			table.insert (parametercheck["optional"], ps)
			local ps1 = param.position .. "_" .. countries[c] .. "1"
			parameters[ps1] = parameters[ps]
			local w = param.weeks .. "_" .. countries[c]
			table.insert (parametercheck["optional"], w)
			local w1 = param.weeks .. "_" .. countries[c] .. "1"
			parameters[w1] = parameters[w]
			local m = param.months .. "_" .. countries[c]
			table.insert (parametercheck["optional"], m)
			local m1 = param.months .. "_" .. countries[c] .. "1"
			parameters[m1] = parameters[m]
			local y = param.year .. "_" .. countries[c]
			table.insert (parametercheck["optional"], y)
			local y1 = param.year .. "_" .. countries[c] .. "1"
			parameters[y1] = parameters[y]
			local s = param.columns .. "_" .. countries[c]
			table.insert (parametercheck["optional"], s)
			local s1 = param.columns .. "_" .. countries[c] .. "1"
			parameters[s1] = parameters[s]
			local z = param.rows .. "_" .. countries[c]
			table.insert (parametercheck["optional"], z)
			local z1 = param.rows .. "_" .. countries[c] .. "1"
			parameters[z1] = parameters[z]
			local a = param.certification .. "_" .. countries[c]
			table.insert (parametercheck["optional"], a)
			local a1 = param.certification .. "_" .. countries[c] .. "1"
			parameters[a1] = parameters[a]
		end
		parameters[param.comment .. "1"] = parameters[param.comment]
		parameters[param.extra .. "1"] = parameters[param.extra]
		parameters[param.rows .. "_" .. param.extra .. "1"] = parameters[param.rows .. "_" .. param.extra]
		if not christmas then
			table.insert (parametercheck["optional"], param.title)
			table.insert (parametercheck["optional"], param.album)
			table.insert (parametercheck["optional"], param.titleadd)
			table.insert (parametercheck["optional"], param.comment)
			table.insert (parametercheck["optional"], param.extra)
			table.insert (parametercheck["optional"], "Zeilen_Extra")
		end
	end
	local rows = 0
	repeat
		rows = rows + 1
		local title = param.title .. rows
	until not parameters[title]
	rows = rows - 1
	-- /
	
	-- service links
	local sltoomanycountries = "<span style='display:none'>[[Template:Charttabelle/Wartung/zu viele Länder]]</span>"
	local slmissingtitle = "<span style='display:none'>[[Template:Charttabelle/Wartung/Titel fehlt]]</span>"
	local slwrongyear = "<span style='display:none'>[[Template:Charttabelle/Wartung/Jahr]]</span>"
	local slparameterissue = "<span style='display:none'>[[Template:Charttabelle/Wartung/Parameterfehler]]</span>"
	local sltemporary = "<span style='display:none'>[[Template:Charttabelle/Wartung/vorläufig"
	if year then
		if string.match(year, "^%d%d%d%d") then
			if tonumber(string.match(year, "^(%d%d%d%d)")) > 2009 then
				sltemporary = sltemporary .. "/" .. string.match(year, "^(%d%d%d%d)")
			end
		end
	end
	sltemporary = sltemporary .. "]]</span>"
	local slbelgium = "<span style='display:none'>[[Template:Charttabelle/Wartung/Belgien]]</span>"
	
	if #countries > 8 then 
		return "|-\n| colspan='12' | <span class='error'>" .. (year or "Charteintrag") .. ": Zu viele Länder definiert!</span>" .. sltoomanycountries
	end
	if rows == 0 then 
		return "|-\n| colspan='12' | <span class='error'>" .. (year or "Charteintrag") .. ": Charteinträge nicht dargestellt, 'Titel'/'Titel1' fehlt!</span>" .. slmissingtitle
	end
	-- /

	-- start building table
	local ret = "|- "
	-- fallback for row colours, overwriting CSS zebra style (first row)
	if christmas and year == "Insgesamt" then
		ret = ret .. " rowspan='" .. rows .. "' class='sortbottom charts-yelst' \n| style='font-style:italic;' | " .. year
	else
		if colour == "1" then
			ret = ret .. " class='charts-grey'"
		elseif colour == "0" then
			ret = ret .. " class='charts-blue'"
		end
		ret = ret .. "\n | rowspan='" .. rows .. "' class='charts-yy' | " .. (year or "")
	end

	if year then
		if christmas then
			if not string.match (year, "^%d%d%d%d") and year ~= "Insgesamt" then
				ret = ret .. slwrongyear
			end
		else
			if not string.match (year, "^%d%d%d%d$") then
				ret = ret .. slwrongyear
			end
		end
	else
		ret = ret .. slwrongyear
	end

	for row = 1, rows do
		local t = param.title .. row
		local title = parameters[t]
		local a = param.album .. row
		local album = parameters[a]
		local ta = param.titleadd .. row
		local titleaddition = parameters[ta]
		local co = param.colour .. row
		local rowcolour = parameters[co]
		if row > 1 then
			ret = ret .. "\n|- "
		-- individual row colours, overwriting everything
			if rowcolour == "1" then
				ret = ret .. " class='charts-grey'"
				else
					if rowcolour == "0" then
						ret = ret .. " class='charts-blue'"
						else
		-- fallback for row colours, overwriting CSS zebra style (other rows)
							-- check if even
							if row % 2 == 0 then
								if colour == "0" then
									ret = ret .. " class='charts-grey'"
								elseif colour == "1" then
									ret = ret .. " class='charts-blue'"
								end
							-- if odd
							else
								if colour == "0" then
									ret = ret .. " class='charts-blue'"
								elseif colour == "1" then
									ret = ret .. " class='charts-grey'"
								end
							end
					end
			end
		end
		if not christmas then
			table.insert (parametercheck["optional"], t)
			table.insert (parametercheck["optional"], a)
			table.insert (parametercheck["optional"], ta)
			table.insert (parametercheck["optional"], co)
			ret = ret .. "\n| class='newcharttablerow' | " .. title -- class newcharttablerow for row count in charttable
			if album or titleaddition then
				ret = ret .. "<br /><span "
				if not (album == "–" or titleaddition == "–") then
					ret = ret .. "class='charts-add'"
				else
					ret = ret .. "style='font-size:smaller;'"
				end
				ret = ret .. ">" .. (album or titleaddition) .. "</span>"
			end
		end

		for c = 1, #countries do
			local country = countries[c]
			local ps = param.position .. "_" .. country .. row
			table.insert (parametercheck["optional"], ps)
			local position = parameters[ps]
			local w = param.weeks .. "_" .. country .. row
			table.insert (parametercheck["optional"], w)
			local weeks = parameters[w]
			local m = param.months .. "_" .. country .. row
			table.insert (parametercheck["optional"], m)
			local months = parameters[m]
			local y = param.year .. "_" .. country .. row
			table.insert (parametercheck["optional"], y)
			local year1 = parameters[y]
			local s = param.columns .. "_" .. country .. row
			table.insert (parametercheck["optional"], s)
			if parameters[s] and #parameters[s] == 0 then parameters[s] = nil end
			local z = param.rows .. "_" .. country .. row
			table.insert (parametercheck["optional"], z)
			if parameters[z] and #parameters[z] == 0 then parameters[z] = nil end
			local a = param.certification .. "_" .. country .. row
			table.insert (parametercheck["optional"], a)
			local certification = parameters[a]
			local certref
			if certification then
				if string.match (certification, "ref") then
					certref = string.match (certification, "[%a%d%s%+%(%)]*(.+)")
				end
			end
			
			-- variables for tracking of non-existing charts
			local slchartnonexacheck
			local slchartnonexa = "<!-- Albumcharts inexistent -->"
			local slchartnonexscheck
			local slchartnonexs = "<!-- Singlecharts inexistent -->"
			-- /

			if position ~= "n" then
				ret = ret .. "\n|"
				
				-- give position as sortkey
				local sortpos
				if not position or position == "" then
					sortpos = "300!"
				else
					local nude = mw.text.unstrip( position )
					sortpos = string.match (nude, "(%d+)") or "300!"
				end
				ret = ret .. " data-sort-value='" .. sortpos .. "'"
				-- /
				
				-- classes
				ret = ret .. " class='"
				
				-- mobile hiding of empty cells
				if not position or position == "" then
					if not certification then
						ret = ret .. "" .. cssclass.hidemobile .. ""
					end
				end
				-- /
				
				-- mark non-existing chart years
				if not countryfunctions.chartexist (country, "Alben", year) then
					ret = ret .. " charts-nxa"
					slchartnonexacheck = true
				end
				if not countryfunctions.chartexist (country, "Singles", year) then
					ret = ret .. " charts-nxs"
					slchartnonexscheck = true
				end
				-- /
				
				ret = ret .. "'"
				-- / close classes
				
				-- define colspan and/or rowspan
				if parameters[s] then
					ret = ret .. " colspan='" .. parameters[s] .. "'"
				end
				if parameters[z] then
					ret = ret .. " rowspan='" .. parameters[z] .. "'"
				end
				-- /

				ret = ret .. " | "
				
				-- mobile country display
				local mobiledisplay
				if position or certification then
					mobiledisplay = true
					ret = ret .. "<span class='charts-mc'>" .. countryfunctions.countrycol (country, c) .. "</span>"
				end
				-- /

				if certification then
					certification = " " .. certicon.certicon(frame, certification)
					certification = certification .. (certref or "")
				else
					certification = ""
				end
				
				if position then
					-- create links to lists of number-one hits in selected countries
					if position == "1" or string.match(position, "^1%D") then
						position = countryfunctions.numberonelinks (position, country, (year1 or year))
					end
					-- /
					
					if position == "" then
						ret = ret .. "&mdash;" .. certification
					else
						if weeks then
							if weeks == "n" then
								ret = ret .. position .. certification
							else
								if weeks == "" then
									ret = ret .. position .. certification .. "<br class='" .. cssclass.hidemobile .. "'><span class='" .. cssclass.mobileonly .. "'> </span><span style='font-size:smaller;'>(&hellip; Wo.)</span>" .. sltemporary
								else
									ret = ret .. position .. certification .. "<br class='" .. cssclass.hidemobile .. "'><span class='" .. cssclass.mobileonly .. "'> </span><span style='font-size:smaller;'>(" .. weeks .. " Wo.)</span>"
								end
							end
						else
							if months then
								if months == "n" then
									ret = ret .. position .. certification
								else
									if months == "" then
										ret = ret .. position .. certification .. "<br class='" .. cssclass.hidemobile .. "'><span class='" .. cssclass.mobileonly .. "'> </span><span style='font-size:smaller;'>(&hellip; Mt.)</span>" .. sltemporary
									else
										ret = ret .. position .. certification .. "<br class='" .. cssclass.hidemobile .. "'><span class='" .. cssclass.mobileonly .. "'> </span><span style='font-size:smaller;'>(" .. months .. " Mt.)</span>"
									end
								end
							else -- default is weeks
								if position then
									ret = ret .. position .. certification .. "<br class='" .. cssclass.hidemobile .. "'><span class='" .. cssclass.mobileonly .. "'> </span><span style='font-size:smaller;'>(&hellip; Wo.)</span>" .. sltemporary
								end
							end
						end
						-- service links for given position in non-existing charts
						if slchartnonexacheck then
							ret = ret .. slchartnonexa
						end
						if slchartnonexscheck then
							ret = ret .. slchartnonexs
						end
						-- /
						-- service link for Belgian data
						if country == "BE" then
							ret = ret .. slbelgium
						end
						--/
					end
				else --: if not position
					ret = ret .. "&mdash;" .. certification
				end

				-- mobile country display width balance
				if mobiledisplay then
					ret = ret .. "<span class='charts-mcb'>" .. countryfunctions.countrycol (country, c, true) .. "</span>"
				end
				-- /
				
			else --: position == "n"
				ret = ret .. "<span class='" .. cssclass.mobileonlyarrow .. "'>[" .. (countryfunctions.countrycol (country, c, true) or country or "") .. ":&nbsp;&uarr;]</span>"
			end
		end
		
		-- final table columns
		if not christmas then
			local com = param.comment .. row
			table.insert (parametercheck["optional"], com)
			local comment = parameters[com]
			ret = ret .. "\n| class='charts-cm' "
			if comment and comment ~= "" then
				ret = ret .. "| <div>\n" .. comment .. "</div>"
			else
				ret = ret .. "class='" .. cssclass.hidemobile .. "' |"
			end
			local x = param.extra .. row
			table.insert (parametercheck["optional"], x)
			local extra = parameters[x]
			local zx = param.rows .. "_" .. param.extra .. row
			table.insert (parametercheck["optional"], zx)
			if extra then
				if parameters[zx] then
					ret = ret .. "\n| rowspan='" .. parameters[zx] .. "' | " .. extra
				else
					ret = ret .. "\n| " .. (extra or "")
				end
			end
		end
	end

	-- parameter check error
	local parameterissue = TemplatePar.check(parametercheck)
	if parameterissue then
		ret = ret .. "\n|-\n| colspan='12' | " .. parameterissue .. slparameterissue
	end
	-- /

	return ret
end



-- Weihnachtscharteintrag - x-mas chart table row
p.xcharttablerow = function (frame)
	
	return p.charttablerow (frame, true)
end



-- Chartplatzierungen - chart positions table
p.chartposhead = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- get content and define rows
	local entry = {}
	for k, v in ipairs (parameters) do
		entry [k] = v
	end
	local rows = 0
	repeat
		rows = rows + 1
		local entry = "" .. rows
	until not parameters[entry]
	rows = rows - 1
	-- /
	
	-- direct template parameters
	local title		= parameters[param.title]
	local year		= parameters[param.year]
	local source	= parameters[param.source]
	local grey		= parameters[param.grey]
	-- /
	
	-- derived parameters
	local months
	local weeks = true
	local monthscount = 0
	for searchrow = 1, rows do
		if string.match (entry[searchrow], "&nbsp;" .. label.mt) then
			months = true
			monthscount = monthscount + 1
		end
	end
	if monthscount == rows then
		weeks = false
	end
	local tablecaption = title
	if title == label.chartpositions:gsub("&shy;", "") or title == label.yearendcharts:gsub("&shy;", "") then -- avoid duplicating default title
		tablecaption = mw.html.create ("span")
						:addClass(cssclass.hidemobile)
						:wikitext(title)
	end
	local weeksmonths
	if weeks then
		weeksmonths = label.weeks
		if months then
			weeksmonths = weeksmonths .. "/<br />" .. label.months
		end
	else
		weeksmonths = label.months
	end
	local tableheaderfirstyear = label.chartpositions
	local yeardisplay
	if year then
		tableheaderfirstyear = label.yearendcharts
		yeardisplay = " (" .. year .. ")"
	end
	-- /
	
	-- CSS classes
	local headerclass		= cssclass.headerrow
	local mobheaderclass	= cssclass.headercell
	local zebraclass		= cssclass.zebra2
	if grey then
		headerclass 		= cssclass.headerrowgrey
		mobheaderclass		= cssclass.headercellgrey
		zebraclass			= cssclass.zebraclassic
	end
	local stickyclass
	if (rows > 20) then
		stickyclass 		= cssclass.sticky -- only sticky if more than 20 rows
	end
	-- /
	
	-- First header column (charts)
	local tableheaderfirst = mw.html.create ("th")
		:addClass(mobheaderclass)
		:css("width", "250px")
		:node( mw.html.create ("span")
				:addClass(cssclass.hidemobile)
				:wikitext(label.charts)
		)
		:node( mw.html.create ("span")
				:addClass(cssclass.mobileonly)
				:wikitext(tableheaderfirstyear)
		)
		:wikitext(yeardisplay)
		:wikitext(source or "")
	-- /
	
	-- Second header column (chart position)
	local tableheadersecond = mw.html.create ("th")
		:addClass(headerclass)
		:css("width", "150px")
		:node ( mw.html.create ("span")
					:addClass(cssclass.hidemobile)
					:wikitext(label.peak)
		)
	-- /
	
	-- Third header column (weeks/months)	
	local tableheaderthird = mw.html.create ("th")
		:addClass(headerclass)
		:css("width", "90px")
		:wikitext(weeksmonths)
	--/
	
	-- Alternative layout for year-end charts	
	if year then
		tableheadersecond = mw.html.create ("th")
			:addClass(headerclass)
			:css("width", "90px")
			:wikitext(label.position)
		tableheaderthird = nil
	end
	-- /
	
	-- table caption
	local chartposheadcaption
	if tablecaption then
		chartposheadcaption = mw.html.create ("caption")
								:wikitext( tostring(tablecaption) )
	end
	-- /
	
	-- table header
	local chartposheadheader = mw.html.create ("tr")
								:node(tableheaderfirst)
								:node(tableheadersecond)
								:node(tableheaderthird)
	-- /
	
	-- start building table
	local chartposheadtable = mw.html.create ("table")
								:addClass("wikitable")
								:addClass(cssclass.charttable)
								:addClass(zebraclass)
								:addClass(stickyclass)
								:css("max-width", "100%")
								:css("break-inside", "avoid")
								:node(chartposheadcaption)
								:node(chartposheadheader)
	-- /
	
	-- add single rows
	for row = 1, rows do
		local singlerow = entry[row]
		-- content substitutions, link fixes
		if months then
			singlerow = singlerow
				:gsub ("<span class='WO'></span>", "&nbsp;" .. label.wk)
		else
			singlerow = singlerow
				:gsub ("<span class='WO'></span>", "")
		end
		if not weeks then
			singlerow = singlerow
				:gsub ("<span class='MT'>&nbsp;" .. label.mt .. "</span>", "")
		end
		if year then
			if string.match (singlerow, "%[%[Liste der") then
				local temp = ""
				temp = string.match (singlerow, "%[%[(Liste der Nummer%-eins%-.-)|")
				local yearnumberonelist = temp
					:gsub ("Nummer%-eins%-", "Jahres-Nummer-eins-")
					:gsub ("%s%(%d%d%d%d%)", "")
				if mw.title.new( yearnumberonelist ).exists then
					singlerow = singlerow
						:gsub (temp, yearnumberonelist)
				end
			end
		end
		-- /
		
		chartposheadtable:node(singlerow)
		
	end
	-- /
	
	local ret = frame:extensionTag( "templatestyles", nil, { src = "Charttabelle/styles.css" } ) .. tostring (chartposheadtable)
	
	-- content substitutions
	if grey then
		ret = ret:gsub("%[%[File:.-]]&nbsp;", "")
	end
	
	return ret

end



-- Charts - chart positions table entry
p.chartposrow = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local countryraw		= parameters[1]
	local position			= parameters[2]
	local weeks 			= parameters[3]
	local ref				= parameters[param.source]
	local year				= parameters[param.year]
	-- /
	
	-- service links
	local sltemporary = "<span style='display:none'>[[Template:Chartplatzierungen/Wartung/vorläufig]]</span>"
	--
	
	-- derived parameters
	local country
	local brackets
	if countryraw then
		country = string.match (countryraw, "(.*)%s%(.*%)") or countryraw
		brackets = string.match (countryraw, ".*%s(%(.*%))")
	end
	local countrydisplay = countryfunctions.countryflag (country, 2, 1, 3, "chartpos")
	if brackets then
		if countrydisplay:match ("%(") then
			countrydisplay = countrydisplay:gsub ("%(.-%)", brackets )
		else
			countrydisplay = countrydisplay .. brackets
		end
	end
	local weekdisplay
	local months
	local mobileweeks
	local mobileweekdisplay
	if weeks then
		if weeks == "" then
			weeks = "&hellip;" .. sltemporary
		end
		mobileweekdisplay = weeks .. "&nbsp;" .. label.wk
		weekdisplay = weeks .. "<span class='WO'></span>"
		if string.match (weeks, label.mt) then
			if weeks == label.mt then
				months = "&hellip;" .. sltemporary
			else
				months = string.gsub (weeks, "%s?" .. label.mt, "")
			end
			mobileweekdisplay = months .. "&nbsp;" .. label.mt
			weekdisplay = months .. "<span class='MT'>&nbsp;" .. label.mt .. "</span>"
		end
		mobileweeks = mw.html.create ("span")
						:addClass(cssclass.mobileonly)
						:css("font-size", "smaller")
						:wikitext(" (" .. mobileweekdisplay .. ")")
	end
	-- /
	
	-- link number one
	if position then
		if position == "1" or string.match(position, "^1%D") then
			position = countryfunctions.numberonelinks (position, country, year)
		end
	end
	-- /
	
	-- first column (country + sources)
	local chartposrowfirst = mw.html.create ("td")
								:wikitext(countrydisplay)
								:wikitext(ref or "")
	-- /
	
	-- second column (chart position + mobile weeks/months)
	local chartposrowsecond = mw.html.create ("td")
								:css("text-align", "center")
								:wikitext(position)
								:node(mobileweeks)
	-- /
	
	-- third column (weeks or months on chart)
	local chartposrowthird
	if weeks then
		chartposrowthird = mw.html.create ("td")
							:addClass(cssclass.hidemobile)
							:css("text-align", "center")
							:wikitext(weekdisplay)
	end
	-- /
	
	-- build table row
	local ret = mw.html.create ("tr")
					:node(chartposrowfirst)
					:node(chartposrowsecond)
					:node(chartposrowthird)
	-- /
	
	return ret
end



-- Infobox Chartplatzierungen - chart positions infobox
p.chartinfobox = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end -- always [?]
	
	-- direct template parameters
	local file			= parameters[param.image]
	local caption		= parameters[param.imagecaption]
	local temporary 	= parameters[param.temporary]

	local albums		= parameters[param.albums]
	local eps			= parameters[param.eps]
	local singles		= parameters[param.singles]
	local dvds			= parameters[param.dvds]

	local refalbums 	= parameters[param.refalbums]
	local refeps		= parameters[param.refeps]
	local refsingles	= parameters[param.refsingles]
	local refdvds		= parameters[param.refdvds]
	local source		= parameters[param.sources]
	-- /
	
	-- derived parameters
	local rformats		= { albums, eps, singles, dvds }
	local refs			= { refalbums, refeps, refsingles, refdvds }
	local refrow
	
	local temporaryweeks
	for temp = 1, 4 do
		if rformats[temp] then
			if string.match (rformats[temp], "%(&hellip;" ) then
				temporaryweeks = true
			end
		end
	end
	-- /
	
	-- service links
	local slsourceparam = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Quellen-Parameter]]</span>"
	local slnosource	= "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/ohne Quellen]]</span>"
	local sltemporary	= "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/vorläufige Chartplatzierung]]</span>"
	-- /
	
	-- image + caption
	local firstrow
	local secondrow
	if file then
		local imagecell
		if file ~= "" then
			imagecell = mw.html.create ("td")
						:css("text-align", "center")
						:wikitext("[[File:" .. file .. "|210px|" .. (caption or mw.title.getCurrentTitle().text) .. "]]")
			firstrow = mw.html.create ("tr")
						:node(imagecell)
			if caption then
				local captioncell
				if caption ~= "" then
					captioncell = mw.html.create ("td")
									:css("text-align", "center")
									:css("font-size", "smaller")
									:wikitext(caption)
					secondrow = mw.html.create ("tr")
									:node(captioncell)
				end
			end
		end
	end
	-- /
	
	-- header
	local headertemporary
	if temporaryweeks then
		headertemporary = mw.html.create ("span")
							:css("font-size", "12px")
							:css("font-stretch", "condensed")
							:wikitext("<br />(" .. label.temporary .. ")")
	end
	
	local headertitle = mw.html.create ("span")
							:css("font-size", "20px")
							:css("font-stretch", "condensed")
							:wikitext(label.chartpositions)
					
	local headerlink = mw.html.create ("span")
							:css("font-size", "smaller")
							:wikitext("<br />[[" .. label.chartinfolink .. "|" .. label.chartinfolinktext .. "]]")
	
	local headercell = mw.html.create ("td")
							:css("background-color", "#F3F3F3")
							:css("text-align", "center")
							:node(headertitle)
							:node(headertemporary)
							:node(headerlink)
					
	local thirdrow = mw.html.create ("tr")
							:node(headercell)
	-- /
	
	-- start building infobox
	local infoboxtable = mw.html.create ("table")
							:addClass("infobox")
							:addClass(cssclass.chartbox)
							:node(firstrow)
							:node(secondrow)
							:node(thirdrow)
	-- /
	
	-- content
	for section = 1, 4 do
		local titles = {label.albums, label.eps, label.singles, label.dvds}
		if rformats[section] then
			if rformats[section] ~= "" then
				local innertable = mw.html.create ("table")
										:css("border-collapse", "collapse")
										:css("display", "table")
										:wikitext(rformats[section])
										
				local sectiontitle = mw.html.create ("span")
										:css("font-size", "larger")
										:css("font-weight", "bold")
										:wikitext(titles[section])
										
				local titlerowcell = mw.html.create ("td")
										:css("padding", "0 .3em")
										:css("background", "#EAECF0")
										:css("color", "#202122")
										:node(sectiontitle)
										:wikitext(refs[section] or "")
										
				local contentrowcell = mw.html.create ("td")
										:css("padding", "0 .3em .5em .3em")
										:node(innertable)
										
				local titlerow = mw.html.create ("tr")
										:node(titlerowcell)
				local contentrow = mw.html.create ("tr")
										:node(contentrowcell)

				-- add sections to infobox
				infoboxtable
					:node(titlerow)
					:node(contentrow)
				-- /
				
				if string.match (rformats[section], "<!%-%-%$QUELLEZEILE%$%-%->") then
					refrow = true
				end
			end
		end
	end
	-- /
	
	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	ret = ret .. tostring (infoboxtable)
	
	-- create service links
	if source then
		ret = ret .. slsourceparam
	elseif not refalbums and not refsingles and not refeps and not refdvds and not refrow then
		ret = ret .. slnosource
	end
	if temporary then
		ret = ret .. sltemporary
	end
	-- /
	
	return ret
	
end



-- Infobox Chartplatzierungen/Werk - chart positions infobox entry
p.chartinfoboxentry = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- service links
	local slmissingtitle = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Titel fehlt]]</span>"
	-- /
	
	-- correct chart links according to rformat
	local templatename = frame:getParent():getTitle()
	local rformat = string.match (templatename, ".*:(%a*)")
	local rows = {}
	local i = 0
	for k, v in ipairs (parameters) do
		if rformat == param.tmpsingle then
			v = countryfunctions.singlechartlink (v)
		end
		
		if #v > 0 then
			i = i + 1
			rows[i] = v
		end
	end
	-- /
	
	local title = ""
	local rownumberstart = 0
	
	-- valididty of title parameter
	if rows[1] then
		if rows[1]:match("^|") then
			title = slmissingtitle
			rownumberstart = 1
		else
			title = rows[1]
			rownumberstart = 2
			if rows[1] == "" then
				title = slmissingtitle
			end
		end
	end
	--/
	
	local ret
	
	-- content (rows)
	local titlecell = mw.html.create ("td")
						:attr("colspan", "6")
						:css("font-size", "95%")
						:css("font-weight", "bold")
						:wikitext(title)
	local titlerow = mw.html.create ("tr")
						:node(titlecell)
						
	ret = tostring(titlerow)
	
	for row = rownumberstart, #rows do
		local contentrow = mw.html.create ("tr")
							:addClass(cssclass.chartboxrow)
							:node(rows[row])
		ret = ret .. tostring (contentrow)
	end
	-- /
	
	return ret
end



-- Charts - chart positions infobox row
p.chartinfoboxrow = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local country = parameters[1]
	if country then
		country = mw.text.trim (country)
	end
	local poscert = parameters[2]
	if poscert then
		poscert = mw.text.trim (poscert)
	else
		poscert = ""
	end
	local entrydate = parameters[3]
	if entrydate then
		entrydate = mw.text.trim (entrydate)
	end
	local weeks = parameters[4]
	if weeks then
		weeks = mw.text.trim (weeks)
	end
	local ref = parameters[5]
	local year = parameters[param.year]
	if not year and entrydate then
		year = string.match (entrydate, "(%d%d%d%d)$")
	end
	-- /
	
	-- derived parameters
	local position
	local certification
	local certref
	
	certification = string.match (poscert, "%s(%d?%d?%d?[SGPD].*)")  -- "%s(%d?%d?%d?[SGPD]%A+.*)" ???
	if certification then
		position = poscert:gsub ("%d?%d?%d?[SGPD].*", "")
	else
		position = poscert
	end
	position = mw.text.trim (position)
	if string.match (position, "%A?[SGPD]%A?") then
		certification = position
		position = ""
	end
	if certification then
		if string.match (certification, "ref") then
			certref = string.match (certification, "[%a%d%s%+%(%)]*(.+)")
		end
	end
	-- /
	
	-- service links
	local slbelgium = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Belgien]]</span>"
	local sltemporary = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/vorläufig"
	if year then
		if tonumber(year) > 2019 then
			sltemporary = sltemporary .. "/" .. year
		end
	end
	sltemporary = sltemporary .. "]]</span>"
	local sldots = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Punkte]]</span>"
	local slwrongdate = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/Datum falsch]]</span>"
	-- /
	
	-- start building table row
	local firstcolumn = mw.html.create ("td")
							:css("width", "3%")
							:css("background", "transparent")
							:wikitext("&nbsp;")
	local secondcolumn = mw.html.create ("td")
							:css("width", "12%")
							:css("font-size", "95%")
							:css("line-height", "90%")
							:wikitext( countryfunctions.countrycol (country, 1, nil, "infobox") )
	if (country == "BE" or country == "BEL") then
		secondcolumn:wikitext( slbelgium )
	end
	
	-- chart position
	local thirdcolumn = mw.html.create ("td")
							:css("width", "27%")
							:css("font-size", "95%")
							:css("line-height", "90%")
							:css("font-weight", "bold")
							:css("text-align", "center")

	if position then
		if position == "1" or string.match(position, "^1%D") then
			position = countryfunctions.numberonelinks (position, country, year)
		end
		
		thirdcolumn:wikitext( position )
	end
	-- /
	
	-- certification
	if certification then
		certification = "&thinsp;" .. certicon.certicon(frame, certification, nil, "16")
	else
		certification = ""
	end
	thirdcolumn:wikitext( certification )
	if position == "" then
		thirdcolumn:wikitext("<span style='font-size:85%;'>" .. (certref or "") .. "</span>")
		certref = ""
	end
	-- /
	
	local fourthcolumn = mw.html.create ("td")
							:css("width", "30%")
							:css("font-size", "smaller")
							:wikitext(entrydate or "")
	
	-- weeks or months on charts
	local fifthcolumn = mw.html.create ("td")
							:css("width", "23%")
							:css("font-size", "smaller")
							:css("text-align", "right")
							:css("padding-left", "5px")

	if weeks then
		if weeks == "" or weeks == "…" or weeks == "..." then
			weeks = "&hellip;" .. sltemporary
			if weeks == "..." then
				weeks = weeks .. sldots
			end
		end
		if string.match (weeks, label.mt) then
			fifthcolumn:wikitext( "(" .. weeks .. ")" )
		else
		    fifthcolumn:wikitext( "(" .. weeks .. "&nbsp;" .. label.wk .. ")" )
		end
	end
	-- /
	
	local sixthcolumn = mw.html.create ("td")
							:css("width", "5%")
							:css("font-size", "smaller")
							:wikitext( (ref or "") .. (certref or "") )


	local ret = tostring (firstcolumn) .. tostring (secondcolumn) .. tostring (thirdcolumn) .. tostring (fourthcolumn) .. tostring (fifthcolumn) .. tostring (sixthcolumn)
	if ref then ret = ret .. "<!--$QUELLEZEILE$-->" end
	
	-- insert service link wrong dates
	if entrydate then
		if #entrydate < 4 then
			ret = ret .. slwrongdate
		end
	end
	-- /
	
	return ret
end



-- Wechsel zwischen Chartplatzierungen-Zeile und Chartbox-Zeile - switch between chart positions table row and infobox row
p.chartrows = function (frame)
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	if parameters[param.source] then
		return p.chartposrow(frame)
	else
		return p.chartinfoboxrow(frame)
	end
	
end



-- AfM-Tabelle - table for certifications
p.certificationtable = function (frame)
	
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- get content and define rows
	local entry = {}
	for k, v in ipairs (parameters) do
		entry [k] = v
	end
	local rows = 0
	repeat
		rows = rows + 1
		local entry = "" .. rows
	until not parameters[entry]
	rows = rows - 1
	-- /
	
	-- direct template parameters
	local statistics				= parameters[param.statistics]
	local main						= parameters[param.mainarticle]
	local note						= parameters[param.certnote]
	local source					= parameters[param.source]
	local nosilver					= parameters[param.deactsilver]
	local nodiamond 				= parameters[param.deactdiamond]
	
	local silver					= parameters[param.totsilver]
	local gold						= parameters[param.totgold]
	local platinum					= parameters[param.totplatinum]
	local diamond					= parameters[param.totdiamond]
	local number					= parameters[param.totnumber]
	
	local grey						= parameters[param.grey]
	-- /
	
	local headerclass				= cssclass.headerrow
	local mobheaderclass			= cssclass.headercell
	if grey then
		headerclass 				= cssclass.headerrowgrey
		mobheaderclass				= cssclass.headercellgrey
	end
	local pagename					= mw.title.getCurrentTitle().text
	local sicon 					= "[[File:Silver record icon.svg|15px|link=]] "
	local gicon 					= "[[File:Gold record icon.svg|15px|link=]] "
	local picon 					= "[[File:Platinum record icon.svg|15px|link=]] "
	local dicon 					= "[[File:Diamond record icon.svg|15px|link=]] "
	if grey then
		sicon, gicon, picon, dicon	= "", "", "", ""
	end

	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	-- add explanation about the allocation of certifications in chart table
	if statistics and not note and not main and not string.match (pagename, label.certpagename) then
		local pagenameroot = string.match ( pagename, "(.+)" .. label.discpagename ) or pagename
		local certifications = pagenameroot .. label.certpagename
		if mw.title.new( certifications ).exists == false then
			ret = ret .. "\n<span style='font-style:italic;font-size:smaller;'>" .. label.certnotedefault .. "</span>"
		end
	end
	
	-- start building table (normal/statistics)
	ret = ret .. "\n{| class='wikitable "
	if statistics then
		ret = ret .. "charts-table"
	else
		ret = ret .. "charts-ctable"
	end
	if grey then
		ret = ret .. " charts-zebra"
	else
		ret = ret .. " charts-zebragrey"
		if not statistics then
			ret = ret .. "2"
		end
	end
	if (rows > 20) then
		ret = ret .. " charts-stickyhead" -- only sticky if more than 20 rows
	end
	
	-- table header
	if statistics then
		ret = ret .. " sortable' style='max-width:100%' \n|-"
		ret = ret .. "\n! style='width:250px;' class='" .. mobheaderclass .. "' | <span class='" .. cssclass.hidemobile .. "'>" .. label.region .. "</span><span class='" .. cssclass.mobileonly .. "'>" .. label.certificationsfull .."<br /><span class='charts-mh'>(" .. label.region .. ", " .. label.certifications .. ", " .. label.sales .. ", " .. label.sources .. ")</span></span> \n!"
		if not nosilver then
			ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. sicon .. label.silver .. " !! "
		end
		ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. gicon .. label.gold .. " !! "
		ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. picon .. label.platinum
		if not nodiamond then
			ret = ret .. " !! class='" .. headerclass .. "' data-sort-type='number' | " .. dicon .. label.diamond
		end
		ret = ret .. "\n! style='width:90px;' class='" .. headerclass .. "' data-sort-type='number' | " .. label.sales
		ret = ret .. "\n ! class='unsortable " .. headerclass .. "' | " .. label.sources
	else
		ret = ret .. "' style='max-width:100%;' \n|-"
		ret = ret .. "\n! style='width:250px;' class='" .. headerclass .. "' | " .. label.region
		ret = ret .. "\n! style='width:150px;' class='" .. mobheaderclass .. "' | Aus&shy;zeich&shy;nung" .. "<span class='" .. cssclass.mobileonly .. "'>&shy;en für Mu&shy;sik&shy;ver&shy;käu&shy;fe<br /><span class='charts-mh'>(" .. label.region .. ", " .. label.certification .. ", " .. label.sales .. ")</span></span>" .. (source or "")
		ret = ret .. "\n! style='width:90px;' class='" .. headerclass .. "' data-sort-type='number' | " .. label.sales
	end
	
	-- single rows
	ret = ret .. "\n|-\n"
	for row = 1, rows do
		local content = entry[row]
		if statistics then
			-- delete empty columns
			if nosilver then
				content = string.gsub (content, '<td class="charts%-hm" style="text%-align:center"><span style="display:none">0! S</span>&mdash;</td>', '')
			end
			if nodiamond then
				content = string.gsub (content, '<td class="charts%-hm" style="text%-align:center"><span style="display:none">0! D</span>&mdash;</td>', '')
			end
		end
		ret = ret .. mw.text.trim (content)
	end
	
	ret = ret .. "\n|-"
	if statistics then
		ret = ret .. "class='sortbottom"
		if not grey then ret = ret .. " charts-yelst" end
		ret = ret .. "' style='font-weight:bold;'\n| " .. label.total
		
		if not nosilver then
			if silver and silver ~= "" and silver ~= "0" then
				local silvercert = silver .. label.silvershort
				ret = ret .. "\n| style='text-align:center;' |"
				-- mobileview
				ret = ret .. "<span class='" .. cssclass.mobileonly .. "'>" .. certicon.certicon(frame, silvercert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='" .. cssclass.hidemobile .. "'>" .. silver .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;' class='" .. cssclass.hidemobile .. "' | &mdash;"
			end
		end
		
		if gold and gold ~= "" and gold ~= "0" then
			local goldcert = gold .. label.goldshort
			ret = ret .. "\n| style='text-align:center;' |"
			-- mobileview
			ret = ret .. "<span class='" .. cssclass.mobileonly .. "'>" .. certicon.certicon(frame, goldcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='" .. cssclass.hidemobile .. "'>" .. gold .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;' class='" .. cssclass.hidemobile .. "' | &mdash;"
		end
		
		if platinum and platinum ~= "" and platinum ~= "0" then
			local platinumcert = platinum .. label.platinumshort
			ret = ret .. "\n| style='text-align:center;' |"
			-- mobileview
			ret = ret .. "<span class='" .. cssclass.mobileonly .. "'>" .. certicon.certicon(frame, platinumcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='" .. cssclass.hidemobile .. "'>" .. platinum .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;' class='" .. cssclass.hidemobile .. "' | &mdash;"
		end
		
		if not nodiamond then
			if diamond and diamond ~= "" and diamond ~= "0" then
				local diamondcert = diamond .. label.diamondshort
				ret = ret .. "\n| style='text-align:center;' |"
				-- mobileview
				ret = ret .. "<span class='" .. cssclass.mobileonly .. "'>" .. certicon.certicon(frame, diamondcert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='" .. cssclass.hidemobile .. "'>" .. diamond .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;' class='" .. cssclass.hidemobile .. "' | &mdash;"
			end
		end
		
		ret = ret .. "\n| colspan='2' |"
	else
		if number then
			if not grey then ret = ret .. "class='charts-yelst' " end
			ret = ret .. "style='font-style:italic;'\n| " .. label.total .. "\n| style='text-align:center;' |"
			if silver or gold or platinum or diamond then
				if silver then
					ret = ret .. sicon .. silver .. "× " .. label.silver .. "<br />"
				end
				if gold then
					ret = ret .. gicon .. gold .. "× " .. label.gold .. "<br />"
				end
				if platinum then
					ret = ret .. picon .. platinum .. "× " .. label.platinum .. "<br />"
				end
				if diamond then
					ret = ret .. dicon .. diamond .. "× " .. label.diamond .. "<br />"
				end
			else
				ret = ret .. "&mdash;"
			end
			ret = ret .. "\n| style='text-align:right;' | <b>" .. number .. "</b>"
		end
	end
	ret = ret .. "\n|}"
	-- / table end
	
	-- add link to main article
	if main then
		ret = ret .. "\n<span style='font-style:italic; font-size:smaller;'>" .. label.mainarticle .. ": [[" .. main .. "]]</span>"
	end
	
	-- content substitutions
	if grey then
		ret = ret:gsub("%[%[File:.-]]&nbsp;", "")
	end

return ret

end



-- AfM - certification table rows
p.certificationtablerow = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local silver				= parameters[param.silver]
	local gold					= parameters[param.gold]
	local platinum				= parameters[param.platinum]
	local diamond				= parameters[param.diamond]
	local sum2					= parameters[2]
	local source				= parameters[param.source]
	
	local country				= parameters[1]
	local certification 		= parameters[2]
	local number				= parameters[3]
	local sum					= parameters[4]
	-- /
	
	-- derived parameters
	local countrydisplay		= countryfunctions.countryflag (country, 4, 1, 5, "certification")
	local sumtest
	if parameters[2] then 
		sumtest 				= parameters[2]:gsub("%(", ""):gsub("%)", ""):gsub("%.", "")
	end
	local statisticstable
	if silver or gold or platinum or diamond or tonumber(sumtest) then
		statisticstable			= true
		certification			= false
	end
	-- /
	
	-- service links
	local slcustomcert			= "<span style='display:none'>[[Template:AfM-Tabelle/Wartung/Manuelle Auszeichnung]]</span>"
	local slcustomcerttemplate	= "<span style='display:none'>[[Template:AfM-Tabelle/Wartung/Schallplattenvorlage]]</span>"
	-- /
	
	-- first column (country)
	local firstcolumnsource
	if not statisticstable then
		firstcolumnsource		= source or ""
	end
	local certtablerowfirst 	= mw.html.create ("td")
									:wikitext(countrydisplay)
									:wikitext(firstcolumnsource)
	-- /
	
	-- silver column
	local certtablerowsilver
	if silver ~= "n" then
		if silver and silver ~= "" and silver ~= "0" then
			local silvercert = silver .. param.silver
			certtablerowsilver 		= mw.html.create ("td")
										:css("text-align", "center")
										:attr("data-sort-value", silver)
										:node( mw.html.create ("span")
												:addClass(cssclass.mobileonly)
												:wikitext(certicon.certicon(frame, silvercert, "text"))
										)
										:node( mw.html.create ("span")
												:addClass(cssclass.hidemobile)
												:wikitext(silver)
										)
		else
			certtablerowsilver 		= mw.html.create ("td")
										:css("text-align", "center")
										:addClass(cssclass.hidemobile)
										:node( mw.html.create ("span")
												:css("display", "none")
												:wikitext("0! " .. param.silver)
										)
										:wikitext("&mdash;")
		end
	end
	-- /
	
	-- gold column
	local certtablerowgold
	if gold and gold ~= "" and gold ~= "0" then
		local goldcert = gold .. param.gold
		certtablerowgold 		= mw.html.create ("td")
									:css("text-align", "center")
									:attr("data-sort-value", gold)
									:node( mw.html.create ("span")
											:addClass(cssclass.mobileonly)
											:wikitext(certicon.certicon(frame, goldcert, "text"))
									)
									:node( mw.html.create ("span")
											:addClass(cssclass.hidemobile)
											:wikitext(gold)
									)
	else
		certtablerowgold 		= mw.html.create ("td")
									:css("text-align", "center")
									:addClass(cssclass.hidemobile)
									:node( mw.html.create ("span")
											:css("display", "none")
											:wikitext("0! " .. param.gold)
									)
									:wikitext("&mdash;")
	end
	-- /
	
	-- platinum column
	local certtablerowplatinum
	if platinum and platinum ~= "" and platinum ~= "0" then
		local platinumcert = platinum .. param.platinum
		certtablerowplatinum 	= mw.html.create ("td")
									:css("text-align", "center")
									:attr("data-sort-value", platinum)
									:node( mw.html.create ("span")
											:addClass(cssclass.mobileonly)
											:wikitext(certicon.certicon(frame, platinumcert, "text"))
									)
									:node( mw.html.create ("span")
											:addClass(cssclass.hidemobile)
											:wikitext(platinum)
									)
	else
		certtablerowplatinum	= mw.html.create ("td")
									:css("text-align", "center")
									:addClass(cssclass.hidemobile)
									:node( mw.html.create ("span")
											:css("display", "none")
											:wikitext("0! " .. param.platinum)
									)
									:wikitext("&mdash;")
	end
	-- /
	
	-- diamond column
	local certtablerowdiamond
	if diamond ~= "n" then
		if diamond and diamond ~= "" and diamond ~= "0" then
			local diamondcert = diamond .. param.diamond
			certtablerowdiamond		= mw.html.create ("td")
										:css("text-align", "center")
										:attr("data-sort-value", diamond)
										:node( mw.html.create ("span")
												:addClass(cssclass.mobileonly)
												:wikitext(certicon.certicon(frame, diamondcert, "text"))
										)
										:node( mw.html.create ("span")
												:addClass(cssclass.hidemobile)
												:wikitext(diamond)
										)
		else
			certtablerowdiamond		= mw.html.create ("td")
										:css("text-align", "center")
										:addClass(cssclass.hidemobile)
										:node( mw.html.create ("span")
												:css("display", "none")
												:wikitext("0! " .. param.diamond)
										)
										:wikitext("&mdash;")
		end
	end
	-- /
	
	-- statistic sum column
	local certtablerowstatsum
	if sum2 and sum2 ~= "" and sum2 ~= "0" then
		certtablerowstatsum			= mw.html.create ("td")
										:css("text-align", "right")
										:wikitext(sum2)
	else
		certtablerowstatsum			= mw.html.create ("td")
										:css("text-align", "right")
										:addClass(cssclass.hidemobile)
										:node( mw.html.create ("span")
											:css("display", "none")
											:wikitext("0!")
										)
										:wikitext("&mdash;")
	end
	-- /
	
	-- statistic source column
	local certtablerowsource
	if source and source ~= "" and source ~= "0" then
		certtablerowsource			= mw.html.create ("td")
										:wikitext(source)
	else
		certtablerowsource			= mw.html.create ("td")
										:addClass(cssclass.hidemobile)
										:wikitext("")
	end
	-- /
	
	-- certification column
	local certtablerowcert
	local certificationdisplay
	if not certification then
		certificationdisplay		= "&mdash;"
	elseif certification == "" or certification == "-" or certification == "—" then
		certificationdisplay		= "&mdash;"
	elseif number == "" or number == "-" or number == "—" then
		certificationdisplay		= certification or ""
	elseif certification == "D+P" or certification == "P+D" then
		certificationdisplay		= "[[File:Diamond record icon.svg|15px|link=]][[File:Platinum record icon.svg|15px|link=]]&nbsp;" .. number .. "×&nbsp;Platin"
	else
		certification				= certification .. (number or "")
		local icontype				= "text"
		certificationdisplay		= certicon.certicon(frame, certification, icontype)
	end
	if certification then
		if string.match (certification, "Datei") and not string.match (certification, "verweis=") and not string.match (certification, "link=") then
			certificationdisplay	= certificationdisplay .. slcustomcert
		end
		if string.match (certification, cssclass.certcontainer) or string.match (certification, "Schallplatte") or string.match (certification, "File") then
			certificationdisplay	= certificationdisplay .. slcustomcerttemplate
		end
	end
		certtablerowcert			= mw.html.create ("td")
										:wikitext(certificationdisplay)
	-- /
	
	-- sum column
	local certtablerowsum			= mw.html.create ("td")
										:wikitext(sum or "&mdash;")
	-- /
	
	-- build table row
	local ret
	if statisticstable then
		ret 			= mw.html.create ("tr")
							:node(certtablerowfirst)
							:node(certtablerowsilver)
							:node(certtablerowgold)
							:node(certtablerowplatinum)
							:node(certtablerowdiamond)
							:node(certtablerowstatsum)
							:node(certtablerowsource)
	else
		ret 			= mw.html.create ("tr")
							:node(certtablerowfirst)
							:node(certtablerowcert)
							:node(certtablerowsum)
	end
	-- /

return ret

end


-- AfM - inline certification
p.certification = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local certification = parameters[1]
	local number = parameters[2]
	local sum = parameters[3]
	-- /
	
	local ret = ""
	if certification == "D+P" or certification == "P+D" then
		ret = ret .. "[[File:Diamond record icon.svg|15px|link=]][[File:Decuple platinum record icon.svg|15px|link=]]&nbsp;" .. number .. "×&nbsp;Platin"
	else
		certification = certification .. (number or "")
		local icontype = "text"
		ret = ret .. certicon.certicon(frame, certification, icontype)
	end
	if sum then
		ret = ret .. " (" .. sum .."+)"
	end
	
	return frame:preprocess (ret)
	
end


-- Wechsel zwischen AfM/AfM2 - switch between certificationtablerow and certification
p.certifications = function (frame)

	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	local ID = parameters[1]
	local certnames = { 
		["S"] = true, 
		["Silber"] = true, 
		["G"] = true, 
		["Gold"] = true, 
		["P"] = true, 
		["Platin"] = true, 
		["D"] = true, 
		["Diamant"] = true, 
		["P+G"] = true, 
		["G+P"] = true, 
		["D+P"] = true, 
		["P+D"] = true
	}
	
	if certnames[ID] then
		return p.certification(frame)
	else
		return p.certificationtablerow(frame)
	end
	
end



-- Schallplatte - formatted inline certification
p.inlinecerticon = function (frame)
	local parameters = frame.args
	if not parameters[1] then parameters = mw.getCurrentFrame():getParent().args end
	
	local raw = parameters[1] or ""
	local inline = frame:extensionTag( "templatestyles", nil, { src = templatestyles } ) .. certicon.certicon (frame, raw)
	inline = inline
		:gsub ("<div", "<span")
		:gsub ("</div>", "</span>")
	if raw:match("%d") then
		inline = inline .. " "
	end
	
	return inline
end



-- Nummer-eins-Hits - table for no. 1 hits and albums
p.no1table = function (frame)
	local parameters = frame.args
	if not parameters.Inhalt then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local listtype = parameters.Art or "Hits"
	local country = parameters.Land or "Land"
	local name = parameters.Bezeichnung
	if name == "" then
		name = nil
	end
	local months = parameters.Monate
	if months == "" then
		months = nil
	end
	local content = parameters.Inhalt or ""
	-- /
	
	-- derived parameters
	local pagename = mw.title.getCurrentTitle().text
	local currentyear = tonumber ( os.date( "%Y" ) )
	local year = string.match (pagename, ".+%((%d%d%d%d)%)") or currentyear
	local prevyear = year - 1
	local nextyear = year + 1
	local linkprev
	local linknext
	if string.match (pagename, "%d%d%d%d") then
		linkprev = string.gsub (pagename, "%d%d%d%d", prevyear)
		linknext = string.gsub (pagename, "%d%d%d%d", nextyear)
	else
		linkprev = pagename .. " (" .. prevyear .. ")"
		linknext = pagename .. " (" .. nextyear .. ")"
	end
	local listlink
	if string.match (pagename, ".+%s%(%d%d%d%d%)") then
		listlink = string.match (pagename, "(.+)%s%(%d%d%d%d%)")
	else
		listlink = pagename
	end
	
	if listtype == "Alben" and string.match (pagename, "Hits") then
		local templistlink = "Liste der Nummer-eins-" .. listtype .. " in " .. countryfunctions.no1tablecountry (country, "countryid")
		if mw.title.new( templistlink ).exists then
			listlink = templistlink
		end
	end
	if listtype == "Jahr" then
		local yearlistlink = "Liste der Jahres-Nummer-eins-Hits in " .. countryfunctions.no1tablecountry (country, "countryid")
		if mw.title.new( yearlistlink ).exists then
			listlink = yearlistlink
		end
	end

	local sectionlink = "#"
	if listtype == "Jahr" then
		sectionlink = sectionlink .. "Jahreshitparaden"
	elseif listtype == "JahrA" or listtype == "JahrS" then
		sectionlink = sectionlink .. "Jahreshitparade"
	else
		sectionlink = sectionlink .. (listtype or "")
	end
	if name then
		if string.match (name, "Wallon") then
			sectionlink = sectionlink .. "_2"
		end
	end
	
	local colour1 = countryfunctions.no1tablecountry (country, "colour1")
	local colour2 = countryfunctions.no1tablecountry (country, "colour2")
	local rowcolour = countryfunctions.no1tablecountry (country, "rowcolour")
	local flag = countryfunctions.no1tablecountry (country, "flag")
	local firstyear = countryfunctions.no1tablecountry (country, "firstyear", listtype)
	-- /
	
	-- check number of rows
	local rownumber
	content, rownumber = string.gsub (content, "class='newno1tablerow' ", "")
	-- /
	
	-- fix colouring of divider rows
	if string.match (content, 'class="sortbottom"') then
		content = string.gsub (content, "background:#EEEEEE;", "background:" .. colour2 .. ";")
	end
	-- /

	-- build table	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	
	-- navigation header
	ret = ret .. "\n{| class='charts-no1table darkmode-standardlinks' style='width:100%;border-spacing:0px;display:table;' \n |- style='background-color:" .. colour1 .. "; color: inherit;' \n| style='width:15%;line-height:1em;' |"
	if prevyear >= tonumber(firstyear) then
		ret = ret .. "[[" .. linkprev .. sectionlink .. "|<span class='" .. cssclass.hidemobile .. "'>← </span>" .. prevyear .. "<span class='" .. cssclass.mobileonly .. "'><br />←</span>]]"
	end
	
	ret = ret .. "\n| colspan='3' style='text-align:center; width:70%' |"
	ret = ret .. (frame:preprocess(flag) or "") .. "&nbsp;[[" .. mw.text.trim (listlink) .."|" .. listlink:gsub ("Liste der ", "<span class='" .. cssclass.hidemobile .. "'>Liste der </span>") .. "]]"
	if name then
		ret = ret .. "&nbsp;(" .. name .. ")"
	end
	
	ret = ret .. "\n| style='text-align:right;width:15%;line-height:1em;' |"
	if tonumber(year) < currentyear then
		ret = ret .. "[[" .. linknext .. sectionlink .. "|" .. nextyear .. " <br class='" .. cssclass.mobileonly .. "' />→]]"
	end
	ret = ret .. "\n|- \n| colspan='5' |"
	-- /
	
	-- table header
	ret = ret .. "\n{| class='wikitable charts-zebra sortable"
	if (rownumber > 5) then
		ret = ret .. " charts-stickyhead" -- only sticky if more than 5 rows
	end
	if listtype ~= "Jahr" and listtype ~= "JahrA" and listtype ~= "JahrS" then
		ret = ret .. " charts-table'"
	else
		ret = ret .. "'"
	end
	ret = ret .. " style='width:100%; background-color:" .. rowcolour .."; color:var(--color-base, #202122); border:none; margin:0px;'"
	ret = ret .. "\n|- style='background-color:" .. colour2 .. "; color:#202122;'"
	if listtype ~= "JahrA" and listtype ~= "JahrS" then
		ret = ret .. "\n! style='background-color:" .. colour2 .. "; border:none; color:#202122; "
		if listtype == "Jahr" then
			ret = ret .. "border-bottom: 1pt solid white; width:45%' class='unsortable charts-th' | <span style='font-size:larger'>Singles</span>"
		else
			ret = ret .. "text-align:left; width:15%' class='charts-trh' | Zeitraum "
			ret = ret .. "!! data-sort-type='number' style='background-color:" .. colour2 .. "; color:#202122; border:none; text-align:center; width:5%' class='charts-trh' | "
			if months then
				ret = ret .. "<abbr title='Monate insgesamt auf Platz eins'>Mt.<br /><span style='font-size:smaller'>ges.</span></abbr>"
			else
				ret = ret .. "<abbr title='Wochen insgesamt auf Platz eins'>Wo.<br /><span style='font-size:smaller'>ges.</span></abbr>"
			end
		end
	end
	ret = ret .. "\n! style='background-color:" .. colour2 .. "; color:#202122; border:none;"
	if listtype == "Jahr" or listtype == "JahrA" or listtype == "JahrS" then
		ret = ret .. "border-bottom: 1pt solid white; width:10%' class='charts-th' | <span class='" .. cssclass.hidemobile .. "'>Position</span><span class='" .. cssclass.mobileonly .. "'>#</span>"
	else
		ret = ret .. "text-align:left; width:15%' class='charts-trh' | Interpret "
		ret = ret .. "!! style='background-color:" .. colour2 .. "; color:#202122; border:none; text-align:left; font-style:italic; width:25%' class='charts-trh' | Titel"
		if listtype ~= "Alben" then
			ret = ret .. "<span style='font-size:smaller; font-style:normal;'><br />Autor(en)</span>"
		end
	end
	ret = ret .. "\n! style='background-color:" .. colour2 .. "; color:#202122; border:none;"
	if listtype == "Jahr" or listtype == "JahrA" then
		ret = ret .. "border-bottom: 1pt solid white; width:45%;' class='unsortable charts-th' | <span style='font-size:larger'>Alben</span>"
	elseif listtype == "JahrS" then
		ret = ret .. "border-bottom: 1pt solid white; width:45%;' class='unsortable charts-th' | <span style='font-size:larger'>Singles</span>"
	else
		ret = ret .. "text-align:left; width:40%;' class='unsortable charts-trh' | Zusätzliche Informationen"
		
		-- mobile table header
		ret = ret .. "\n|- style='background-color:" .. colour2 .. "; color:#202122;'"
		ret = ret .. "\n! style='font-size:smaller; font-weight:normal; background-color:" .. colour2 .. "; color:#202122; '"
		ret = ret .. " class='unsortable " .. cssclass.mobileonlycell .. " charts-th' | (Zeitraum,"
		if months then
			ret = ret .. " Monate"
		else
			ret = ret .. " Wochen"
		end
		ret = ret .. " auf Platz eins, Interpret, <i>Titel</i>, "
		if listtype ~= "Alben" then
			ret = ret .. "Autor[en], "
		end
		ret = ret .. "zusätzliche Informationen)"
		-- /
		
	end
	-- /
	
	-- content
	ret = ret .. "\n|- \n" .. (content or "") .. "\n|}"
	-- /
	
	-- navigation footer
	ret = ret .. "\n|- style='background-color:" .. colour1 .. "; color:inherit;' \n| style='line-height:1em;' | "
	if prevyear >= tonumber(firstyear) then
		ret = ret .. "[[" .. linkprev .. sectionlink .. "|← <br class='" .. cssclass.mobileonly .. "' />" .. prevyear .. "]]"
	end
	ret = ret .. "\n| colspan='3' | &nbsp; \n| style='text-align:right;line-height:1em;' |"
	if tonumber(year) < currentyear then
		ret = ret .. "[[" .. linknext .. sectionlink .. "|<span class='" .. cssclass.mobileonly .. "'>→<br /></span>" .. nextyear .. "<span class='" .. cssclass.hidemobile .. "'> →</span>]]"
	end
	-- /
	
	ret = ret .. "\n|}"

return ret

end


-- Nummer-eins-Hits Zeile - no. 1 table rows
p.no1tablerow = function (frame)
	local parameters = frame.args
	if not parameters.Chartein then parameters = mw.getCurrentFrame():getParent().args end
	
	local currentweek = mw.getContentLanguage():formatDate( 'W' )
	
	-- direct template parameters
	local chartentry = parameters.Chartein or tostring(currentweek - 1)
	if chartentry == "" then
		chartentry = nil
	end
	local chartexit = parameters.Chartaus or tostring(currentweek)
	if chartexit == "" then
		chartexit = nil
	end
	local yearturn = parameters.Jahr
	if yearturn == "" then
		yearturn = nil
	end
	local givenweeks = parameters.Wochen
	if givenweeks == "" then
		givenweeks = nil
	end
	local givenmonths = parameters.Monate
	if givenmonths == "" then
		givenmonths = nil
	end
	local total = parameters.Insges
	if total == "" then
		total = nil
	end
	local artist = parameters.Interpret
	if artist == "" then
		artist = nil
	end
	local title = parameters.Titel
	if title == "" then
		title = nil
	end
	local songwriters = parameters.Autor
	if songwriters == "" then
		songwriters = nil
	end
	local notes = parameters.Info
	if notes == "" then
		notes = nil
	end
	-- /

	-- derived parameters
	local pagename = mw.title.getCurrentTitle().text
	local year
	if string.match (pagename, ".+%(%d%d%d%d%)") then
		year = string.match (pagename, ".+%((%d%d%d%d)%)")
	else
		year = os.date( "%Y" )
	end
	local chartentryyear
	if string.match (chartentry, "%d%d%d%d") then
		chartentryyear = string.match (chartentry, "(%d%d%d%d)")
	end
	local chartexityear = string.match (chartexit, "(%d%d%d%d)")
	if string.match (chartexit, "%d%d%d%d") then
		chartexityear = string.match (chartexit, "(%d%d%d%d)")
	end
	-- /
	
	-- service links
	local slgiven = "<span style='display:none'>[[Template:Nummer-eins-Hits/Wartung/feste Dauer]]</span>"
	local slmonths = "<span style='display:none'>[[Template:Nummer-eins-Hits/Wartung/Monate]]</span>"
	local slerrordate = "<span style='display:none'>[[Template:Nummer-eins-Hits/Wartung/Datumsfehler]]</span>"
	-- /
	
	-- date formats
	local entrydateview
	local entrydateweek
	local entrydatemonth
	local sortdate
	if #chartentry > 2 then
		local entrydate = DateTime (chartentry)
		if type (entrydate) == "string" or type (entrydate) == "boolean" then
			return "<span class='error'>Parameter Chartein: falsches Format</span>" .. slerrordate
		end
		entrydateview = entrydate:format ("T._Monat JJJJ")
		sortdate = entrydate:format ("ISO")
		entrydateweek = entrydate:format ("W")
		entrydatemonth = entrydate:format ("m")
	else
		entrydateview = chartentry .. "."
		sortdate = chartentry
		entrydateweek = chartentry
	end
	
	local exitdateview
	local exitdateweek
	local exitdatemonth
	if #chartexit > 2 then
		local exitdate = DateTime (chartexit)
		if type (exitdate) == "string" or type (exitdate) == "boolean" then
			return "<span class='error'>Parameter Chartaus: falsches Format</span>" .. slerrordate
		end
		exitdateview = exitdate:format ("T._Monat JJJJ")
		local exitdate1 = exitdate + "1 day"
		exitdateweek = exitdate1:format ("W")
		exitdatemonth = exitdate:format ("m")
	else
		exitdateview = chartexit .. ".&nbsp;Woche"
		exitdateweek = chartexit + 1
	end

	-- auto-calculate week and month number
	local weeks = (exitdateweek - entrydateweek)
	local months
	if #chartentry > 2 and #chartexit > 2 then
		months = (exitdatemonth - entrydatemonth) + 1
		if months < 0 then
			months = months + 12
		end
	end
	local year1 = year
	if yearturn == "-1" then
		year1 = year - 1
	end
	if chartentryyear then
		year1 = chartentryyear
		if chartentryyear == chartexityear then
			if tonumber(exitdatemonth) then
				if tonumber(exitdatemonth) < 10 then
					year1 = year1 - 1
				end
			end
		end
	end
	local endweekdate = year1 .. "-12-28"
	local endweek = DateTime (endweekdate)
	local weeksyear = endweek:format ("W")
	if weeks < 0 then
		weeks = weeks + weeksyear
	end
	if weeks == 0 then
		weeks = 1
	end

	-- build table row
	local ret = "\n|- class='newno1tablerow' style='padding-top:5px; border:none; margin:0;' "
	
	-- date
	ret = ret .. "\n| style='border:none;' data-sort-value='" .. sortdate .. "'|" .. entrydateview
	if #chartentry <= 2 and #chartexit <= 2 then
		if tonumber(chartexit) < tonumber(chartentry) then
			if yearturn == "-1" then
				ret = ret .. "&nbsp;Woche " .. (year -1) .. "&nbsp;&ndash; " .. exitdateview .. " " .. (year)
			else
				ret = ret .. "&nbsp;Woche " .. year .. "&nbsp;&ndash; " .. exitdateview .. " " .. (year +1)
			end
		elseif chartentry == chartexit then
			ret = ret .. "&nbsp;Woche"
		else
			ret = ret .. "&ndash;" .. exitdateview
		end
	elseif entrydateview ~= exitdateview then
		if #chartentry <= 2 then
			ret = ret .. " Woche"
		end
		ret = ret .. "&nbsp;&ndash; " .. exitdateview
	end
	ret = ret .. "<br /><span style='font-size:smaller'>"
	
	local monthview
	if (not string.match (entrydateview, "%.") and not givenweeks) or givenmonths then
		monthview = true
	end
	
	if not monthview then
		ret = ret .. (givenweeks or weeks or "&hellip;") .. "&nbsp;Woche"
		if givenweeks then
			if givenweeks ~= "1" then
				ret = ret .. "n"
			end
		else
			if weeks ~= 1 then
				ret = ret .. "n"
			end
		end
	else
		ret = ret .. (givenmonths or months or "&hellip;") .. "&nbsp;Monat"
		if givenmonths then
			if givenmonths ~= "1" and givenmonths ~= "½" then
				ret = ret .. "e"
			end
		else
			if months ~= 1 and months ~= "½" then
				ret = ret .. "e"
			end
		end
	end
	ret = ret .. "</span>"
	-- /
	
	-- total weeks/months
	local totaldisplay
	local mobiletotal
	if monthview then
		totaldisplay = total or givenmonths or months
		if totaldisplay ~= months then
			mobiletotal = true
		end
	else
		totaldisplay = total or givenweeks or weeks
		if totaldisplay ~= weeks then
			mobiletotal = true
		end
	end
	if mobiletotal then
		ret = ret .. "<span style='font-size:smaller;' class='" .. cssclass.mobileonly .. "'> (insgesamt " .. totaldisplay .. ")</span>"
	end
	ret = ret .. "\n| style='text-align:center; border:none;' class='" .. cssclass.hidemobile .. "' |" .. totaldisplay
	-- /
	
	ret = ret .. "\n| style='border:none;' "
	if artist then
		if string.match(artist, "data%-sort%-value") then
			ret = ret .. artist
		else
			ret = ret .. "| " .. artist
		end
	else
		ret = ret .. "| Interpret"
	end
	
	ret = ret .. "\n| style='border:none; font-style:italic;' | " .. (title or "Titel")
	
	if songwriters then
		ret = ret .. "<br /><span style='font-style:normal;font-size:smaller;'>" .. songwriters .. "</span>"
	end
	
	ret = ret .. "\n|"
	if not notes then ret = ret .. " class='" .. cssclass.hidemobile .. "'" end
	ret = ret .. " style='border:none;' | " .. (notes or "&ndash;")
	
	-- create service links
	if givenweeks or givenmonths then
		ret = ret .. slgiven
	elseif monthview then
		ret = ret .. slmonths
	end
	-- /
	
	return ret
end


-- Jahreshitparaden Zeile - year-end chart table row
p.yearendrow = function (frame, half)
	local parameters = frame.args
	if not parameters.Position then parameters = mw.getCurrentFrame():getParent().args end
	
	-- direct template parameters
	local position = parameters.Position
	
	local single = parameters.Single
	if single == "" then
		single = false
	end
	local album = parameters.Album
	if album == "" then
		album = false
	end
	local singleartist = parameters.InterpretS
	if singleartist == "" then
		singleartist = false
	end
	local albumartist = parameters.InterpretA
	if albumartist == "" then
		albumartist = false
	end
	local songwriter = parameters.Autor
	if songwriter == "" then
		songwriter = false
	end
	-- /
	
	local ret = "|- class='newno1tablerow' style='padding-top:5px; border:none; margin:0;'"
	if not half then
		ret = ret .. "\n| style='text-align:center; border:none; margin:0; width:45%'|"
		ret = ret .. "<i>" .. (single or "&hellip;") .. "</i>"
		if singleartist then
			ret = ret .. "<br />" .. singleartist
		end
		if songwriter then
			ret = ret .. "<br /><span style='font-size:smaller'>" .. songwriter .. "</span>"
		end
	end
	ret = ret .. "\n| style='text-align:center; font-size:larger; font-weight:bold; border:none; margin:0; width:10%'|" .. (position or "#")
	ret = ret .. "\n| style='text-align:center; border:none; margin:0; width:45%'|"
	ret = ret .. "<i>"
	if half then
		ret = ret .. (album or single or "&hellip;") 
	else
		ret = ret .. (album or "&hellip;")
	end
	ret = ret .. "</i>"
	if albumartist then
		ret = ret .. "<br />" .. albumartist
	elseif half then
		if singleartist then
			ret = ret .. "<br />" .. singleartist
		end
		if songwriter then
			ret = ret .. "<br /><span style='font-size:smaller'>" .. songwriter .. "</span>"
		end
	end
	
	return ret
	
end


-- Jahreshitparade Zeile - year-end chart table row one-col
p.yearendrowhalf = function (frame)
	local parameters = frame.args
	if not parameters.Position then parameters = mw.getCurrentFrame():getParent().args end
	
	local half = true
	
	return p.yearendrow( frame, half )

end


return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.