모듈:Medical cases chart

local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local barBox = require('Module:Bar box')
local language = 'ko-KR' -- 로컬 기본 언어
local i18n = require("Module:Medical cases chart/i18n")language
local function is(v)
	return (v or ) ~= 
end
local p = {}
function p._barColors(n)
	local colors = {
		'#A50026', --deaths
		'SkyBlue', --recoveries
		'Tomato', --cases or altlbl1
		'Gold', --altlbl2
		'OrangeRed' --altlbl3
	}
	return colorsn
end
function p._legend0(args)
	return  ..  .. '    ' ..  .. ' ' .. (args2 or ) .. 
end
function p._customBarStacked(args)
	barargs = {}
	barargs1 = args1
	local function _numwidth(nw)
		if nw == 'n' then
			return 0
		elseif nw == 't' then
			return 2.45
		elseif nw == 'm' then
			return 3.5
		elseif nw == 'w' then
			return 4.55
		elseif nw == 'x' then
			return 5.6
		elseif nw == 'd' then
			return 3.5
		end
		return 3.5
	end
	width1 = 3.5
	width2 = 3.5
	if is(args.numwidth) then
		width1 = _numwidth(mw.ustring.sub(args.numwidth,1,1))
		width2 = _numwidth(mw.ustring.sub(args.numwidth,2,2))
		width3 = _numwidth(mw.ustring.sub(args.numwidth,3,3))
		width4 = _numwidth(mw.ustring.sub(args.numwidth,4,4))
	end
	barargs2 =
		 .. (args7 or ) ..  ..
		 .. (args8 or ) .. 
	if mw.ustring.len(args.numwidth) == 4 then
		local padding = '0.3em'
		if mw.ustring.sub(args.numwidth,3,3) == 'n' then
			padding = '0'
		end
		barargs.note2 =
			 .. (args9 or ) ..  ..
			 .. (args10 or ) .. 
	end
	for i=1,5 do
		barargs2*i + 1 = p._barColors(i)
		barargs2*i + 2 = (tonumber(argsi+1) or 0)/(tonumber(args.divisor) or 1)
		barargs'title' .. i = argsi+1
	end
	barargs.align = 'cdcc'
	barargs.collapsed = args.collapsed
	barargs.id = args.id
	barargs.rowstyle = is(tonumber(args.rowheight)) and ('line-height:'..args.rowheight..';') or nil
	return barBox._stacked(barargs)
end
function p._row(args)
	local barargs = {}
	local rowDate = args.prevDate or 
	if is(args1) then
		if pcall(function () mw.getContentLanguage():formatDate(, args1) end) then
			barargs1 = args1
			rowDate = args1
		else
			barargs1 =  .. i18n.invalidTime .. 
		end
	else
		barargs1 = '⋮'
	end
	barargs2 = args2 or 0
	barargs3 = args3 or 0
	if is(args'alttot1') then
		barargs4 = args'alttot1'
	elseif args4 then
		barargs4 = (tonumber(args4) or 0) - (tonumber(barargs2) or 0) - (tonumber(barargs3) or 0)
	else
		barargs4 = 0
	end
	barargs5 = args5 or 0
	if is(args'alttot2') then
		barargs6 = args'alttot2'
	elseif args6 then
		barargs6 = (tonumber(args6) or 0) - (tonumber(barargs2) or 0) - (tonumber(barargs3) or 0)
	else
		barargs6 = 0
	end
	barargs7 = args7 or 
	local function changeArg(firstright, valuecol, changecol)
		local change = 
		if yesno(args'firstright' .. firstright) == true then
			change = '(' .. i18n.na .. ')'
		elseif yesno(args'firstright' .. firstright) == false or not is(args'firstright' .. firstright) then
			if not is(args1) and is(argsvaluecol) then
				change = '(' .. i18n'=' .. ')'
			else
				change = is(argschangecol) and '(' .. argschangecol .. ')' or 
			end
		end
		return change
	end
	barargs8 = changeArg(1,7,8)
	barargs9 = args9 or 
	barargs10 = changeArg(2,9,10)
	barargs.divisor = args.divisor or 1
	barargs.numwidth = args.numwidth
	barargs.rowheight = args.rowheight
	if yesno(args.collapsible) == true then
		local duration = tonumber(args.duration) or 15
		if args.collapsed then
			barargs.collapsed = args.collapsed
		elseif args.rowsToEnd >= duration then
			barargs.collapsed = 'y'
		else
			barargs.collapsed = 
		end
		if args.id then
			barargs.id = args.id
		elseif args.nooverlap and args.rowsToEnd = 2 and i  0 then
									change = '+' .. lang:formatNum(change)
								end
							else -- change type is "percent", "only percent" or undefined
								local percent = 100 * change / prevnum -- calculate percent
								local rounding = math.abs(percent) >= 10 and "%.0f" or math.abs(percent) >= 1 and "%.1f" or "%.2f"
								percent = tonumber(mw.ustring.format(rounding, percent)) -- round to two sigfigs
								
								if percent > 0 then
									change = '+' .. lang:formatNum(percent) .. '%'
								elseif percent (args.duration or 0) then
			rowsi.nooverlap = args.nooverlap
		end
		
		barsi = p._row(rowsi)
	end
	
	return table.concat(bars), months
