Module:Sandbox/Izno/Pie chart

local p = {}
local compress_sparse_array = require('Module:TableTools').compressSparseArray

local function arg_or_default(arg, default)
	if arg and mw.text.trim(arg) ~= '' then
		return arg
	else
		return default
	end
end

local incoming_args = {
	['other-color'] = 'other_color_default()',
	style = nil,
	thumb = nil,
	labeln = nil,
	valuen = nil,
	colorn = 'get_graph_color(n)',
	caption = nil,
	other = nil,
	footer = nil
}

local graph_colors = {
	'#1F78B4',
	'#33A02C',
	'#FF7F00',
	'#6A3D9A',
	'#B15928',
	'#A6CEE3',
	'#B2DF8A',
	'#FB9A99',
	'#FDBF6F',
	'#CAB2D6',
	'#FFFF99',
	'#FEEBE2',
	'#A9A9A9'
}
	
local function get_graph_color(nth_item)
	return graph_colors[math.max(math.min(nth_item, #graph_colors), 1)]
end

local function get_css_for_slices(args)
	local slices = {}
	local degree_ratio = 360/100

	for k, v in pairs(args) do
		if k:match('value%d+') then
			local number = k:find('(%d+)')
			slices[number] = { value = tonumber(v) * degree_ratio }
		end
	end
	
	-- second loop because we need to guarantee that we've found all the potential slices
	-- before attempting to add their labels and colors
	for k, v in pairs(args) do
		if k:match('label%d+') then
			local number = k:find('(%d)')
			if slices[number] then -- if we don't have a value, then no label set
				slices[number]['label'] = v
			end
		end
		if k:match('color%d+') then
			local number = k:find('(%d)')
			if slices[number] then -- if we don't have a value, then no color set
				slices[number]['color'] = v
			end
		end
	end
	
	compress_sparse_array(slices)
	local conical_css_for_slices = {}
	local accumulated_value = 0
	
	for i, slice in ipairs(slices) do
		local value = slice.value
		local color = slice.color or get_graph_color(i)
		local next_accumulated_value = accumulated_value + value
		
		if i == 1 then
			-- we only need the end degree for the first
			table.insert(conical_css_for_slices, color .. ' ' .. value .. 'deg,')
		elseif i > 1 and i < #slices then
			-- need both start and end for the first, start is the previous end
			table.insert(conical_css_for_slices, color .. ' ' .. accumulated_value .. 'deg ' .. next_accumulated_value .. 'deg,')
		elseif i == #slices then
			-- we only need the start degree for the last
			table.insert(conical_css_for_slices, color .. ' ' .. accumulated_value .. 'deg')
		end
		
		accumulated_value = next_accumulated_value
	end
	return 'background: conic-gradient(' .. table.concat(conical_css_for_slices) .. ')'
end

function p._main(args)
	
	local root = mw.html.create('div')
	root:addClass('pie-chart thumb')
		:cssText(arg_or_default(args.style, nil))
	
	local thumb = arg_or_default(args.thumb, nil)
	local thumb_class = 'tright'
	if thumb and (thumb == 'center' or thumb == 'none') then
		thumb_class = 'tnone'
	elseif thumb and thumb == 'left' then
		thumb_class = 'tleft'
	end
	root:addClass(thumb_class)
	
	local radius = tonumber(arg_or_default(args.radius, 100))
	local diameter = radius * 2
	root:tag('div')
		:addClass('pie-chart-inner thumbinner')
		:css('width', (diameter + 2) .. 'px')
	
	local chart = mw.html.create('div')
	chart:addClass('pie-chart-chart mw-no-invert')
	chart:css('border-radius', '50%') -- can be in pie chart/styles.css if we have one
	chart:css('width', diameter .. 'px')
	chart:css('height', diameter .. 'px')
	
	local conic_css = get_css_for_slices(args)
	chart:cssText(conic_css)

	if thumb and thumb == 'center' then
		local root_container = mw.html.create('div')
		root_container:addClass('pie-chart-container center')
			:node(root)
		return root_container
	end

	return root
	
end

function p.main(frame)
	return p._main(frame:getParent().args)
end

return p

Content Disclaimer

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

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