Modul:Musikcharts

aus Wikipedia, der freien Enzyklopädie
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'>Charttabelle: Zu viele Länder definiert!</span>" .. sltoomanycountries end
	-- /
	
	-- direct template parameters
	local source = parameters.Quellen
	if source then
		source = mw.text.trim (source)
			:gsub ("\n", "")
	end
	local rformat = parameters.Art
	local sortable = parameters.sortierbar
	local grey = parameters["Grautöne"]
	local extra = parameters.Extra
	local titleaddition = parameters.TitelErg
	local givenwidth = parameters.Breite
	local content = parameters.INHALT or ""
	-- /
	
	-- headers
	local headerclass = "charts-trh"
	local mobheaderclass = "charts-th"
	if grey then
		headerclass = "charts-trhg"
		mobheaderclass = "charts-thg"
	end
	-- /
	
	-- parameter check
	local templatename
	if christmas then
		templatename = "[[Vorlage:Weihnachtscharttabelle|Weihnachtscharttabelle]]"
	else
		templatename = "[[Vorlage:Charttabelle|Charttabelle]]"
	end
	local parametercheck = {
		["mandatory"] = {"INHALT", "1"},
		["optional"] = {"Quellen", "Art", "sortierbar", "Grautöne", "2", "3", "4", "5", "6", "7", "8"},
		["template"] = templatename
	}
	if not christmas then
		table.insert (parametercheck["optional"], "Extra")
		table.insert (parametercheck["optional"], "TitelErg")
		table.insert (parametercheck["optional"], "Breite")
	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, "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 charts-tbor"
	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
	ret = ret .. "' style='text-align:center;"
	if not grey then ret = ret .. " background-color:#E1E9F3;" end
	ret = ret .. "'\n|-\n! style='width:25px;' class='" .. mobheaderclass .. " " .. headerclass .. "' rowspan='2' | "
	if christmas then
		ret = ret .. "Periode"
	else
		ret = ret .. "Jahr"
		ret = ret .. "\n! style='width:" .. tablewidth[width][1] .. "px;' class='" .. mobheaderclass .. " " .. headerclass .. "' rowspan='2'| Titel"
		if titleaddition then
			ret = ret .. "<br /><span style='font-size:smaller;font-style:italic;'>" .. titleaddition .. "</span>"
		elseif rformat == "Singles" then
			ret = ret .. "<br /><span style='font-size:smaller;font-style:italic;'>Album</span>"
		end
	end
	ret = ret .. "\n! class='" .. mobheaderclass .. "' colspan='" .. #countries .. "'| "
	ret = ret .. "<span style='white-space:nowrap;'><span class='charts-hidm charts-certc'><span class='charts-certt'>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 .. "Chartplatzierungen"
	else
		ret = ret .. "Charts"
	end
	ret = ret .. "</span><span class='charts-monl'>Chartplatzierungen</span>"
	
	-- sources
	ret = ret .. (source or slnosources) .. "</span>"
	-- /
	
	-- insert service links
	if rformat then
		if not rformat == "" and not rformat == "Singles" and not rformat == "Alben" then
			ret = ret .. slwrongrformat
		end
	end
	if months then
		ret = ret .. slmonths
	end
	-- /
	
	-- mobile header
	ret = ret .. "<span class='charts-monl 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 == "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' | Anmerkungen"
		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%-monla'") then
		ret = ret .. "\n! style='font-style:italic;border:none;margin-top:-1px;' class='charts-monlc 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 == "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
		if string.match (country, "]]") then
			country = country:gsub("</?small>", "")
			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 == "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 == "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 ("background%-color:#FFEBAD;", "background-color:#F0F0FF;")
	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%-monl.-<span.-class='charts%-)monla'>%[(.-)&uarr;(%]</span>)", "%1monl' style='font-size:smaller;font-style:italic;'> %[%2&larr;%3"))
	end
	if string.match (content, "&uarr;%]") then
		content = string.gsub (content, "\n|[^\n]*charts%-monl[^\n]*<span[^\n]*charts%-monla[^\n]*", replacer)
	end
		-- visibility in hidden cells
		content = string.gsub (content, "(\n|[^\n]*)charts%-hidm([^\n]*)' | &mdash;([^\n]*<span[^\n]*charts%-monla)", "%1charts-aup%2' | <span class='charts-hidm'>&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='charts-hidm charts-hidp'><span class='charts-nxa' style='padding:2px;border:solid .5px grey;font-style:italic;'>grau schraffiert</span>: keine Chartdaten aus diesem Jahr verfügbar</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.Art
	local comment = parameters.Anmerkung
	local istable = parameters.Tabelle
	local grey = parameters["Grautöne"]
	-- /
	
	local greycountry
	if grey then
		greycountry = "g"
	else
		greycountry = ""
	end
	
	-- parameter check
	local parametercheck = {
		["mandatory"] = {"1"},
		["optional"] = {"Art", "Anmerkung", "Extra", "Tabelle", "Grautöne", "2", "3", "4", "5", "6", "7", "8"},
		["template"] = "Chartauswertung"
	}
	-- /
	
	-- start building table
	local ret
	if istable then
		ret = "{| class='wikitable charts-table charts-tbor"
		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 .. "background-color:#FFEBAD;' 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='charts-hidm' 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 = "NR1_" .. 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='charts-hidm' | "
		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='charts-hidm' |"
		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 = "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='charts-hidm' | "
		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 .. "background:#FBF8D6;" 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 = "INSG_" .. 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='charts-hidm' | "
		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.Periode
	else
		year = parameters.Jahr
	end
	local colour = parameters.Farbe
	local unnumberedtitle
	if christmas then
		unnumberedtitle = "title"
	else
		unnumberedtitle = parameters["Titel"]
	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"], "Periode")
	else
		table.insert (parametercheck["optional"], "Jahr")
	end
	-- /
	
	-- row numbering
	if unnumberedtitle then
		parameters["Farbe1"] = parameters["Farbe"]
		table.insert (parametercheck["optional"], "Farbe")
		parameters["Titel1"] = unnumberedtitle
		parameters["Album1"] = parameters["Album"]
		parameters["TitelErg1"] = parameters["TitelErg"]
		for c = 1, #countries do
			local ps = "POS_" .. countries[c]
			table.insert (parametercheck["optional"], ps)
			local ps1 = "POS_" .. countries[c] .. "1"
			parameters[ps1] = parameters[ps]
			local w = "WO_" .. countries[c]
			table.insert (parametercheck["optional"], w)
			local w1 = "WO_" .. countries[c] .. "1"
			parameters[w1] = parameters[w]
			local m = "MT_" .. countries[c]
			table.insert (parametercheck["optional"], m)
			local m1 = "MT_" .. countries[c] .. "1"
			parameters[m1] = parameters[m]
			local y = "Jahr_" .. countries[c]
			table.insert (parametercheck["optional"], y)
			local y1 = "Jahr_" .. countries[c] .. "1"
			parameters[y1] = parameters[y]
			local s = "Spalten_" .. countries[c]
			table.insert (parametercheck["optional"], s)
			local s1 = "Spalten_" .. countries[c] .. "1"
			parameters[s1] = parameters[s]
			local z = "Zeilen_" .. countries[c]
			table.insert (parametercheck["optional"], z)
			local z1 = "Zeilen_" .. countries[c] .. "1"
			parameters[z1] = parameters[z]
			local a = "A_" .. countries[c]
			table.insert (parametercheck["optional"], a)
			local a1 = "A_" .. countries[c] .. "1"
			parameters[a1] = parameters[a]
		end
		parameters["Anmerkung1"] = parameters["Anmerkung"]
		parameters["Extra1"] = parameters["Extra"]
		parameters["Zeilen_Extra1"] = parameters["Zeilen_Extra"]
		if not christmas then
			table.insert (parametercheck["optional"], "Titel")
			table.insert (parametercheck["optional"], "Album")
			table.insert (parametercheck["optional"], "TitelErg")
			table.insert (parametercheck["optional"], "Anmerkung")
			table.insert (parametercheck["optional"], "Extra")
			table.insert (parametercheck["optional"], "Zeilen_Extra")
		end
	end
	local rows = 0
	repeat
		rows = rows + 1
		local title = "Titel" .. 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>"
	
	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' style='background:#FBF8D6;' \n| style='font-style:italic;' | " .. year
	else
		if colour == "1" then
			ret = ret .. " style='background:#eeeeee;'"
		elseif colour == "0" then
			ret = ret .. " style='background:#e1e9f3;'"
		end
		ret = ret .. "\n | rowspan='" .. rows .. "' style='background-color:#f0f0ff;' | " .. (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 = "Titel" .. row
		local title = parameters[t]
		local a = "Album" .. row
		local album = parameters[a]
		local ta = "TitelErg" .. row
		local titleaddition = parameters[ta]
		local co = "Farbe" .. row
		local rowcolour = parameters[co]
		if row > 1 then
			ret = ret .. "\n|- "
		-- individual row colours, overwriting everything
			if rowcolour == "1" then
				ret = ret .. " style='background:#eeeeee;'"
				else
					if rowcolour == "0" then
						ret = ret .. " style='background:#e1e9f3;'"
						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 .. " style='background:#eeeeee;'"
								elseif colour == "1" then
									ret = ret .. " style='background:#e1e9f3;'"
								end
							-- if odd
							else
								if colour == "0" then
									ret = ret .. " style='background:#e1e9f3;'"
								elseif colour == "1" then
									ret = ret .. " style='background:#eeeeee;'"
								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' style='text-align:left;' | " .. title -- class newcharttablerow for row count in charttable
			if album or titleaddition then
				ret = ret .. "<br /><span style='font-size:smaller;"
				if not (album == "–" or titleaddition == "–") then
					ret = ret .. "font-style:italic;"
				end
				ret = ret .. "'>" .. (album or titleaddition) .. "</span>"
			end
		end

		for c = 1, #countries do
			local country = countries[c]
			local ps = "POS_" .. country .. row
			table.insert (parametercheck["optional"], ps)
			local position = parameters[ps]
			local w = "WO_" .. country .. row
			table.insert (parametercheck["optional"], w)
			local weeks = parameters[w]
			local m = "MT_" .. country .. row
			table.insert (parametercheck["optional"], m)
			local months = parameters[m]
			local y = "Jahr_" .. country .. row
			table.insert (parametercheck["optional"], y)
			local year1 = parameters[y]
			local s = "Spalten_" .. country .. row
			table.insert (parametercheck["optional"], s)
			if parameters[s] and #parameters[s] == 0 then parameters[s] = nil end
			local z = "Zeilen_" .. country .. row
			table.insert (parametercheck["optional"], z)
			if parameters[z] and #parameters[z] == 0 then parameters[z] = nil end
			local a = "A_" .. 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 .. "charts-hidm"
					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='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(&hellip; Wo.)</span>" .. sltemporary
								else
									ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </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='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(&hellip; Mt.)</span>" .. sltemporary
									else
										ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </span><span style='font-size:smaller;'>(" .. months .. " Mt.)</span>"
									end
								end
							else -- default is weeks
								if position then
									ret = ret .. position .. certification .. "<br class='charts-hidm'><span class='charts-monl'> </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
						-- /
					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='charts-monla'>[" .. (countryfunctions.countrycol (country, c, true) or country or "") .. ":&nbsp;&uarr;]</span>"
			end
		end
		
		-- final table columns
		if not christmas then
			local com = "Anmerkung" .. row
			table.insert (parametercheck["optional"], com)
			local comment = parameters[com]
			ret = ret .. "\n| style='text-align:left;' "
			if comment and comment ~= "" then
				ret = ret .. "| <div style='font-size:smaller;'>\n" .. comment .. "</div>"
			else
				ret = ret .. "class='charts-hidm' |"
			end
			local x = "Extra" .. row
			table.insert (parametercheck["optional"], x)
			local extra = parameters[x]
			local zx = "Zeilen_Extra" .. row
			table.insert (parametercheck["optional"], zx)
			if extra then
				if parameters[zx] then
					ret = ret .. "\n| rowspan='" .. parameters[zx] .. "' style='text-align:left;' | " .. extra
				else
					ret = ret .. "\n| style='text-align:left;' | " .. (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
	for searchrow = 1, rows do
		if string.match (entry[searchrow], "&nbsp;" .. label.mt) then
			months = true
		end
	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 = label.weeks
	if months then
		weeksmonths = weeksmonths .. "/<br />" .. 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(cssclass.charttableborder)
								: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 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
			months = string.gsub (weeks, "%s?" .. label.mt, "")
			mobileweekdisplay = months .. "&nbsp;" .. label.mt
			weekdisplay = mobileweekdisplay
		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.Bild
	local caption = parameters.Bildbeschreibung
	local temporary = parameters["vorläufige Chartplatzierung"]

	local albums = parameters.Alben
	local eps = parameters.EPs
	local singles = parameters.Singles
	local dvds = parameters.DVDs

	local refalbums = parameters["Quellen Alben"]
	local refeps = parameters["Quellen EPs"]
	local refsingles = parameters["Quellen Singles"]
	local refdvds = parameters["Quellen DVDs"]
	local source = parameters.Quellen
	-- /
	
	-- 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>"
	-- /
	
	-- start building infobox
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	ret = ret .. "<div class='infobox' style='background:none;border:none;'>\n{| class='charts-infobox' \n|-"
	
	-- image
	if file then
		if file ~= "" then
			ret = ret .. "\n| style='text-align:center' | [[File:" .. file .. "|210px|" .. (caption or mw.title.getCurrentTitle().text) .. "]]"
			if caption then
				if caption ~= "" then
					ret = ret .. "\n|- \n| style='text-align:center; font-size:smaller;' | " .. caption
				end
			end
		end
	end
	-- /
	
	-- header
	ret = ret .. "\n|- \n| style='background-color:#F3F3F3; text-align:center;' | <span style='font-size:20px; font-stretch:condensed;'>Chartplatzierungen</span>"
	if temporaryweeks then
		ret = ret .. "<br /><span style='font-size:12px; font-stretch:condensed;'>(vorläufig)</span>"
	end
	ret = ret .. "<br /><span style='font-size:smaller;'>[[Wikipedia:Formatvorlage Charts|Erklärung der Daten]]</span>"
	-- /
	
	-- content
	for section = 1, 4 do
		local titles = {"Alben", "EPs", "Singles", "DVDs"}
		if rformats[section] then
			if rformats[section] ~= "" then
				ret = ret .. "\n|- style='background:#EAECF0;' \n| style='padding:0 .3em;' | <span style='font-size:larger; font-weight:bold;'>" .. titles[section] .. "</span>" .. (refs[section] or "")
				ret = ret .. "\n|- \n| style='padding:0 .3em .5em .3em;' | "
				-- inner table
				ret = ret .. "\n{| style='border-collapse:collapse;width:222px;display:table;' \n" .. rformats[section] .. "\n|}"
				if string.match (rformats[section], "<!%-%-%$QUELLEZEILE%$%-%->") then
					refrow = true
				end
			end
		end
	end
	-- /
	
	ret = ret .. "\n|}"
-- /
	
	-- 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
	-- /
	ret = ret .. "</div>"
	
	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, "Vorlage:(%a*)")
	local rows = {}
	local i = 0
	for k, v in ipairs (parameters) do
		if rformat == "Single" 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
	--/
	
	-- content (rows)
	local ret = "\n|- \n| colspan='6' style='font-size:95%;font-weight:bold;' |" .. title
	
	for row = rownumberstart, #rows do
		ret = ret .. "\n|- style='background:#F3F3F3;' \n" .. mw.text.trim( (rows[row] or "") )
	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.Jahr 
	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 slno1link = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/NR1-Link]]</span>"
	local sltemporary = "<span style='display:none'>[[Template:Infobox Chartplatzierungen/Wartung/vorläufig"
	if year then
		if tonumber(year) > 2009 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 ret = "| style='width:3%; background-color:white;' | &nbsp;"
	ret = ret .. "\n| style='width:12%; font-size:95%; line-height:90%;' | "
	
	ret = ret .. countryfunctions.countrycol (country, 1, nil, "infobox")
	
	if (country == "BEL" or country == "BE") and (tonumber(year) or 0) > 1994 then
		ret = ret .. slbelgium
	end
	
	-- chart position
	ret = ret .. "\n| style='width:27%; font-size:95%; font-weight:bold; text-align:center;' | "
	if position then
		if position == "1" or string.match(position, "^1%D") then
			position = countryfunctions.numberonelinks (position, country, year)
			if not parameters.Jahr then
				position = position .. slno1link
			end
		end
		ret = ret .. position
	end
	-- /
	
	-- certification
	if certification then
		certification = "&thinsp;" .. certicon.certicon(frame, certification, nil, "16")
	else
		certification = ""
	end
	ret = ret .. certification
	if position == "" then
		ret = ret .. "<span style='font-size:85%;'>" .. (certref or "") .. "</span>"
		certref = ""
	end
	-- /
	
	ret = ret .. "\n| style='width:30%; font-size:smaller;' | " .. (entrydate or "")
	
	-- weeks or months on charts
	ret = ret .. "\n| style='width:23%; text-align:right; padding-left:5px; font-size:smaller;' | "
	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, "Mt") then
			ret = ret .. "(" .. weeks .. ")"
		else
		    ret = ret .. "(" .. weeks .. "&nbsp;Wo.)"
		end
	end
	-- /
	
	ret = ret .. "\n| style='width:5%; font-size:smaller;' | " .. (ref or "") .. (certref or "")
	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.Statistik
	local main = parameters.Hauptartikel
	local note = parameters.Hinweis
	local source = parameters.Q
	local nosilver = parameters.S
	local nodiamond = parameters.D
	
	local silver = parameters.GesS
	local gold = parameters.GesG
	local platinum = parameters.GesP
	local diamond = parameters.GesD
	local number = parameters.GesZ
	
	local grey = parameters["Grautöne"]
	-- /
	
	local headerclass = "charts-trh"
	local mobheaderclass = "charts-th"
	if grey then
		headerclass = "charts-trhg"
		mobheaderclass = "charts-thg"
	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, "/Auszeichnungen für Musikverkäufe") then
		local pagenameroot = string.match ( pagename, "(.+)/Diskografie" ) or pagename
		local certifications = pagenameroot .. "/Auszeichnungen für Musikverkäufe"
		if mw.title.new( certifications ).exists == false then
			ret = ret .. "\n<span style='font-style:italic;font-size:smaller;'>Anmerkung: Auszeichnungen in Ländern aus den Charttabellen bzw. Chartboxen sind in ebendiesen zu finden.</span>"
		end
	end
	
	-- start building table (normal/statistics)
	ret = ret .. "\n{| class='wikitable charts-table charts-tbor"
	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='charts-hidm'>Land/Region</span><span class='charts-monl'>Aus&shy;zeich&shy;nung&shy;en für Mu&shy;sik&shy;ver&shy;käu&shy;fe<br /><span class='charts-mh'>(Land/Region, Auszeichnungen, Verkäufe, Quellen)</span></span> \n!"
		if not nosilver then
			ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. sicon .. "Silber !! "
		end
		ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. gicon .. "Gold !! "
		ret = ret .. " class='" .. headerclass .. "' data-sort-type='number' | " .. picon .. "Platin"
		if not nodiamond then
			ret = ret .. " !! class='" .. headerclass .. "' data-sort-type='number' | " .. dicon .. "Diamant"
		end
		ret = ret .. "\n! style='width:90px;' class='" .. headerclass .. "' data-sort-type='number' | Ver&shy;käu&shy;fe"
		ret = ret .. "\n ! class='unsortable " .. headerclass .. "' | Quel&shy;len"
	else
		ret = ret .. "' style='max-width:100%;' \n|-"
		ret = ret .. "\n! style='width:250px;' class='" .. headerclass .. "' | Land/Region"
		ret = ret .. "\n! style='width:150px;' class='" .. mobheaderclass .. "' | Aus&shy;zeich&shy;nung" .. "<span class='charts-monl'>&shy;en für Mu&shy;sik&shy;ver&shy;käu&shy;fe<br /><span class='charts-mh'>(Land/Region, Auszeichnung, Verkäufe)</span></span>" .. (source or "")
		ret = ret .. "\n! style='width:90px;' class='" .. headerclass .. "' data-sort-type='number' | Ver&shy;käu&shy;fe"
	end
	
	-- single rows
	ret = ret .. "\n|-"
	for row = 1, rows do
		local content = entry[row]
		if statistics then
			-- delete empty columns
			if nosilver then
				content = string.gsub (content, "\n| style='text%-align:center;' class='charts%-hidm' | <span style='display:none;'>0! S</span>&mdash;", "")
			end
			if nodiamond then
				content = string.gsub (content, "\n| style='text%-align:center;' class='charts%-hidm' | <span style='display:none;'>0! D</span>&mdash;", "")
			end
		end
		ret = ret .. "\n" .. content .. "\n|-"
	end
	
	ret = ret .. "\n|-"
	if statistics then
		if not grey then ret = ret .. "style='background:#FBF8D6;' " end
		ret = ret .. "class='sortbottom' \n| style='font-weight:bold;' | Insgesamt"
		
		if not nosilver then
			if silver and silver ~= "" and silver ~= "0" then
				local silvercert = silver .. "S"
				ret = ret .. "\n| style='text-align:center;' |"
				-- mobileview
				ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, silvercert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='charts-hidm' style='font-weight:bold;'>" .. silver .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;font-weight:bold;' class='charts-hidm' | &mdash;"
			end
		end
		
		if gold and gold ~= "" and gold ~= "0" then
			local goldcert = gold .. "G"
			ret = ret .. "\n| style='text-align:center;' |"
			-- mobileview
			ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, goldcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='charts-hidm' style='font-weight:bold;'>" .. gold .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;font-weight:bold;' class='charts-hidm' | &mdash;"
		end
		
		if platinum and platinum ~= "" and platinum ~= "0" then
			local platinumcert = platinum .. "P"
			ret = ret .. "\n| style='text-align:center;' |"
			-- mobileview
			ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, platinumcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='charts-hidm' style='font-weight:bold;'>" .. platinum .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;font-weight:bold;' class='charts-hidm' | &mdash;"
		end
		
		if not nodiamond then
			if diamond and diamond ~= "" and diamond ~= "0" then
				local diamondcert = diamond .. "D"
				ret = ret .. "\n| style='text-align:center;' |"
				-- mobileview
				ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, diamondcert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='charts-hidm' style='font-weight:bold;'>" .. diamond .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;font-weight:bold;' class='charts-hidm' | &mdash;"
			end
		end
		
		ret = ret .. "\n| colspan='2' |"
	else
		if number then
			if not grey then ret = ret .. "style='background:#FBF8D6;' " end
			ret = ret .. "\n| <i>Insgesamt</i> \n| style='text-align:center; font-style:italic;' |"
			if silver or gold or platinum or diamond then
				if silver then
					ret = ret .. sicon .. silver .. "× Silber<br />"
				end
				if gold then
					ret = ret .. gicon .. gold .. "× Gold<br />"
				end
				if platinum then
					ret = ret .. picon .. platinum .. "× Platin<br />"
				end
				if diamond then
					ret = ret .. dicon .. diamond .. "× Diamant<br />"
				end
			else
				ret = ret .. "&mdash;"
			end
			ret = ret .. "\n| style='text-align:right; font-style:italic;' | <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;'>Hauptartikel: [[" .. 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.S
	local gold = parameters.G
	local platinum = parameters.P
	local diamond = parameters.D
	local source = parameters.Q
	
	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")
	-- /
	
	-- 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>"
	-- /
	
	-- start building table row
	local ret = "| "
	
	-- create flag template
	ret = ret .. countrydisplay
	-- /
	
	local sumtest
	if parameters[2] then 
		sumtest = parameters[2]:gsub("%(", ""):gsub("%)", ""):gsub("%.", "")
	end
	if silver or gold or platinum or diamond or tonumber(sumtest) then -- statistics table
		local sum2 = parameters[2]
		if silver ~= "n" then
			if silver and silver ~= "" and silver ~= "0" then
				local silvercert = silver .. "S"
				ret = ret .. "\n| style='text-align:center;' data-sort-value='" .. silver .. "' |"
				-- mobileview
				ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, silvercert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='charts-hidm'>" .. silver .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | <span style='display:none;'>0! S</span>&mdash;"
			end
		end
		
		if gold and gold ~= "" and gold ~= "0" then
			local goldcert = gold .. "G"
			ret = ret .. "\n| style='text-align:center;' data-sort-value='" .. gold .. "' |"
			-- mobileview
			ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, goldcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='charts-hidm'>" .. gold .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | <span style='display:none;'>0! G</span>&mdash;"
		end
		
		if platinum and platinum ~= "" and platinum ~= "0" then
			local platinumcert = platinum .. "P"
			ret = ret .. "\n| style='text-align:center;' data-sort-value='" .. platinum .. "' |"
			-- mobileview
			ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, platinumcert, "text") .. "</span>"
			-- desktopview
			ret = ret .. "<span class='charts-hidm'>" .. platinum .. "</span>"
		else
			ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | <span style='display:none;'>0! P</span>&mdash;"
		end
		
		if diamond ~= "n" then
			if diamond and diamond ~= "" and diamond ~= "0" then
				local diamondcert = diamond .. "D"
				ret = ret .. "\n| style='text-align:center;' data-sort-value='" .. diamond .. "' |"
				-- mobileview
				ret = ret .. "<span class='charts-monl'>" .. certicon.certicon(frame, diamondcert, "text") .. "</span>"
				-- desktopview
				ret = ret .. "<span class='charts-hidm'>" .. diamond .. "</span>"
			else
				ret = ret .. "\n| style='text-align:center;' class='charts-hidm' | <span style='display:none;'>0! D</span>&mdash;"
			end
		end
		
		if sum2 and sum2 ~= "" and sum2 ~= "0" then
			ret = ret .. "\n| style='text-align:right;' |" .. sum2 
		else
			ret = ret .. "\n| style='text-align:right;' class='charts-hidm' | <span style='display:none;'>0!</span>&mdash;"
		end
		
		if source and source ~= "" and source ~= "0" then
			ret = ret .. "\n| " .. source
		else
			ret = ret .. "\n| class='charts-hidm' | "
		end
		
	else
		ret = ret .. (source or "") .. "\n| style='text-align:center;' | "
		if not certification then
			ret = ret .. "&mdash;"
		elseif certification == "" or certification == "-" or certification == "—" then
			ret = ret .. "&mdash;"
		elseif number == "" or number == "-" or number == "—" then
			ret = ret .. certification or ""
		elseif certification == "D+P" or certification == "P+D" then
			ret = ret .. "[[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"
			ret = ret .. 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
				ret = ret .. slcustomcert
			end
			if string.match (certification, "charts-certc") or string.match (certification, "Schallplatte") or string.match (certification, "File") then
				ret = ret .. slcustomcerttemplate
			end
		end
		ret = ret .. "\n| style='text-align:right;' | " .. (sum or "&mdash;")
		
	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]
	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
	-- /
	
	-- 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' ", "")
	-- /

	-- build table	
	local ret = frame:extensionTag( "templatestyles", nil, { src = templatestyles } )
	
	-- navigation header
	ret = ret .. "\n{| style='width:100%;border-spacing:0px;' \n |- style='background-color:" .. colour1 .. "' \n| style='width:15%;line-height:1em;' |"
	if prevyear >= tonumber(firstyear) then
		ret = ret .. "[[" .. linkprev .. sectionlink .. "|<span class='charts-hidm'>← </span>" .. prevyear .. "<span class='charts-monl'><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='charts-hidm'>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='charts-monl' />→]]"
	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 .."; border:none; margin:0px;'"
	ret = ret .. "\n|- style='background-color:" .. colour2 .. "'"
	if listtype ~= "JahrA" and listtype ~= "JahrS" then
		ret = ret .. "\n! style='background-color:" .. colour2 .. "; border:none;"
		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 .. "; 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 .. "; 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='charts-hidm'>Position</span><span class='charts-monl'>#</span>"
	else
		ret = ret .. "text-align:left; width:15%' class='charts-trh' | Interpret "
		ret = ret .. "!! style='background-color:" .. colour2 .. "; 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 .. "; 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 .. "'"
		ret = ret .. "\n! style='font-size:smaller; font-weight:normal; background-color:" .. colour2 .. "'"
		ret = ret .. " class='unsortable charts-monlc 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 .. ";' \n| style='line-height:1em;' | "
	if prevyear >= tonumber(firstyear) then
		ret = ret .. "[[" .. linkprev .. sectionlink .. "|← <br class='charts-monl' />" .. 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='charts-monl'>→<br /></span>" .. nextyear .. "<span class='charts-hidm'> →</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='charts-monl'> (insgesamt " .. totaldisplay .. ")</span>"
	end
	ret = ret .. "\n| style='text-align:center; border:none;' class='charts-hidm' |" .. totaldisplay
	-- /
	
	ret = ret .. "\n| style='border:none;' |" .. (artist or "Interpret")
	
	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='charts-hidm'" 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