end
function p._monthToggleButton(args)
	local month = mw.ustring.lower(mw.ustring.sub(args.month1 or ,1,3))
	local outString = 
	local newline = (args.nonewline or false) and  or '\n'
	if is(month) then
		local collapsed = (args.active == ) and  or ' mw-collapsed'
		local uncollapsed = (args.active == ) and ' mw-collapsed' or 
		if args.nooverlap then
			outString = '%s\n' ..
				'%s' .. newline
			
			if mw.ustring.sub(month,1,1) == 'l' and tonumber(mw.ustring.sub(month,2)) == args.duration then
				--"Last ## days"
				local lastDays = mw.ustring.format(i18n.lastDays, args.duration)
			
				outString = mw.ustring.format( outString,
					collapsed, lastDays,
					uncollapsed, lastDays )
			else
				if i18n.mmonth then
					if is(args.month2) and is(args.month3) then
						if (args.month2 ~= args.month3) then -- "Mmm ##–##"
							month = mw.ustring.gsub(i18n.toggleRange,'$.', {
								'$m' = i18n.mmonth,
								'$s' = args.month2,
								'$e' = args.month3})
						else -- "Mmm ##""
							month = mw.ustring.gsub(i18n.toggleSingleDate,'$.', {
								'$m' = i18n.mmonth,
								'$s' = args.month2})
						end
					else --"Mmm"
						month = i18n.mmonth
					end
				end
						
				outString = mw.ustring.format( outString,
					uncollapsed, month,
					collapsed, month )
			end
		elseif mw.ustring.sub(month,1,1) == 'l' and tonumber(mw.ustring.sub(month,2)) == args.duration then
			local customtoggles = {(' mw-customtoggle-l' .. args.duration)}
			for k in pairs(i18n.m) do --list of months
				customtoggles#customtoggles + 1 = ' mw-customtoggle-' .. k .. '-l' .. args.duration
			end
			
			local lastDays = mw.ustring.format(i18n.lastDays, args.duration)
			
			outString =  .. lastDays .. '\n' ..
				 .. lastDays ..  .. newline
			
		else
			local customtoggles = ' mw-customtoggle-' .. month .. ' mw-customtoggle-' .. month .. '-l' .. args.duration
			
			outString =  .. (i18n.mmonth or month)  .. '\n' ..
				 .. (i18n.mmonth or month)  ..   .. newline
		end
	end
	
	return outString
