Модуль:Песочница/Nikolai/Test

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация
local p = {}

function round(x, precision)
    x = math.floor(x * math.pow(10, precision) + 0.5) / math.pow(10, precision)
    if precision == 0 then
        return x
    end
    x = mw.ustring.gsub(x, "%.", ",")
    if precision == 1 and string.find(x, ",") == nil then
        x = x..",0"
    end
    return x
end

function createSlice(sbeg, send, color, radius, art)
    str = ''
    rad = sbeg * math.pi / 50; -- convert % in radian
	
    if art == 'круг' or art == 'кольцо' then
        if sbeg <= 12 then
            border = radius * math.tan(rad) --border-left
            str = [[<div style="position:absolute; right:0; top:0; width:]]..(radius-border)..[[px; height:0; background-color:transparent; border-style:solid; border-width:0px 0px ]]..(2*radius)..[[px ]]..(2*border)..[[px; border-color:transparent transparent ]]..color..[[ transparent;"></div>]]
            if send > 50 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..(2*radius)..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 25 then
            border = radius * math.tan(math.pi/2 - rad) --border-top
            str = [[<div style="position:absolute; left:0; bottom:0; width:0; height:0; background-color:transparent; border-style:solid; border-width:]]..border..[[px ]]..radius..[[px ]]..radius..[[px ]]..radius..[[px; border-color:transparent ]]..color..[[ ]]..color..[[ ]]..color..[[;"></div>]]
            if send > (100 - sbeg) then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 37 then
            border = radius * math.tan(rad - math.pi/2) --border-top
            str = [[<div style="position:absolute; left:0; bottom:0; width:0; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:]]..(2*border)..[[px 0px 0px ]]..(2*radius)..[[px; border-color:transparent transparent transparent ]]..color..[[;"></div>]]
            if send > (sbeg + 50) then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 50 then
            border = radius * math.tan(math.pi - rad) --border-right
            str = [[<div style="position:absolute; left:0; top:0; width:0; height:0; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px ]]..radius..[[px ]]..radius..[[px; border-color:transparent transparent ]]..color..[[ ]]..color..[[;"></div>]]
            if send > 87 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 62 then
            border = radius * math.tan(rad - math.pi) --border-right
            str = [[<div style="position:absolute; left:0; bottom:0; width:]]..(radius-border)..[[px; height:0; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px 0px 0px; border-color:]]..color..[[ transparent transparent transparent;"></div>]]
            if send > 75 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 75 then
            border = radius * math.tan(math.pi*1.5 - rad) --border-bottom
            str = [[<div style="position:absolute; right:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px 0px ]]..border..[[px ]]..radius..[[px; border-color:transparent transparent transparent ]]..color..[["></div>]]	
        elseif sbeg <= 87 then
            border = radius * math.tan(rad - math.pi*1.5) --border-bottom
            str = [[<div style="position:absolute; left:0; top:0; width:0; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..radius..[[px ]]..border..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]]
        else
            border = radius * math.tan(math.pi*2 - rad) --border-right
            str = [[<div style="position:absolute; left:0; top:0; width:]]..(radius-border)..[[px; height:0; background-color:transparent; border-style:solid; border-width:0px ]]..border..[[px ]]..radius..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]]
        end    	
    else
    	local x = 0;    x = math.cos(rad)
        local y = 0;    y = math.sin(rad)
	
        if x >= 0 then x = math.floor(x * 10 + 0.5) / 10
        else           x = math.floor(math.abs(x) * 10 + 0.5) / (-10)
        end

        if y >= 0 then y = math.floor(y * 10 + 0.5) / 10
        else           y = math.floor(math.abs(y) * 10 + 0.5) / (-10)
        end	
        if sbeg <= 12 then
            border = radius * math.tan(rad) --border-left
            str =      [[<div style="position:absolute; right: ]]..x..[[px; top:]]..(-1-y)..[[px; width:]]..(radius-border)..[[px;height:1px;background-color:transparent; border-style:solid; border-width:0px 0px ]]..(2*radius)..[[px ]]..(2*border)..[[px; border-color:transparent transparent ]]..'#FFF'..[[ transparent;"></div>]]
            str = str..[[<div style="position:absolute; right:-]]..x..[[px; top:]]..(-1+y)..[[px; width:]]..(radius-border)..[[px;height:1px;background-color:transparent; border-style:solid; border-width:0px 0px ]]..(2*radius)..[[px ]]..(2*border)..[[px; border-color:transparent transparent ]]..color..[[ transparent;"></div>]]
            if send > 50 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..(2*radius)..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 25 then
            border = radius * math.tan(math.pi/2 - rad) --border-top
            str =      [[<div style="position:absolute; left:-]]..x..[[px; bottom: ]]..y..[[px; width:]]..radius..[[px;height:]]..radius..[[px;background-color:transparent; border-style:solid; border-width:]]..border..'px '..radius..[[px 0px 0px; border-color:transparent ]]..'#FFF'..[[ transparent transparent;"></div>]]
            str = str..[[<div style="position:absolute; left: ]]..x..[[px; bottom:-]]..y..[[px; width:]]..radius..[[px;height:]]..radius..[[px;background-color:transparent; border-style:solid; border-width:]]..border..'px '..radius..[[px 0px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]]
            if send > 50 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..(2*radius)..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 37 then
            border = radius * math.tan(rad - math.pi/2)
            str =      [[<div style="position:absolute; left:]]..(-1*x)..[[px; bottom: ]]..y..[[px; width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:]]..(2*border)..[[px 0px 0px ]]..(2*radius)..[[px; border-color:transparent transparent transparent ]]..'#FFF'..[[;"></div>]]
            str = str..[[<div style="position:absolute; left:     ]]..x..[[px; bottom:-]]..y..[[px; width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:]]..(2*border)..[[px 0px 0px ]]..(2*radius)..[[px; border-color:transparent transparent transparent ]]..color..[[;"></div>]]
            if send > 75 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 50 then
            border = radius * math.tan(math.pi - rad) --border-right
            str =      [[<div style="position:absolute; left:]]..(-1*x)..[[px; top:-]]..y..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..border..'px '..radius..[[px 0px; border-color:transparent transparent ]]..'#FFF'..[[ transparent;"></div>]]
            str = str..[[<div style="position:absolute; left:     ]]..x..[[px; top: ]]..y..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..border..'px '..radius..[[px 0px; border-color:transparent transparent ]]..color..[[ transparent;"></div>]]
            if send > 75 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 62 then
            border = radius * math.tan(rad - math.pi) --border-right
            str =      [[<div style="position:absolute; left:]]..(-1*x)..[[px; bottom:]]..(-1+y)..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px 0px 0px; border-color:]]..'#FFF'..[[ transparent transparent transparent;"></div>]]
            str = str..[[<div style="position:absolute; left:     ]]..x..[[px; bottom:]]..(-1-y)..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px 0px 0px; border-color:]]..color..[[ transparent transparent transparent;"></div>]]
            if send > 75 then
                str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]]
            end
        elseif sbeg <= 75 then
            border = radius * math.tan(math.pi*1.5 - rad) --border-bottom
            str =      [[<div style="position:absolute; right:]]..x..[[px; top:]]..(-1*y)..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px 0px ]]..border..[[px ]]..radius..[[px; border-color:transparent transparent transparent ]]..'#FFF'..[["></div>]]	
            str = str..[[<div style="position:absolute; right:]]..(-1*x)..[[px; top:]]..y..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px 0px ]]..border..[[px ]]..radius..[[px; border-color:transparent transparent transparent ]]..color..[["></div>]]	
        elseif sbeg <= 87 then
            border = radius * math.tan(rad - math.pi*1.5) --
            str =      [[<div style="position:absolute; left:]]..(-1-x)..[[px; top:]]..(-1*y)..[[px;  width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..radius..[[px ]]..border..[[px 0px; border-color:transparent ]]..'#FFF'..[[ transparent transparent;"></div>]]
            str = str..[[<div style="position:absolute; left:]]..(-1+x)..[[px; top:]]..y..[[px;       width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..radius..[[px ]]..border..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]]
        else
            border = radius * math.tan(math.pi*2 - rad)
            str =      [[<div style="position:absolute; left:-]]..x..[[px; top:]]..(-1+(-1*y))..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:0px ]]..(border)..[[px ]]..radius..[[px 0px; border-color:transparent ]]..'#FFF'..[[ transparent transparent;"></div>]]
            str = str..[[<div style="position:absolute; left: ]]..x..[[px; top:]]..(-1+y)..[[px;      width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:0px ]]..(border)..[[px ]]..radius..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]]
        end
    end
    return str
end

function p.start(frame)
    local Dsize = 100 --size of diagram ( 10 - 500 )
    local Dart = '' --art of diagram ( circle / ring )
    local Dpos = '' --position of diagram ( left / right /no )
    local Dleg = '' --view & position of legends ( no / bottom / right / coordin )
    local Dpct = '' --percent (prozent) ( yes /no )
    local Dprc = 0  --precision of rounding ( 0 / 1 / 2 )
    local Dtit = '' --title of diagram
    local Dbrd = '' --border of diagram
    local i = 0   --counter
    local num = 0 --number
    local err = 0 --errors
    local sum = 0 --sum
    local color = {"#DC3912", "#3366CC", "#FF9900", "#109618", "#990099", "#0099C6", "#DD4477", "#66AA00", "#B82E2E", "#316395",
        "#994499", "#22AA99", "#AAAA11", "#6633CC", "#E67300", "#8B0707", "#651067", "#329262", "#5574A6", "#3B3EAC"}
		
    for k, v in pairs(frame.args) do
        if i > 7 and (i - 5) % 3 == 0 then
            if not tonumber(frame.args[i]) then err = 1;
            else num = num + 1;  sum = sum + tonumber(frame.args[i]);
            end
        end
        i = i + 1
    end

    if i < 10 or i > 67 or (i - 7) % 3 ~= 0 then
        err = 1
    end
	
    if err == 0 then
        Dsize = tonumber(frame.args[1]);       if not Dsize or Dsize < 30 or Dsize > 500 then Dsize = 100 end
        Dart = mw.text.trim(frame.args[2]);    if Dart ~= 'круг' and Dart ~= 'круг+' and Dart ~= 'круг-' and Dart ~= 'кольцо' and Dart ~= 'кольцо+' and Dart ~= 'кольцо-' then Dart = 'круг'; end
        Dpos = mw.text.trim(frame.args[3]);    if Dpos ~= 'справа' and Dpos ~= 'слева' and Dpos ~= 'нет' then Dpos = 'нет'; end
        Dleg = mw.text.trim(frame.args[4]);    if Dleg ~= 'справа' and Dleg ~= 'внизу' and Dleg ~= 'нет' and Dleg ~= 'ху' then Dleg = 'нет'; end
        Dpct = mw.text.trim(frame.args[5]);
        Dprc = mw.text.trim(frame.args[6]);
        Dtit = mw.text.trim(frame.args[7]);
        
        Dsize = math.floor(Dsize/2)*2;
        if Dart == 'круг-' then Dart = 'круг'; Dbrd = 'border:0'; end
        if Dart == 'кольцо-' then Dart = 'кольцо'; Dbrd = 'border:0'; end
        if Dleg == 'ху' then
            Dpct = tonumber(Dpct)    if not Dpct or Dpct > 500 then Dpct = 0 end
            Dprc = tonumber(Dprc)    if not Dprc or Dprc > 500 then Dprc = 0 end
        end
        if Dleg ~= 'ху' then
            if Dpct ~= 'нет' and Dpct ~= 'да' then Dpct = 'нет'; end
            Dprc = tonumber(Dprc)   if Dprc ~= 0 and Dprc ~= 1 and Dprc ~= 2 then Dprc = 0; end
        end
    end
	
    local n = 1
    local Svalue = 0
    local Spct = 0 --percent (prozent) of slice
    local Sbegin = 0 -- begin of slice in %
    local Send = 0 -- end of slice in %
    local Sdescr = ''
    local Scolor = ''
    local htmlCaption = ''
    local htmlLegendCont = ''
    local htmlLegendCont_= ''
    local htmlLegends = ''
    local BorderLeft = ''  if Dleg == 'ху' then BorderLeft = [[border-left:]]..Dpct..[[px solid #FFF;]] end
    local BorderRight= ''  if Dleg == 'ху' then BorderRight = [[border-right:]]..Dprc..[[px solid #FFF;]] end
    local floatL = ''
    local marginL = ''
    local bre = ''
    local slice = ''
    local percentage = ''
    
	local html = ''
	local html1 = ''
	if Dpos == 'слева'  then html1 = [[<div class="thumb tleft">]] end
	if Dpos == 'справа' then html1 = [[<div class="thumb tright">]] end
	if Dpos == 'нет'    then html1 = [[<div class="thumb" style="display:inline-block">]] end

	local html2 = [[<div class="thumbinner" style="position:relative; background-color:#FFF; ]]..Dbrd..[[;">]]
	local html2e= [[</div>]];
	local html1e= [[</div>]];
	
    if err == 0 then
        Scolor = mw.text.trim(frame.args[10])
        if Scolor == '' then
            Scolor = color[1]
        end
        if Dleg == 'справа' then
            floatL = [[float:left;]]
            marginL = [[margin-left:15px;]]
            bre = [[<br />]]
        end        
        if Dtit ~= '' then htmlCaption = [[<div class="thumbcaption" style="text-align:center; font-size:100%; font-weight:bold; padding:9px;">]]..Dtit..[[</div>]] end
        htmlLegendCont = [[<div class="thumbcaption" style="margin:5px; font-size:100%; line-height:1.5em;]]..marginL..floatL..[[">]] --begin of legends
        htmlLegendCont_= '</div>'  -- end of legends
        slice = [[<div style="position:relative; width:]]..Dsize..[[px; height:]]..Dsize..[[px; background-color:]]..Scolor..[[; overflow:hidden; margin:5px;]]..floatL..BorderLeft..BorderRight..[[">]] --begin of slides
        
		while n <= num do
			Svalue = tonumber(frame.args[3*n+5])
			Sdescr = mw.text.trim(frame.args[3*n+6])
			Scolor = mw.text.trim(frame.args[3*n+7])
			if Scolor == '' then
				Scolor = color[n]
			end	
			Spct = 100 * Svalue / sum
			if n > 1 then Sbegin = Send end
			Send = Sbegin + Spct
			if n > 1 then
				slice = slice.. createSlice(Sbegin, Send, Scolor, Dsize/2, Dart) --function
			end
			if Dpct == 'да' then
				percentage = round(Spct, Dprc)..'% '
			end
			if Dleg == 'справа' or Dleg == 'внизу' then
				htmlLegends = htmlLegends..[[<span style="box-shadow:2px -1px 3px 0px #C0C0C0; color:]]..Scolor..[[; background-color:]]..Scolor..[[;">&#160;&#160;&#160;&#160;&#160;</span> &#160;]]..percentage..Sdescr..bre
			end
			if Dleg == 'ху' then
				local legv, legx, legy, legc = unpack(mw.text.split(Sdescr, '%s*:%s*'))
				if legc == nil then legc = '#000' end
				if not tonumber(legx) or not tonumber(legy) then legx = 2; legy = n*10; legv = 'ошибка с'..n; legc = '#F00'; end
				htmlLegends = htmlLegends..[[<div style="position:absolute; left:]]..legx..[[px; top:]]..legy..[[px; color:]]..legc..[[; font-size:100%; line-height:1.4em;">]]..legv..[[</div>]]
			end
			n = n + 1
		end
		
		if Dart == 'круг+' or Dart == 'кольцо+' then
			slice = slice..[[<div style="position:absolute; left:]]..(Dsize/2-1)..[[px; top:0px; width:2px; height:]]..(Dsize/2)..[[px; background-color:#F9F9F9;"></div>]]
		end
		slice = slice..[[<div style="position:absolute;left:0;top:0">]]..'[[Файл:Circle200.svg|'..Dsize..'px|link=]]</div>'  -- end of slices
		--slice = slice..[[<div style="position:absolute; left:-]]..(Dsize/4)..[[px; top:-]]..(Dsize/4)..[[px; width:]]..Dsize..[[px; height:]]..Dsize..[[px; border-radius:100%; border:]]..(Dsize/4)..[[px solid #F9F9F9;"></div>]] -- circle
		if Dart == 'кольцо' or Dart == 'кольцо+' then
			slice = slice..[[<div style="position:absolute;left:0;top:0">]]..'[[Файл:Circle200c.svg|'..Dsize..'px|link=]]</div>' --ring
			--slice = slice..[[<div style="position:absolute; left:]]..(Dsize/4)..[[px; top:]]..(Dsize/4)..[[px; width:]]..(Dsize/2)..[[px; height:]]..(Dsize/2)..[[px; background:#F9F9F9; border-radius:100%; border:0;"></div>]] --ring
		end
		slice = slice..'</div>' --end of slices
	end

    if Dleg == 'нет' then htmlLegendCont = '';  htmlLegendCont_= ''; htmlLegends = ''; end
    if Dleg == 'ху' then htmlLegendCont = ''; htmlLegendCont_= ''; end
	
    if err == 0 then
        html = html1..html2..htmlCaption..slice.. htmlLegendCont..htmlLegends.. htmlLegendCont_..html2e..html1e;
    end
    return html
end

return p