end
function p._chart(args)
	local navbar = require('Module:Navbar')._navbar
	local barargs = {}
	local function _numwidth(p)
		local nw = mw.ustring.sub(args.numwidth or ,p,p)
		if nw == 'n' then
			return 0
		elseif nw == 't' then
			return 40
		elseif nw == 'm' then
			return 55
		elseif nw == 'w' then
			return 70
		elseif nw == 'x' then
			return 85
		elseif nw == 'd' then
			return 55
		end
		return 0
	end
	local numwidth = 120
	local right1 = numwidth - 8 -- -8 because of padding
	if args.numwidth then
		numwidth = _numwidth(1) + 10 + _numwidth(2)
		if mw.ustring.len(args.numwidth) == 4 then
			numwidth = numwidth + _numwidth(3) + _numwidth(4)
			if mw.ustring.sub(args.numwidth,3,3) == 'n' then
				numwidth = numwidth + 6
			else
				numwidth = numwidth + 10
			end
		end
		right1 = _numwidth(1) + 2 + _numwidth(2)
		if not args.right2 and mw.ustring.len(args.numwidth) == 4 then
			right1 = right1 + _numwidth(3) + _numwidth(4)
			if mw.ustring.sub(args.numwidth,3,3) == 'n' then
				numwidth = numwidth + 6
			else
				numwidth = numwidth + 10
			end
		end
	end
	local barwidth = 280
	if args.barwidth == 'thin' then
		barwidth = 120
	elseif args.barwidth == 'medium' then
		barwidth = 280
	elseif args.barwidth == 'wide' then
		barwidth = 400
	elseif args.barwidth == 'auto' then
		barwidth = 'auto'
	end
	if tonumber(barwidth) then
		barargs.width = 85 + barwidth + numwidth .. 'px'
		barargs.barwidth = barwidth .. 'px'
	else
		barargs.width = 'auto'
		barargs.barwidth = 'auto'
	end
	barargs.float = args.float and args.float or 'right'
	local location = mw.ustring.gsub(args.location, 'the ', )
	location = mw.ustring.upper(mw.ustring.sub(location,1,1)) .. mw.ustring.sub(location,2)
	local navbartitle = args.outbreak .. '/' ..
		(args.location3 and args.location3 .. ' ' or ) ..
		(args.location2 and args.location2 .. ' ' or ) ..
		location .. ' 차트'
	
	-- get duration for toggles
	local duration = 15 -- default if manual togglesbar is last 15 days
	if yesno(args.collapsible) == true and ( not is(args.togglesbar) ) then
		duration = tonumber(args.duration) or 15 -- default if auto togglesbar is last 15 days
	end
	
	local months, togglesbar, lastdate = , , nil
	if args.rows then
		barargs.bars = args.rows
		if yesno(args.collapsible) == true then
			togglesbar = is(args.togglesbar) and args.togglesbar or 
		end
	elseif is(args.data) or is(args.datapage) then
		local buildargs = {}
		
		local nooverlap = yesno(args.nooverlap)
		
		buildargs.barwidth = tonumber(barwidth) or 280
		buildargs.data = is(args.datapage) and require('Module:Medical cases chart/data')._externalData(args) or args.data
		buildargs.divisor = args.divisor
		buildargs.numwidth = args.numwidth
		buildargs.collapsible = args.collapsible
		buildargs.right1data = args.right1data or -- if no right1data and right1 title is default, use 3rd classification
				not args.right1 and 3
		buildargs.right2data = args.right2data or -- if no right2data and right2 title is deaths, use 1st classification
				(args.right2 == i18n.noOfDeaths or args.right2 == i18n.noOfDeaths2) and 1
		buildargs.changetype1 = mw.ustring.sub(args.changetype1 or (args.changetype or ),1,1) -- 1st letter
		buildargs.changetype2 = mw.ustring.sub(args.changetype2 or (args.changetype or ),1,1) -- 1st letter
		buildargs.rowheight = args.rowheight
		buildargs.duration = duration
		if is(args.togglesbar) then
			buildargs.nooverlap = false
		else
			buildargs.nooverlap = nooverlap
		end
		
		barargs.bars, monthList = p._buildBars(buildargs)
		
		local lastRow = #monthList
		if nooverlap == true then
			if #monthList  1 and i > 1 then
					months#months3 = monthListi-12 --store end of previous month
				end
				months#months+1 = monthListi --store start of this month
			end
		end
		months#months3 = monthListlastRow2 --store end of final month
		
		-- automatically generate toggles
		if yesno(args.collapsible) == true then
			if is(args.togglesbar) then
				togglesbar = args.togglesbar
			else
				local toggles = {}
				for i=1,#months do
					toggles#toggles+1 = p._monthToggleButton({month=monthsi, duration=duration, nooverlap=nooverlap})
				end
				toggles#toggles+1 = p._monthToggleButton({month={('l' .. duration)}, duration=duration, nooverlap=nooverlap})
				togglesbar = '\n' .. table.concat(toggles) .. 
			end
		end
	end
	
	local title = {}
	title1 = (args.pretitle and args.pretitle .. ' ' or ) ..
		(args.location3 and args.location3 .. ' ' or ) ..
		(args.location2 and args.location2 .. ' ' or ) ..
		args.location ..  .. i18n.casesIn ..  .. args.disease ..
		(args.posttitle and ' 현황' .. args.posttitle or ' 현황') .. '  (' ..
		navbar({1 = navbartitle, titleArg = ':' .. mw.getCurrentFrame():getParent():getTitle(), mini = 1, nodiv = 1}) ..
		')'
	title2 = p._legend0({1 = p._barColors(1), 2 = '사망자'})
	if yesno(args.recoveries) == false then
		title3 = 
	else
		title3 = '   ' .. p._legend0({1 = p._barColors(2), 2 = args.reclbl or i18n.recoveries})
	end
	title4 = '   ' .. p._legend0({1 = p._barColors(3), 2 = args.altlbl1 or i18n.activeCases})
	if args.altlbl2 then
		title5 = '   ' .. p._legend0({1 = p._barColors(4), 2 = args.altlbl2})
	else
		title5 = 
	end
	if args.altlbl3 then
		title6 = '   ' .. p._legend0({1 = p._barColors(5), 2 = args.altlbl3}) ..'\n'
	else
		title6 = '\n'
	end
	title7 = togglesbar
	
	barargs.title = table.concat(title)
	barargs.left1 =
		 .. -- 85-8 because of padding
			"" .. i18n.date .. "" ..
		
	barargs.right1 =
		 ..
			"" .. (args.right1 or i18n.noOfCases) .. "" ..
		
	if args.right2 then
		local right2 = _numwidth(3) + _numwidth(4)
		if mw.ustring.sub(args.numwidth,3,3) == 'n' then
			right2 = right2 - 2
		else
			right2 = right2 + 2
		end
		barargs.right2 =
		 ..
			"" .. args.right2 .. "" ..
		
	end
	barargs.caption = args.caption
	barargs.css = 'Template:Medical_cases_chart/styles.css'
	return barBox._box(barargs)
end
function p.chart(frame)
	local args = getArgs(frame, {
		valueFunc = function (key, value)
			if value then
				value = mw.text.trim(value)
				if ({'numwidth'=1,'barwidth'=1,'recoveries'=1,'changetype'=1})mw.ustring.gsub(key,"%A","") then
					value = mw.ustring.lower(value) --make numwidth, barwidth, recoveries, and changetype lower case
				end
				if is(value) then
					return value
				end
			end
			return nil
		end
	})
	return p._chart(args)
end
function p.barColors(frame)
	return p._barColors(tonumber(frame:getParent().args1))
end
function p.buildBars(frame)
	local bars = p._buildBars(frame.args)
	return bars
end
function p.monthToggleButton(frame)
	local args = {}
	args.month = {frame:getParent().args.month or frame:getParent().args1 or 'l15'}
	args.active = frame:getParent().args.active or 'true'
	args.duration = frame:getParent().args.duration or 15
	args.nonewline = true
	return p._monthToggleButton(args)
end
return p