if not modules then modules = { } end modules ['t-statistical-charts'] = { version = "0.31", comment = "Statistical charts", author = "Tamara Kocurová, Adriana Kašparová, Tomáš Hála", copyright = "Tamara Kocurová, Adriana Kašparová, Tomáš Hála", email = "kocurova.tamara@gmail.com, adka.kaspar@seznam.cz, thala@mendelu.cz", license = "GNU General Public License" } documentdata = documentdata or {} documentdata.statcharts = documentdata.statcharts or {} documentdata.statcharts.data = documentdata.statcharts.data or {} thirddata = thirddata or {} thirddata.statcharts = thirddata.statcharts or {} local m = thirddata.statcharts ctx = context local percentsign = "\\%" ------------------------------ thirddata.readdata = require "t-readdata" local r = thirddata.readdata ------------------------------ -------------------------------------------------------------------------------- AUXILLARY TOOLS function set_hash_values (from, to) local l = to or {} for k,v in pairs(from) do if v ~= "" then l[k]=v end end return l end -------------------------------------------------------------------------------- MUTUAL SUBPROGRAMS function m.dotslabels(main, val, dec, dec2, dec3, i) local lab=val local pos=0 local n=m[thirddata.statcharts.charttype].settings if thirddata.statcharts.charttype == "radar" then local d=documentdata.statcharts local cols=#d.data[1] pos=math.floor(360/cols*i/45) end if thirddata.statcharts.charttype ~= "radar" then if thirddata.statcharts.subtype == "stacked100" then lab=tostring(val/n.ylength*100) else lab=tostring(val/n.yscale) end end if n.decimalzero == "yes" then if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals) else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000) elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100) elseif dec == 1 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end else if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end else if lab*1000%10 ~= 0 then lab=math.round(lab*1000)/1000 elseif lab*100%10 ~= 0 then lab=math.round(lab*100)/100 elseif lab*10%10 ~= 0 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end end if thirddata.statcharts.charttype == "radar" then ctx("label."..thirddata.statcharts.MPpositions[pos].." (btex \\dotslabels{"..lab.."} etex, ((0,"..main.."));") else ctx("label.top (btex \\dotslabels {"..lab.."} etex, ("..main.."u,"..val.."u));") end end function m.yaxislabels() local lab=0 local n=m[thirddata.statcharts.charttype].settings local ycount=math.floor(n.ylength) if n.decimalzero == "yes" then local dec, dec2, dec3=0, 0, 0 for j=1, ycount do lab=j/n.yscale if lab*10%10 ~= 0 then dec=1 if lab*100%10 ~= 0 then dec2=1 end if lab*1000%10 ~= 0 then dec3=1 break end end end for i=1, ycount do lab=i/n.yscale if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals) else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000) elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100) elseif dec == 1 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end if tonumber(n.ygridlinesdensity) < 1 then if i*n.ygridlinesdensity%1 == 0 then ctx("label.lft (btex \\yaxislabels {"..lab.."} etex, (0,"..i.."u));") end else ctx("label.lft (btex \\yaxislabels {"..lab.."} etex, (0,"..i.."u));") end end else for i=1, ycount do lab=i/n.yscale if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end else if lab*1000%10 ~= 0 then lab=math.round(lab*1000)/1000 elseif lab*100%10 ~= 0 then lab=math.round(lab*100)/100 elseif lab*10%10 ~= 0 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end if tonumber(n.ygridlinesdensity) < 1 then if i*n.ygridlinesdensity%1 == 0 then ctx("label.lft (btex \\yaxislabels {"..lab.."} etex, (0,"..i.."u));") end else ctx("label.lft (btex \\yaxislabels {"..lab.."} etex, (0,"..i.."u));") end end end end m.stacked100={} function m.stacked100.yaxislabels() local lab=0 local n=m[thirddata.statcharts.charttype].settings if n.decimalzero == "yes" then local dec, dec2, dec3=0, 0, 0 for j=1, n.ylabelscount do lab=j*100/n.ylabelscount if lab*10%10 ~= 0 then dec=1 if lab*100%10 ~= 0 then dec2=1 end if lab*1000%10 ~= 0 then dec3=1 break end end end for i=1, n.ylabelscount do lab=i*100/n.ylabelscount if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals)..percentsign else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000)..percentsign elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100)..percentsign elseif dec == 1 then lab=tostring(math.round(lab*10)/10)..percentsign else lab=tostring(math.round(lab))..percentsign end end local y=n.ylength/n.ylabelscount*i ctx("label.lft (btex \\yaxislabels{"..lab.."} etex, (0,"..y.."u));") end else for i=1, n.ylabelscount do lab=i*100/n.ylabelscount if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end lab=lab..percentsign else if lab*1000%10 ~= 0 then lab=string.format("%0.3f", math.round(lab*1000)/1000)..percentsign elseif lab*100%10 ~= 0 then lab=string.format("%0.2f", math.round(lab*100)/100)..percentsign elseif lab*10%10 ~= 0 then lab=tostring(math.round(lab*10)/10)..percentsign else lab=tostring(math.round(lab))..percentsign end end local y=n.ylength/n.ylabelscount*i ctx("label.lft (btex \\yaxislabels{"..lab.."} etex, (0,"..y.."u));") end end end function m.xgridlines(main,n) return m.gridlines(main,n,"x") end function m.ygridlines(main,n) return m.gridlines(main,n,"y") end function m.gridlines(main,n,xy) local x1,y1,x2,y2=0,main,n.xlength,main if xy == "x" then x1,y1,x2,y2=main,0,main,n.ylength end return "pickup pencircle scaled "..n.gridlinewidth.."pt; draw("..x1.."u,"..y1.."u)--("..x2.."u,"..y2.."u) "..n.gridline.." withcolor \\MPcolor{"..n.gridcolor.."};" end function m.pickcolor(i, color, palette) local finalcolor="" if not color then local ind=i%#m.palette[palette] if ind == 0 then ind=#m.palette[palette] end finalcolor=m.palette[palette][ind] else finalcolor=color end return finalcolor end function m.decidecolor(i, color, palette) local finalcolor="" if not palette then finalcolor=color else local ind=i%#m.palette[palette] if ind == 0 then ind=#m.palette[palette] end finalcolor=m.palette[palette][ind] end return finalcolor end function m.decim(decimals) local decim=0 if decimals%1 == 0 then decim=0 elseif (decimals*10)%1 == 0 then decim=1 elseif (decimals*100)%1 == 0 then decim=2 elseif (decimals*1000)%1 == 0 then decim=3 elseif (decimals*10000)%1 == 0 then decim=4 else decim=5 end return decim end function m.definepalette(name, colors) m.palette = m.palette or {} m.palette[name] = utilities.parsers.settings_to_array(colors) end function m.axesunits() local n=m[thirddata.statcharts.charttype].settings ctx("label.bot (btex \\xaxisunit{"..n.xunit.."} etex, ("..(n.xlength/2).."u, 0));") ctx("label.lft (btex \\yaxisunit{"..n.yunit.."} etex, (0, "..(n.ylength/2).."u));") end -------------------------------------------------------------------------------- GENERAL SETTINGS m.root={} m.root.processvals=function () return { unit="cm", xlength=0, ylength=0, xshift=0, yshift=0, xwidth=0.5, ywidth=0.5, xscale=1, yscale=1, xaxislabels="yes", yaxislabels="yes", axesunits="no", xunit="", yunit="", xaxislabelsnoval="yes", yaxislabelsnoval="yes", xlabelscount=5, ylabelscount=5, distance=1, left=1, bottom=1, grid="on", gridcolor="middlegray", gridline="dotted", gridlinewidth=1, xgridlines="yes", ygridlines="yes", xgridlinesdensity=1, ygridlinesdensity=1, xgridlinesnoval="yes", ygridlinesnoval="yes", xgridlinesleft="yes", line="yes", linecolor="black", linepalette=nil, linewidth=1, dots="yes", dotscolor="black", dotspalette=nil, dotswidth=5, dotslabels="no", contour="yes", contourcolor="black", contourpalette=nil, contourwidth=0.5, decimalzero="no", decimals=0.1, } end m.root.settings=m.root.processvals() thirddata.statcharts.MPpositions = {"top", "urt", "rt", "lrt", "bot", "llft", "lft", "ulft"} -------------------------------------------------------------------------------- AREA m.area={} m.area.basic={} m.area.stacked={} m.area.stacked100={} function m.area.default() return { fillcolor="gray", fillpalette=nil, filltransparency=0.7, } end function m.area.processvals(keyvals, keyvalsdata) m.area.settings=set_hash_values(m.root.settings) m.area.settings=set_hash_values(m.area.default(), m.area.settings) m.area.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.area.settings) if m.area.settings.gridline == "dashed" then m.area.settings.gridline="dashed evenly" elseif m.area.settings.gridline == "full" then m.area.settings.gridline="" else m.area.settings.gridline="dashed withdots" end documentdata.statcharts=r.readdata(keyvalsdata) end function m.area.all() local n=m.area.settings if not m.subtype or m.subtype == "" then m.subtype="basic" end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.area[m.subtype].changeaxeslength()) if n.grid == "on" then ctx(m.area.grid()) end m.area[thirddata.statcharts.subtype].main() ctx(m.area.axes()) if n.dots == "yes" then ctx(m.area[thirddata.statcharts.subtype].drawdots()) end if n.xaxislabels == "yes" then ctx(m.area.xaxislabels()) end if n.yaxislabels == "yes" then if thirddata.statcharts.subtype == "stacked100" then ctx(m[thirddata.statcharts.subtype].yaxislabels()) else ctx(m.yaxislabels()) end end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.area.basic.main() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] for i=1, rows do local line="l:=" local s="p:=" -- local main for j=1, cols do main=((j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale s=m.area.path(main, val, s) if j < cols then local nextval=d.data[i][j+1]*n.yscale line=m.area.line(main, val, nextval, line) if j < cols-1 then line=line.."--" end end end s=s.."("..main.."u,0)--(0,0)--cycle;" line=line..";" ctx("path p, l;"..s..line) local finalcolor=m.decidecolor(i, n.fillcolor, n.fillpalette) ctx("fill p withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.filltransparency..");") if n.line == "yes" then local finalcolor=m.decidecolor(i, n.linecolor, n.linepalette) ctx("pickup pencircle scaled "..n.linewidth.." pt; draw l withcolor \\MPcolor{"..finalcolor.."};") end end end function m.area.stacked.main() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] for i=rows, 1, -1 do local line="l:=" local s="p:=" -- local main for j=1, cols do local val, nextval=0, 0 -- local main=((j-1)*n.distance)*n.xscale for k=1, i do val=val+d.data[k][j]*n.yscale end s=m.area.path(main, val, s) if j < cols then for k=1, i do nextval=nextval+d.data[k][j+1]*n.yscale end line=m.area.line(main, val, nextval, line) if j < cols-1 then line=line.."--" end end end if i ~= 1 then for j=cols, 1, -1 do local val=0 local main=((j-1)*n.distance)*n.xscale for k=1, i-1 do val=val+d.data[k][j]*n.yscale end s=m.area.path(main, val, s) end s=s.."cycle;" else s=s.."("..main.."u,0)--(0,0)--cycle;" end line=line..";" ctx("path p, l;"..s..line) local finalcolor=m.decidecolor(i, n.fillcolor, n.fillpalette) ctx("fill p withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.filltransparency..");") if n.line == "yes" then local finalcolor=m.decidecolor(i, n.linecolor, n.linepalette) ctx("pickup pencircle scaled "..n.linewidth.." pt; draw l withcolor \\MPcolor{"..finalcolor.."};") end end end function m.area.stacked100.main() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] for i=rows, 1, -1 do local line="l:=" local s="p:=" -- local main for j=1, cols do local val, nextval, totalval, totalnextval=0, 0, 0, 0 for k=1, rows do totalval=totalval+d.data[k][j] if j < cols then totalnextval=totalnextval+d.data[k][j+1] end end -- local main=((j-1)*n.distance)*n.xscale for l=1, i do val=val+d.data[l][j]/totalval*n.ylength end s=m.area.path(main, val, s) if j < cols then for l=1, i do nextval=nextval+d.data[l][j+1]/totalnextval*n.ylength end line=m.area.line(main, val, nextval, line) if j < cols-1 then line=line.."--" end end end if i ~= 1 then for j=cols, 1, -1 do local val, totalval=0, 0 for k=1, rows do totalval=totalval+d.data[k][j] end local main=((j-1)*n.distance)*n.xscale for l=1, i-1 do val=val+d.data[l][j]/totalval*n.ylength end s=m.area.path(main, val, s) end s=s.."cycle;" else s=s.."("..main.."u,0)--(0,0)--cycle;" end line=line..";" ctx("path p, l;"..s..line) local finalcolor=m.decidecolor(i, n.fillcolor, n.fillpalette) ctx("fill p withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.filltransparency..");") if n.line == "yes" then local finalcolor=m.decidecolor(i, n.linecolor, n.linepalette) ctx("pickup pencircle scaled "..n.linewidth.." pt; draw l withcolor \\MPcolor{"..finalcolor.."};") end end end function m.area.basic.drawdots() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.area.decimals() for i=1, rows do for j=1, cols do local transp="no" local main=((j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale for k=i, rows do if d.data[i][j] < d.data[k][j] then transp="yes" end end if n.dots == "yes" then ctx(m.area.dots(i, main, val, transp)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end function m.area.stacked.drawdots() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.area.decimals() local transp="no" for i=1, rows do for j=1, cols do local val=0 local main=((j-1)*n.distance)*n.xscale for k=1, i do val=val+d.data[k][j]*n.yscale end for k=i, rows do if d.data[i][j] < d.data[k][j] then dots="no" end end ctx(m.area.dots(i, main, val, transp)) if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end function m.area.stacked100.drawdots() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.area.decimals() local transp="no" for i=1, rows do for j=1, cols do local val, totalval=0, 0 for k=1, rows do totalval=totalval+d.data[k][j] end for l=1, i do val=val+d.data[l][j]/totalval*n.ylength end local main=((j-1)*n.distance)*n.xscale ctx(m.area.dots(i, main, val, transp)) if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end function m.area.basic.changeaxeslength() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for i=1, rows do for j=1, cols do if d.data[i][j]*n.yscale > minylength then minylength=d.data[i][j]*n.yscale end end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength end minxlength=(cols-1)*n.distance*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength end thirddata.statcharts.minxlength=minxlength end function m.area.stacked.changeaxeslength() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for j=1, cols do local total=0 for i=1, rows do total=total+d.data[i][j]*n.yscale end if total > minylength then minylength=total end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength end minxlength=(cols-1)*n.distance*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength end thirddata.statcharts.minxlength=minxlength end function m.area.stacked100.changeaxeslength() local d,n=documentdata.statcharts,m.area.settings local cols=#d.data[1] local minxlength=0 if tonumber(n.ylength) < 3 then n.ylength=3 end minxlength=(cols-1)*n.distance*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength end thirddata.statcharts.minxlength=minxlength end function m.area.line(main, val, next, line) local d,n=documentdata.statcharts,m.area.settings line=line.."("..main.."u,"..val.."u)--("..main+n.distance*n.xscale.."u,"..next.."u)" return line end function m.area.path(main, val, s) s=s.."("..main.."u,"..val.."u)--" return s end function m.area.dots(i, main, val, transp) local n=m.area.settings local finalcolor=m.decidecolor(i, n.dotscolor, n.dotspalette) local str="pickup pencircle scaled "..n.dotswidth.."pt; drawdot ("..main.."u,"..val.."u) withcolor \\MPcolor{"..finalcolor.."}" if transp=="yes" then return str.." withtransparency (1,0.4);" else return str..";" end end function m.area.decimals() local d,n=documentdata.statcharts,m.area.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=0, 0, 0 local val, totalval=0, 0 if n.dotslabels == "yes" and n.decimalzero == "yes" then for i=1, rows do for j=1, cols do if thirddata.statcharts.subtype == "basic" then val=d.data[i][j] elseif thirddata.statcharts.subtype == "stacked" then for k=1, i do val=val+d.data[k][j] end elseif thirddata.statcharts.subtype == "stacked100" then for k=1, rows do totalval=totalval+d.data[k][j] end for l=1, i do val=val+d.data[l][j]/totalval*n.ylength end end if val*10%10 ~= 0 then dec=1 if val*100%10 ~= 0 then dec2=1 end if val*1000%10 ~= 0 then dec3=1 break end end end end end return dec, dec2, dec3 end function m.area.axes() local n=m.area.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.area.xaxislabels() local d,n=documentdata.statcharts,m.area.settings local cols=#d.data[1] local lab, count=0, 0 if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength then count=math.round((n.xlength)/(n.distance*n.xscale))+1 else count=cols end for i=1, count do if #d.xlabels == 1 and d.xlabels[1] == "" then lab=i else if d.xlabels[i] then lab=d.xlabels[i] else lab="" end end local x=((i-1)*n.distance)*n.xscale if x <= tonumber(n.xlength) then if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end end function m.area.grid() local d,n=documentdata.statcharts,m.area.settings local cols=#d.data[1] local count=0 if n.xgridlines == "yes" then if n.xgridlinesnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength then count=math.round((n.xlength)/(n.distance*n.xscale)*n.xgridlinesdensity)+1 else count=math.round(cols*n.xgridlinesdensity) if tonumber(n.xgridlinesdensity) > 1 then count=count-(n.xgridlinesdensity-1) end end for i=1, count do -- local main if tonumber(n.xgridlinesdensity) > 1 then main=((i-1)*n.distance/n.xgridlinesdensity)*n.xscale else local iter=i/n.xgridlinesdensity main=((iter-1)*n.distance)*n.xscale end if main > 0 and main <= tonumber(n.xlength) then ctx(m.xgridlines(main, n)) end end end if n.ygridlines == "yes" then if thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "stacked" then local xcount=math.floor(n.ylength)*n.ygridlinesdensity for i=1, xcount do local main=i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end elseif thirddata.statcharts.subtype == "stacked100" then if tonumber(n.ygridlinesdensity) < 1 then n.ygridlinesdensity=1 end for i=1, n.ylabelscount*n.ygridlinesdensity do local main=n.ylength/n.ylabelscount*i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end end end end -------------------------------------------------------------------------------- BAR m.bar={} m.bar.basic={} m.bar.clustered={} m.bar.stacked={} m.bar.stacked100={} function m.bar.default() return { barcolor="gray", barpalette=nil, bartransparency=1, barwidth=1, } end function m.bar.processvals(keyvals, keyvalsdata) m.bar.settings=set_hash_values(m.root.settings) m.bar.settings=set_hash_values(m.bar.default(), m.bar.settings) m.bar.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.bar.settings) if m.bar.settings.gridline == "dashed" then m.bar.settings.gridline="dashed evenly" elseif m.bar.settings.gridline == "full" then m.bar.settings.gridline="" else m.bar.settings.gridline="dashed withdots" end documentdata.statcharts=r.readdata(keyvalsdata) end function m.bar.all() local d,n=documentdata.statcharts,m.bar.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then if d.method == "plain" then thirddata.statcharts.subtype="basic" else thirddata.statcharts.subtype="clustered" end end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.bar[thirddata.statcharts.subtype].changeaxeslength()) if n.grid == "on" then ctx(m.bar.grid()) end m.bar[thirddata.statcharts.subtype].main() ctx(m.bar.axes()) if n.yaxislabels == "yes" then ctx(m.bar.yaxislabels()) end if n.xaxislabels == "yes" then if thirddata.statcharts.subtype == "stacked100" then ctx(m.bar[thirddata.statcharts.subtype].xaxislabels()) else ctx(m.bar.xaxislabels()) end end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.bar.basic.main() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local left=0 for i=1, rows do for j=1, cols do local leftbot=(n.bottom+(j-1)*(n.barwidth+n.distance))*n.yscale local val=d.data[i][j]*n.xscale ctx(m.bar.rectangle(leftbot, n.barwidth*n.yscale, j, val, left)) if n.contour == "yes" then ctx(m.bar.contour(j, leftbot, n.barwidth*n.yscale, val, left)) end end end end function m.bar.clustered.main() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local left, vcount=0, 0 for j=1, cols do for i=1, rows do vcount=vcount+1 local dcount=math.ceil(vcount/rows)-1 local leftbot=(n.bottom+(vcount-1)*n.barwidth+dcount*n.distance)*n.yscale local val=d.data[i][j]*n.xscale ctx(m.bar.rectangle(leftbot, n.barwidth*n.yscale, i, val, left)) if n.contour == "yes" then ctx(m.bar.contour(i, leftbot, n.barwidth*n.yscale, val, left)) end end end end function m.bar.stacked.main() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local vcount=0 for j=1, cols do local val, left=0, 0 for i=1, rows do vcount=vcount+1 local bwdcount=math.ceil(vcount/rows)-1 local leftbot=(n.bottom+bwdcount*(n.barwidth+n.distance))*n.yscale left=val val=val+d.data[i][j]*n.xscale ctx(m.bar.rectangle(leftbot, n.barwidth*n.yscale, i, val, left)) if n.contour == "yes" then ctx(m.bar.contour(i, leftbot, n.barwidth*n.yscale, val, left)) end end end end function m.bar.stacked100.main() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local vcount=0 for j=1, cols do local total, val, left=0, 0, 0 for i=1, rows do total=total+d.data[i][j] end for i=1, rows do vcount=vcount+1 local bwdcount=math.ceil(vcount/rows)-1 local leftbot=(n.bottom+bwdcount*(n.barwidth+n.distance))*n.yscale left=val val=val+d.data[i][j]/total*n.xlength ctx(m.bar.rectangle(leftbot, n.barwidth*n.yscale, i, val, left)) if n.contour == "yes" then ctx(m.bar.contour(i, leftbot, n.barwidth*n.yscale, val, left)) end end end end function m.bar.basic.changeaxeslength() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for i=1, rows do for j=1, cols do if d.data[i][j]*n.xscale > minxlength then minxlength=d.data[i][j]*n.xscale end end end if not n.xlength or n.xlength == "" or tonumber(n.xlength) < minxlength then n.xlength=minxlength end minylength=(n.bottom+cols*n.barwidth+(cols-1)*n.distance)*n.yscale if not n.ylength or n.ylength == "" or minylength > tonumber(n.ylength) then n.ylength=minylength+n.bottom*n.yscale end thirddata.statcharts.minylength=minylength end function m.bar.clustered.changeaxeslength() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for j=1, cols do for i=1, rows do if d.data[i][j]*n.xscale > minxlength then minxlength=d.data[i][j]*n.xscale end end end if not n.xlength or n.xlength == "" or tonumber(n.xlength) < minxlength then n.xlength=minxlength end minylength=(n.bottom+cols*rows*n.barwidth+(cols-1)*n.distance)*n.yscale if not n.ylength or n.ylength == "" or minylength > tonumber(n.ylength) then n.ylength=minylength+n.bottom*n.yscale end thirddata.statcharts.minylength=minylength end function m.bar.stacked.changeaxeslength() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for j=1, cols do local val=0 for i=1, rows do val=val+d.data[i][j]*n.xscale end if val > minxlength then minxlength=val end end if not n.xlength or n.xlength == "" or tonumber(n.xlength) < minxlength then n.xlength=minxlength end minylength=(n.bottom+cols*n.barwidth+(cols-1)*n.distance)*n.yscale if not n.ylength or n.ylength == "" or minylength > tonumber(n.ylength) then n.ylength=minylength+n.bottom*n.yscale end thirddata.statcharts.minylength=minylength end function m.bar.stacked100.changeaxeslength() local d,n=documentdata.statcharts,m.bar.settings local cols=#d.data[1] local minylength=0 if tonumber(n.xlength) < 3 then n.xlength=3 end minylength=(n.bottom+cols*n.barwidth+(cols-1)*n.distance)*n.yscale if not n.ylength or n.ylength == "" or minylength > tonumber(n.ylength) then n.ylength=minylength+n.bottom*n.yscale end thirddata.statcharts.minylength=minylength end function m.bar.rectangle(leftbot, barwidth, i, val, left) local n=m.bar.settings local finalcolor=m.decidecolor(i, n.barcolor, n.barpalette) return "fill ("..left.."u,"..leftbot.."u)--("..val.."u,"..leftbot.."u)--("..val.."u,"..leftbot+barwidth.."u)--("..left.."u,"..leftbot+barwidth.."u)--cycle withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.bartransparency..");" end function m.bar.contour(i, leftbot, barwidth, val, left) local n=m.bar.settings local finalcolor=m.decidecolor(i, n.contourcolor, n.contourpalette) return "pickup pencircle scaled "..n.contourwidth.." pt; draw ("..left.."u,"..leftbot.."u)--("..val.."u,"..leftbot.."u)--("..val.."u,"..leftbot+barwidth.."u)--("..left.."u,"..leftbot+barwidth.."u)--cycle withcolor \\MPcolor{"..finalcolor.."};" end function m.bar.axes() local n=m.bar.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.bar.xaxislabels() local lab=0 local n=m.bar.settings local xcount=math.floor(n.xlength) if n.decimalzero == "yes" then local dec, dec2, dec3=0, 0, 0 for j=1, xcount do lab=j/n.xscale if lab*10%10 ~= 0 then dec=1 if lab*100%10 ~= 0 then dec2=1 end if lab*1000%10 ~= 0 then dec3=1 break end end end for i=1, xcount do lab=i/n.xscale if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals) else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000) elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100) elseif dec == 1 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels {"..lab.."} etex, ("..i.."u, 0));") end else ctx("label.bot (btex \\xaxislabels {"..lab.."} etex, ("..i.."u, 0));") end end else for i=1, xcount do lab=i/n.xscale if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end else if lab*1000%10 ~= 0 then lab=math.round(lab*1000)/1000 elseif lab*100%10 ~= 0 then lab=math.round(lab*100)/100 elseif lab*10%10 ~= 0 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels {"..lab.."} etex, ("..i.."u, 0));") end else ctx("label.bot (btex \\xaxislabels {"..lab.."} etex, ("..i.."u, 0));") end end end end function m.bar.stacked100.xaxislabels() local lab=0 local n=m.bar.settings if n.decimalzero == "yes" then local dec, dec2, dec3=0, 0, 0 for j=1, n.xlabelscount do lab=j*100/n.xlabelscount if lab*10%10 ~= 0 then dec=1 if lab*100%10 ~= 0 then dec2=1 end if lab*1000%10 ~= 0 then dec3=1 break end end end for i=1, n.xlabelscount do lab=i*100/n.xlabelscount if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals)..percentsign else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000)..percentsign elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100)..percentsign elseif dec == 1 then lab=tostring(math.round(lab*10)/10)..percentsign else lab=tostring(math.round(lab))..percentsign end end local x=n.xlength/n.xlabelscount*i ctx("label.bot (btex \\yaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else for i=1, n.xlabelscount do lab=i*100/n.xlabelscount if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end lab=lab..percentsign else if lab*1000%10 ~= 0 then lab=string.format("%0.3f", math.round(lab*1000)/1000)..percentsign elseif lab*100%10 ~= 0 then lab=string.format("%0.2f", math.round(lab*100)/100)..percentsign elseif lab*10%10 ~= 0 then lab=tostring(math.round(lab*10)/10)..percentsign else lab=tostring(math.round(lab))..percentsign end end local x=n.xlength/n.xlabelscount*i ctx("label.bot (btex \\yaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end function m.bar.yaxislabels() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local lab, count=0, 0 if n.yaxislabelsnoval == "yes" and tonumber(n.ylength) > thirddata.statcharts.minylength+n.bottom*n.yscale then if thirddata.statcharts.subtype == "clustered" then count=math.round((n.ylength-(n.bottom*n.yscale))/((n.distance+rows*n.barwidth)*n.yscale))+1 elseif thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "stacked" or thirddata.statcharts.subtype == "stacked100" then count=math.round((n.ylength-(n.bottom*n.yscale))/((n.distance+n.barwidth)*n.yscale))+1 end else count=cols end for i=1, count do if #d.ylabels == 1 and d.ylabels[1] == "" then lab=i else if d.ylabels[i] then lab=d.ylabels[i] else lab="" end end if thirddata.statcharts.subtype == "clustered" then y=(n.bottom+rows*n.barwidth/2+(i-1)*(rows*n.barwidth+n.distance))*n.yscale elseif thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "stacked" or thirddata.statcharts.subtype == "stacked100" then y=(n.bottom+n.barwidth/2+(i-1)*(n.barwidth+n.distance))*n.yscale end if y <= tonumber(n.ylength) then ctx("label.lft (btex \\yaxislabels{"..lab.."} etex, (0, "..y.."u));") end end end function m.bar.grid() local d,n=documentdata.statcharts,m.bar.settings local rows, cols=#d.data, #d.data[1] local count=0 if n.xgridlines == "yes" then if thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "clustered" or thirddata.statcharts.subtype == "stacked"then local ycount=math.floor(n.xlength)*n.xgridlinesdensity for i=1, ycount do local main=i/n.xgridlinesdensity ctx(m.xgridlines(main, n)) end elseif thirddata.statcharts.subtype == "stacked100" then if tonumber(n.xgridlinesdensity) < 1 then n.xgridlinesdensity=1 end for i=1, n.xlabelscount*n.xgridlinesdensity do local main=n.xlength/n.xlabelscount*i/n.xgridlinesdensity ctx(m.xgridlines(main, n)) end end end if n.ygridlines == "yes" then if thirddata.statcharts.subtype == "clustered" then local maxcount=math.round((n.ylength-(n.bottom*n.yscale))/((n.distance+n.barwidth*rows)*n.yscale)) if n.ygridlinesnoval == "yes" then count=maxcount else count=cols end for i=1, count do local main=(n.bottom+n.barwidth*rows/2+(i-1)*(rows*n.barwidth+n.distance))*n.yscale ctx(m.ygridlines(main, n)) end else local maxcount=math.round((n.ylength-(n.bottom*n.yscale))/((n.distance+n.barwidth)*n.yscale)) if n.ygridlinesnoval == "yes" then count=maxcount else count=cols end for i=1, count do local main=(n.bottom+n.barwidth/2+(i-1)*(n.barwidth+n.distance))*n.yscale ctx(m.ygridlines(main, n)) end end end end ------------------------------------------------------------------------------------ BUBBLE m.bubble={} m.bubble.basic={} function m.bubble.default() return { bubblediameter=1, bubblecolor="gray", bubblepalette=nil, bubbletransparency=0.7, xcoor="no", zcoor="no", xaxislabinit=1, xaxislabinc=1, } end function m.bubble.processvals(keyvals, keyvalsdata) m.bubble.settings=set_hash_values(m.root.settings) m.bubble.settings=set_hash_values(m.bubble.default(), m.bubble.settings) m.bubble.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.bubble.settings) if m.bubble.settings.gridline == "dashed" then m.bubble.settings.gridline="dashed evenly" elseif m.bubble.settings.gridline == "full" then m.bubble.settings.gridline="" else m.bubble.settings.gridline="dashed withdots" end if m.bubble.settings.xcoor == "yes" then m.bubble.settings.left, m.bubble.settings.distance=1,1 end documentdata.statcharts=r.readdata(keyvalsdata) end function m.bubble.all() local d,n=documentdata.statcharts,m.bubble.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then thirddata.statcharts.subtype="basic" end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.bubble.changeaxeslength()) if n.grid == "on" then ctx(m.bubble.grid()) end m.bubble[thirddata.statcharts.subtype].main() ctx(m.bubble.axes()) if n.xaxislabels == "yes" then ctx(m.bubble.xaxislabels()) end if n.yaxislabels == "yes" then ctx(m.yaxislabels()) end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.bubble.basic.main() local d,n=documentdata.statcharts,m.bubble.settings local rows=#d.data local count=0 if n.xcoor == "no" and n.zcoor == "no" then for i=1, rows do local cols=#d.data[i] for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale local dia=n.bubblediameter if rows/1 == 1 then index=j else index=count end ctx(m.bubble.bubbles(index, main, val, dia)) if n.contour == "yes" then ctx(m.bubble.contour(i, main, val, dia)) end end end elseif n.xcoor == "yes" and n.zcoor == "no" then for i=2, rows, 2 do local cols=#d.data[i] count=count+1 for j=1, cols do local main=d.data[i-1][j]*n.xscale local val=d.data[i][j]*n.yscale local dia=n.bubblediameter if rows/2 == 1 then index=j else index=count end ctx(m.bubble.bubbles(index, main, val, dia)) if n.contour == "yes" then ctx(m.bubble.contour(count, main, val, dia)) end end end elseif n.xcoor == "no" and n.zcoor == "yes" then for i=1, rows, 2 do local cols=#d.data[i] count=count+1 for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale local dia=d.data[i+1][j]*n.bubblediameter if rows/2 == 1 then index=j else index=count end ctx(m.bubble.bubbles(index, main, val, dia)) if n.contour == "yes" then ctx(m.bubble.contour(count, main, val, dia)) end end end elseif n.xcoor == "yes" and n.zcoor == "yes" then for i=2, rows, 3 do local cols=#d.data[i] count=count+1 for j=1, cols do local main=d.data[i-1][j]*n.xscale local val=d.data[i][j]*n.yscale local dia=d.data[i+1][j]*n.bubblediameter if rows/3 == 1 then index=j else index=count end ctx(m.bubble.bubbles(index, main, val, dia)) if n.contour == "yes" then ctx(m.bubble.contour(count, main, val, dia)) end end end end end function m.bubble.changeaxeslength() local d,n=documentdata.statcharts,m.bubble.settings local rows, maxcols=#d.data, 0 local minxlength, minylength=0, 0 local maxycoor= 0 local inc,init=1,1 for i=1, rows do if maxcols < #d.data[i] then maxcols=#d.data[1] end end if n.xcoor == "yes" then init,inc=2,2 end if n.zcoor == "yes" then inc=3 end for i=init, rows, inc do local cols=#d.data[i] for j=1, cols do if maxycoor < tonumber(d.data[i][j]) then maxycoor=tonumber(d.data[i][j]) end end end minylength=maxycoor*n.yscale if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength+1*n.yscale end if n.xcoor == "yes" then local maxxcoor=0 if n.zcoor == "no" then inc=2 else inc=3 end for i=1, rows, inc do local cols=#d.data[i] for j=1, cols do if maxxcoor < d.data[i][j] then maxxcoor=d.data[i][j] end end end minxlength=maxxcoor*n.xscale else minxlength=(n.left+(maxcols-1)*n.distance)*n.xscale end if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.bubble.bubbles(ind, main, val, dia) local n=m.bubble.settings local finalcolor=m.decidecolor(ind, n.bubblecolor, n.bubblepalette) return "fill (fullcircle scaled "..dia.."u shifted ("..main.."u,"..val.."u)) withcolor \\MPcolor{"..finalcolor.."} withtransparency (1,"..n.bubbletransparency..");" end function m.bubble.contour(i, main, val, dia) local n=m.bubble.settings local finalcolor=m.decidecolor(i, n.contourcolor, n.contourpalette) return "pickup pencircle scaled "..n.contourwidth.."pt; draw (fullcircle scaled "..dia.."u shifted ("..main.."u,"..val.."u)) withcolor \\MPcolor{"..finalcolor.."};" end function m.bubble.axes() local n=m.bubble.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.bubble.xaxislabels() local d,n=documentdata.statcharts,m.bubble.settings local rows, maxcols=#d.data, 0 local lab, count=0, 0 for i=1, rows do if maxcols < #d.data[i] then maxcols=#d.data[1] end end if n.xcoor == "yes" then if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 else local maxxcoor=0 if n.zcoor == "no" then inc=2 else inc=3 end for i=1, rows, inc do local cols=#d.data[i] for j=1, cols do if maxxcoor < d.data[i][j] then maxxcoor=d.data[i][j] end end end count=math.round(maxxcoor) end for i=1, count do local x=(n.left+(i-1)*n.distance)*n.xscale lab=math.round(n.xaxislabinit+(i-1)*n.xaxislabinc) if x <= tonumber(n.xlength) then if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end else if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 else count=maxcols end for i=1, count do if #d.xlabels == 1 and d.xlabels[1] == "" then lab=i else if d.xlabels[i] then lab=d.xlabels[i] else lab="" end end local x=(n.left+(i-1)*n.distance)*n.xscale if x <= tonumber(n.xlength) then if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end end end function m.bubble.grid() local d,n=documentdata.statcharts,m.bubble.settings local rows, maxcols=#d.data, 0 local count=0 for i=1, rows do if maxcols < #d.data[i] then maxcols=#d.data[1] end end if n.xgridlines == "yes" then if n.xgridlinesnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale)*n.xgridlinesdensity)+1 else if n.xcoor == "yes" then local maxxcoor=0 if n.zcoor == "no" then inc=2 else inc=3 end for i=1, rows, inc do local cols=#d.data[i] for j=1, cols do if maxxcoor < d.data[i][j] then maxxcoor=d.data[i][j] end end end count=math.round(maxxcoor*n.xgridlinesdensity) elseif n.xcoor == "no" then count=math.round(maxcols*n.xgridlinesdensity) end if tonumber(n.xgridlinesdensity) > 1 then count=count-(n.xgridlinesdensity-1) end end for i=1, count do -- local main if tonumber(n.xgridlinesdensity) > 1 then main=((n.left+(i-1)*n.distance/n.xgridlinesdensity))*n.xscale else iter=i/n.xgridlinesdensity main=((n.left+(iter-1)*n.distance))*n.xscale end if main > 0 and main <= tonumber(n.xlength) then ctx(m.xgridlines(main, n)) end end if n.xgridlinesleft == "yes" then local leftcount=n.left*n.xgridlinesdensity/n.distance for i=1, leftcount do local main=((n.left-i*n.distance/n.xgridlinesdensity)*n.xscale) if main > 0 then ctx(m.xgridlines(main, n)) end end end end if n.ygridlines == "yes" then local xcount=math.floor(n.ylength)*n.ygridlinesdensity for i=1, xcount do local main=i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end end end ---------------------------------------------------------------------------------------- COLUMN m.column={} m.column.basic={} m.column.clustered={} m.column.stacked={} m.column.stacked100={} function m.column.default() return { columncolor="gray", columnpalette=nil, columntransparency=1, columnwidth=1, } end function m.column.processvals(keyvals, keyvalsdata) m.column.settings=set_hash_values(m.root.settings) m.column.settings=set_hash_values(m.column.default(), m.column.settings) m.column.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.column.settings) if m.column.settings.gridline == "dashed" then m.column.settings.gridline="dashed evenly" elseif m.column.settings.gridline == "full" then m.column.settings.gridline="" else m.column.settings.gridline="dashed withdots" end documentdata.statcharts=r.readdata(keyvalsdata) end function m.column.all() local d,n=documentdata.statcharts,m.column.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then if m.method == "plain" then thirddata.statcharts.subtype="basic" else thirddata.statcharts.subtype="clustered" end end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.column[thirddata.statcharts.subtype].changeaxeslength()) if n.grid == "on" then ctx(m.column.grid()) end m.column[thirddata.statcharts.subtype].main() ctx(m.column.axes()) if n.xaxislabels == "yes" then ctx(m.column.xaxislabels()) end if n.yaxislabels == "yes" then if thirddata.statcharts.subtype == "stacked100" then ctx(m[thirddata.statcharts.subtype].yaxislabels()) else ctx(m.yaxislabels()) end end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.column.basic.main() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local bottom=0 for i=1, rows do for j=1, cols do local leftbot=(n.left+(j-1)*(n.columnwidth+n.distance))*n.xscale local val=d.data[i][j]*n.yscale ctx(m.column.rectangle(j, leftbot, n.columnwidth*n.xscale, val, bottom)) if n.contour == "yes" then ctx(m.column.contour(j, leftbot, n.columnwidth*n.xscale, val, bottom)) end end end end function m.column.clustered.main() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local bottom, vcount=0, 0 for j=1, cols do for i=1, rows do vcount=vcount+1 local dcount=math.ceil(vcount/rows)-1 local leftbot=(n.left+(vcount-1)*n.columnwidth+dcount*n.distance)*n.xscale local val=d.data[i][j]*n.yscale ctx(m.column.rectangle(i, leftbot, n.columnwidth*n.xscale, val, bottom)) if n.contour == "yes" then ctx(m.column.contour(i, leftbot, n.columnwidth*n.xscale, val, bottom)) end end end end function m.column.stacked.main() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local vcount=0 for j=1, cols do local val, bottom=0, 0 for i=1, rows do vcount=vcount+1 local cwdcount=math.ceil(vcount/rows)-1 local leftbot=(n.left+cwdcount*(n.columnwidth+n.distance))*n.xscale bottom=val val=val+d.data[i][j]*n.yscale ctx(m.column.rectangle(i, leftbot, n.columnwidth*n.xscale, val, bottom)) if n.contour == "yes" then ctx(m.column.contour(i, leftbot, n.columnwidth*n.xscale, val, bottom)) end end end end function m.column.stacked100.main() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local vcount=0 for j=1, cols do local total, val, bottom=0, 0, 0 for i=1, rows do total=total+d.data[i][j] end for i=1, rows do vcount=vcount+1 local cwdcount=math.ceil(vcount/rows)-1 local leftbot=(n.left+cwdcount*(n.columnwidth+n.distance))*n.xscale bottom=val val=val+d.data[i][j]/total*n.ylength ctx(m.column.rectangle(i, leftbot, n.columnwidth*n.xscale, val, bottom)) if n.contour == "yes" then ctx(m.column.contour(i, leftbot, n.columnwidth*n.xscale, val, bottom)) end end end end function m.column.basic.changeaxeslength() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for i=1, rows do for j=1, cols do if d.data[i][j]*n.yscale > minylength then minylength=tonumber(d.data[i][j])*n.yscale end end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength end minxlength=(n.left+cols*n.columnwidth+(cols-1)*n.distance)*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.column.clustered.changeaxeslength() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for j=1, cols do for i=1, rows do if d.data[i][j]*n.yscale > minylength then minylength=d.data[i][j]*n.yscale end end end if not n.ylength or n.ylength == "" or tonumber(n.ylength)tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.column.stacked.changeaxeslength() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for j=1, cols do local val=0 for i=1, rows do val=val+d.data[i][j]*n.yscale end if val > minylength then minylength=val end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength end minxlength=(n.left+cols*n.columnwidth+(cols-1)*n.distance)*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.column.stacked100.changeaxeslength() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local minxlength=0 if tonumber(n.ylength) < 3 then n.ylength=3 end minxlength=(n.left+cols*n.columnwidth+(cols-1)*n.distance)*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.column.rectangle(i, leftbot, columnwidth, val, bottom) local n=m.column.settings local finalcolor=m.decidecolor(i, n.columncolor, n.columnpalette) return "fill ("..leftbot.."u,"..bottom.."u)--("..leftbot+columnwidth.."u,"..bottom.."u)--("..leftbot+columnwidth.."u,"..val.."u)--("..leftbot.."u,"..val.."u)--cycle withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.columntransparency..");" end function m.column.contour(i, leftbot, columnwidth, val, bottom) local n=m.column.settings local finalcolor=m.decidecolor(i, n.contourcolor, n.contourpalette) return "pickup pencircle scaled "..n.contourwidth.." pt; draw ("..leftbot.."u,"..bottom.."u)--("..leftbot+columnwidth.."u,"..bottom.."u)--("..leftbot+columnwidth.."u,"..val.."u)--("..leftbot.."u,"..val.."u)--cycle withcolor \\MPcolor{"..finalcolor.."};" end function m.column.axes() local n=m.column.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.column.xaxislabels() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local lab, count=0, 0 if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then if thirddata.statcharts.subtype == "clustered" then count=math.round((n.xlength-(n.left*n.xscale))/((n.distance+rows*n.columnwidth)*n.xscale))+1 elseif thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "stacked" or thirddata.statcharts.subtype == "stacked100" then count=math.round((n.xlength-(n.left*n.xscale))/((n.distance+n.columnwidth)*n.xscale))+1 end else count=cols end for i=1, count do if #d.xlabels == 1 and d.xlabels[1] == "" then lab=i else if d.xlabels[i] then lab=d.xlabels[i] else lab="" end end if thirddata.statcharts.subtype == "clustered" then x=(n.left+rows*n.columnwidth/2+(i-1)*(rows*n.columnwidth+n.distance))*n.xscale elseif thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "stacked" or thirddata.statcharts.subtype == "stacked100" then x=(n.left+n.columnwidth/2+(i-1)*(n.columnwidth+n.distance))*n.xscale end if x <= tonumber(n.xlength) then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end function m.column.grid() local d,n=documentdata.statcharts,m.column.settings local rows, cols=#d.data, #d.data[1] local count=0 if n.xgridlines == "yes" then if thirddata.statcharts.subtype == "clustered" then if n.xgridlinesnoval == "yes" then count=math.round((n.xlength-(n.left*n.xscale))/((n.distance+n.columnwidth*rows)*n.xscale)) else count=cols end for i=1, count do local main=(n.left+n.columnwidth*rows/2+(i-1)*(rows*n.columnwidth+n.distance))*n.xscale ctx(m.xgridlines(main, n)) end else local maxcount=math.round((n.xlength-(n.left*n.xscale))/((n.distance+n.columnwidth)*n.xscale)) if n.xgridlinesnoval == "yes" then count=maxcount else count=cols end for i=1, count do local main=(n.left+n.columnwidth/2+(i-1)*(n.columnwidth+n.distance))*n.xscale ctx(m.xgridlines(main, n)) end end end if n.ygridlines == "yes" then if thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "clustered" or thirddata.statcharts.subtype == "stacked" then local xcount=math.floor(n.ylength)*n.ygridlinesdensity for i=1, xcount do local main=i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end elseif thirddata.statcharts.subtype == "stacked100" then if tonumber(n.ygridlinesdensity) < 1 then n.ygridlinesdensity=1 end for i=1, n.ylabelscount*n.ygridlinesdensity do local main=n.ylength/n.ylabelscount*i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end end end end ---------------------------------------------------------------------------------------- LINE m.line={} m.line.basic={} m.line.stacked={} m.line.stacked100={} function m.line.default() return { } end function m.line.processvals(keyvals, keyvalsdata) m.line.settings=set_hash_values(m.root.settings) m.line.settings=set_hash_values(m.line.default(), m.line.settings) m.line.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.line.settings) if m.line.settings.gridline == "dashed" then m.line.settings.gridline="dashed evenly" elseif m.line.settings.gridline == "full" then m.line.settings.gridline="" else m.line.settings.gridline="dashed withdots" end documentdata.statcharts=r.readdata(keyvalsdata) end function m.line.all() local d,n=documentdata.statcharts,m.line.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then thirddata.statcharts.subtype="basic" end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.line[thirddata.statcharts.subtype].changeaxeslength()) if n.grid == "on" then ctx(m.line.grid()) end m.line[thirddata.statcharts.subtype].main() ctx(m.line.axes()) if n.xaxislabels == "yes" then ctx(m.line.xaxislabels()) end if n.yaxislabels == "yes" then if thirddata.statcharts.subtype == "stacked100" then ctx(m[thirddata.statcharts.subtype].yaxislabels()) else ctx(m.yaxislabels()) end end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.line.basic.main() local d,n=documentdata.statcharts,m.line.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.line.decimals() for i=1, rows do for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale if j < cols then local nextval=d.data[i][j+1]*n.yscale ctx(m.line.line(i, main, val, nextval)) end if n.dots == "yes" then ctx(m.line.dots(i, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end function m.line.stacked.main() local d,n=documentdata.statcharts,m.line.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.line.decimals() for i=1, rows do for j=1, cols do local val, nextval=0, 0 local main=(n.left+(j-1)*n.distance)*n.xscale for k=1, i do val=val+d.data[k][j]*n.yscale end if j < cols then if i == 1 then nextval=d.data[i][j+1]*n.yscale else for k=1, i do nextval=nextval+d.data[k][j+1]*n.yscale end end ctx(m.line.line(i, main, val, nextval)) end if n.dots == "yes" then ctx(m.line.dots(i, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end function m.line.stacked100.main() local d,n=documentdata.statcharts,m.line.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.line.decimals() for i=1, rows do for j=1, cols do local val, nextval, totalval, totalnextval=0, 0, 0, 0 for k=1, rows do totalval=totalval+d.data[k][j] if j < cols then totalnextval=totalnextval+d.data[k][j+1] end end local main=(n.left+(j-1)*n.distance)*n.xscale for l=1, i do val=val+d.data[l][j]/totalval*n.ylength end if j < cols then if i == 1 then nextval=d.data[i][j+1]/totalnextval*n.ylength else for l=1, i do nextval=nextval+d.data[l][j+1]/totalnextval*n.ylength end end ctx(m.line.line(i, main, val, nextval)) end if n.dots == "yes" then ctx(m.line.dots(i, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end function m.line.basic.changeaxeslength() local d,n=documentdata.statcharts,m.line.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for i=1, rows do for j=1, cols do if d.data[i][j]*n.yscale > minylength then minylength=d.data[i][j]*n.yscale end end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength+1*n.yscale end minxlength=(n.left+(cols-1)*n.distance)*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.line.stacked.changeaxeslength() local d,n=documentdata.statcharts,m.line.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for j=1, cols do local total=0 for i=1, rows do total=total+d.data[i][j]*n.yscale end if total > minylength then minylength=total end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength+1*n.yscale end minxlength=(n.left+(cols-1)*n.distance)*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.line.stacked100.changeaxeslength() local d,n=documentdata.statcharts,m.line.settings local cols=#d.data[1] local minxlength=0 if tonumber(n.ylength) < 3 then n.ylength=3 end minxlength=(n.left+(cols-1)*n.distance)*n.xscale if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.line.line(i, main, val, next) local n=m.line.settings local finalcolor=m.decidecolor(i, n.linecolor, n.linepalette) return "pickup pencircle scaled "..n.linewidth.."pt; draw("..main.."u,"..val.."u)--("..main+n.distance*n.xscale.."u,"..next.."u) withcolor \\MPcolor{"..finalcolor.."};" end function m.line.dots(i, main, val) local n=m.line.settings local finalcolor=m.decidecolor(i, n.dotscolor, n.dotspalette) return "pickup pencircle scaled "..n.dotswidth.."pt; drawdot ("..main.."u,"..val.."u) withcolor \\MPcolor{"..finalcolor.."};" end function m.line.decimals() local d,n=documentdata.statcharts,m.line.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3, val, totalval=0, 0, 0, 0, 0 if n.dotslabels == "yes" and n.decimalzero == "yes" then for i=1, rows do for j=1, cols do if thirddata.statcharts.subtype == "basic" then val=d.data[i][j] elseif thirddata.statcharts.subtype == "stacked" then for k=1, i do val=val+d.data[k][j] end elseif thirddata.statcharts.subtype == "stacked100" then for k=1, rows do totalval=totalval+d.data[k][j] end for l=1, i do val=val+d.data[l][j]/totalval*n.ylength end end if val*10%10 ~= 0 then dec=1 if val*100%10 ~= 0 then dec2=1 end if val*1000%10 ~= 0 then dec3=1 break end end end end end return dec, dec2, dec3 end function m.line.axes() local n=m.line.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.line.xaxislabels(i, x) local d,n=documentdata.statcharts,m.line.settings local cols=#d.data[1] local lab, count=0, 0 if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 else count=cols end for i=1, count do if #d.xlabels == 1 and d.xlabels[1] == "" then lab=i else if d.xlabels[i] then lab=d.xlabels[i] else lab="" end end local x=(n.left+(i-1)*n.distance)*n.xscale if x <= tonumber(n.xlength) then if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end end function m.line.grid() local d,n=documentdata.statcharts,m.line.settings local cols=#d.data[1] local count=0 if n.xgridlines == "yes" then if n.xgridlinesnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale)*n.xgridlinesdensity)+1 else count=math.round(cols*n.xgridlinesdensity) if tonumber(n.xgridlinesdensity) > 1 then count=count-(n.xgridlinesdensity-1) end end for i=1, count do -- local main if tonumber(n.xgridlinesdensity) > 1 then main=((n.left+(i-1)*n.distance/n.xgridlinesdensity))*n.xscale else iter=i/n.xgridlinesdensity main=((n.left+(iter-1)*n.distance))*n.xscale end if main > 0 and main <= tonumber(n.xlength) then ctx(m.xgridlines(main, n)) end end if n.xgridlinesleft == "yes" then local leftcount=n.left*n.xgridlinesdensity/n.distance for i=1, leftcount do local main=((n.left-i*n.distance/n.xgridlinesdensity)*n.xscale) if main > 0 then ctx(m.xgridlines(main, n)) end end end end if n.ygridlines == "yes" then if thirddata.statcharts.subtype == "basic" or thirddata.statcharts.subtype == "stacked" then local xcount=math.floor(n.ylength)*n.ygridlinesdensity for i=1, xcount do local main=i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end elseif thirddata.statcharts.subtype == "stacked100" then if tonumber(n.ygridlinesdensity) < 1 then n.ygridlinesdensity=1 end for i=1, n.ylabelscount*n.ygridlinesdensity do local main=n.ylength/n.ylabelscount*i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end end end end --------------------------------------------------------------------------------------------- PIE m.pie={} function m.pie.default() return { fillcolor=nil, fillpalette="orange", filltransparency=1, diameter=5, holediameter=3, perc="no", distanceout=0.2, distancebetween=0, labels="yes", labelposition="out", coef=0, out={}, } end function m.pie.processvals(keyvals, keyvalsdata) m.pie.settings=set_hash_values(m.root.settings) m.pie.settings=set_hash_values(m.pie.default(), m.pie.settings) m.pie.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.pie.settings) m.pie.settings.partsout=utilities.parsers.settings_to_array(m.pie.settings.out) for i=1, #m.pie.settings.partsout do m.pie.settings.partsout[i]=tonumber(m.pie.settings.partsout[i]) end documentdata.statcharts=r.readdata(keyvalsdata) end function m.pie.all() local n=m.pie.settings radius=n.diameter/2 if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then if d.method == "plain" then thirddata.statcharts.subtype="basic" else thirddata.statcharts.subtype="doughnut" end end ctx.startMPcode() ctx("save u; u="..n.unit..";") m.pie[thirddata.statcharts.subtype]() ctx.stopMPcode() end function m.pie.basic() local d,n=documentdata.statcharts,m.pie.settings local lab=0 local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.pie.decimals() local total, sum, angle, angleh=0, 0, 0, 0 for i=1, rows do for j=1, cols do sum=sum+d.data[i][j] end end local x1,y1=0,radius for i=1, rows do for j=1, cols do local perc=d.data[i][j]/sum*100 angleh=angle+(perc*3.6*3.1415/180)/2 angle=angle+(perc*3.6*3.1415/180) -- pi/180 prevod na radians local x2=math.sin(angle)*radius local y2=math.cos(angle)*radius local xh=math.sin(angleh)*radius local yh=math.cos(angleh)*radius ctx(m.pie.parts(j, x1, x2, xh, yh, y1, y2)) if n.contour == "yes" then ctx(m.pie.contour(j, x1, x2, xh, yh, y1, y2)) end total=total+math.round(perc*1/n.decimals)*n.decimals if j == cols then local remainder=total%100 if remainder ~= 0 then if remainder > 90 then perc=perc+100-remainder else perc=perc-remainder end end end if n.labels == "yes" then if n.perc == "yes" then if n.decimals then lab=math.round(perc/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end end lab=lab..percentsign ctx(m.pie.partslabels(j, lab, xh, yh, angleh)) else lab=d.data[i][j] if n.decimalzero == "yes" then if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals) else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000) elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100) elseif dec == 1 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end else if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end else if lab*1000%10 ~= 0 then lab=math.round(lab*1000)/1000 elseif lab*100%10 ~= 0 then lab=math.round(lab*100)/100 elseif lab*10%10 ~= 0 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end end ctx(m.pie.partslabels(j, lab, xh, yh, angleh)) end end x1, y1=x2, y2 end end end function m.pie.doughnut() local d,n=documentdata.statcharts,m.pie.settings local lab=0 local rows=#d.data local doughnutwidth=(n.diameter-n.holediameter)/2 local dec, dec2, dec3=m.pie.decimals() for i=1, rows do local cols=#d.data[i] local total, sum, angle, angleh=0, 0, 0, 0 for j=1, cols do sum=sum+d.data[i][j] end local x1=0 local y1=radius+(i-1)*(doughnutwidth+n.distancebetween) local x1in=0 local y1in=n.holediameter/2+(i-1)*(doughnutwidth+n.distancebetween) for j=1, cols do local perc=d.data[i][j]/sum*100 angleh=angle+(perc*3.6*3.1415/180)/2 angle=angle+(perc*3.6*3.1415/180) -- pi/180 prevod na radiany local x2=math.sin(angle)*(radius+(i-1)*(doughnutwidth+n.distancebetween)) local y2=math.cos(angle)*(radius+(i-1)*(doughnutwidth+n.distancebetween)) local x2in=math.sin(angle)*(n.holediameter/2+(i-1)*(doughnutwidth+n.distancebetween)) local y2in=math.cos(angle)*(n.holediameter/2+(i-1)*(doughnutwidth+n.distancebetween)) local xh=math.sin(angleh)*(radius+(i-1)*(doughnutwidth+n.distancebetween)) local yh=math.cos(angleh)*(radius+(i-1)*(doughnutwidth+n.distancebetween)) local xhin=math.sin(angleh)*(n.holediameter/2+(i-1)*(doughnutwidth+n.distancebetween)) local yhin=math.cos(angleh)*(n.holediameter/2+(i-1)*(doughnutwidth+n.distancebetween)) ctx(m.pie.doughnutparts(j, x1, x2, xh, yh, y1, y2, x1in, x2in, xhin, yhin, y1in, y2in)) if n.contour == "yes" then ctx(m.pie.doughnutcontour(j, x1, x2, xh, yh, y1, y2, x1in, x2in, xhin, yhin, y1in, y2in)) end total=total+math.round(perc*1/n.decimals)*n.decimals if j == cols then local remainder=total%100 if remainder ~= 0 then if remainder > 90 then perc=perc+100-remainder else perc=perc-remainder end end end if n.labels == "yes" then if n.perc == "yes" then if n.decimals then lab=math.round(perc/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end end lab=lab..percentsign ctx(m.pie.partslabels(j, lab, xh, yh, angleh)) else lab=d.data[i][j] if n.decimalzero == "yes" then if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals) else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000) elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100) elseif dec == 1 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end else if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end else if lab*1000%10 ~= 0 then lab=math.round(lab*1000)/1000 elseif lab*100%10 ~= 0 then lab=math.round(lab*100)/100 elseif lab*10%10 ~= 0 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end end ctx(m.pie.partslabels(j, lab, xh, yh, angleh)) end end x1, y1=x2, y2 x1in, y1in=x2in, y2in end end end function m.pie.parts(i, x1, x2, xh, yh, y1, y2) local n, path=m.pie.settings, "p" for j=1, #n.partsout do if i == n.partsout[j] then path="pout" break end end local finalcolor=m.pickcolor(i, n.fillcolor, n.fillpalette) return "path p, pout; p=(0,0)--("..x1.."u,"..y1.."u)..("..xh.."u,"..yh.."u)..("..x2.."u,"..y2.."u)--cycle; pout=p shifted ("..xh*n.distanceout.."u,"..yh*n.distanceout.."u); fill "..path.." withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.filltransparency..");" end function m.pie.doughnutparts(i, x1, x2, xh, yh, y1, y2, x1d, x2d, xhd, yhd, y1d, y2d) local n=m.pie.settings local finalcolor=m.pickcolor(i, n.fillcolor, n.fillpalette) return "path p; p=("..x1d.."u,"..y1d.."u)..("..xhd.."u,"..yhd.."u)..("..x2d.."u,"..y2d.."u)--("..x2.."u,"..y2.."u)..("..xh.."u,"..yh.."u)..("..x1.."u,"..y1.."u)--cycle; fill p withcolor \\MPcolor{"..finalcolor.."} withtransparency (1, "..n.filltransparency..");" end function m.pie.contour(i, x1, x2, xh, yh, y1, y2) local n, path=m.pie.settings, "p" for j=1, #n.partsout do if i == n.partsout[j] then path="pout" break end end local finalcolor=m.decidecolor(i, n.contourcolor, n.contourpalette) return "path p, pout; p=(0,0)--("..x1.."u,"..y1.."u)..("..xh.."u,"..yh.."u)..("..x2.."u,"..y2.."u)--cycle; pout=p shifted ("..xh*n.distanceout.."u,"..yh*n.distanceout.."u); draw "..path.." withcolor \\MPcolor{"..finalcolor.."};" end function m.pie.doughnutcontour(i, x1, x2, xh, yh, y1, y2, x1d, x2d, xhd, yhd, y1d, y2d) local n=m.pie.settings local finalcolor=m.decidecolor(i, n.contourcolor, n.contourpalette) return "pickup pencircle scaled "..n.contourwidth.." pt; draw ("..x1d.."u,"..y1d.."u)..("..xhd.."u,"..yhd.."u)..("..x2d.."u,"..y2d.."u)--("..x2.."u,"..y2.."u)..("..xh.."u,"..yh.."u)..("..x1.."u,"..y1.."u)--cycle withcolor \\MPcolor{"..finalcolor.."};" end function m.pie.decimals() local d,n=documentdata.statcharts,m.pie.settings local rows=#d.data local dec, dec2, dec3=0, 0, 0 if n.labels == "yes" and n.decimalzero == "yes" and n.percent ~= "yes" then for i=1, rows do for j=1, #d.data[i] do local val=d.data[i][j] if val*10%10 ~= 0 then dec=1 if val*100%10 ~= 0 then dec2=1 end if val*1000%10 ~= 0 then dec3=1 break end end end end end return dec, dec2, dec3 end function m.pie.partslabels(i, lab, xh, yh, angleh) local d,n,isin=documentdata.statcharts,m.pie.settings, 0 local rows=#d.data for j=1, #n.partsout do if i == n.partsout[j] then isin=1 break end end local pos=math.floor(angleh*180/3.14159/45) if n.labelposition == "in" or rows > 1 then pos=(pos+4)% 8+1 coef=1-n.coef else pos=pos+1 coef=1+n.coef end if thirddata.statcharts.subtype == "basic" and isin == 1 then ctx("label."..thirddata.statcharts.MPpositions[pos].." (btex \\partslabels{"..lab.."} etex, ("..xh*coef.."u,"..yh*coef.."u) shifted ("..xh*n.distanceout.."u, "..yh*n.distanceout.."u) );") else ctx("label."..thirddata.statcharts.MPpositions[pos].." (btex \\partslabels{"..lab.."} etex, ("..xh*coef.."u,"..yh*coef.."u));") end end ---------------------------------------------------------------------------------------- RADAR m.radar={} m.radar.basic={} function m.radar.default() return { axes="yes", axiswidth=0.5, axisline="dashed", axiscolor="middlegray", step=2, layers=0, layercolor="black", layerline="dashed", layerwidth=0.5, layerslabels="yes", fill="no", fillcolor="gray", fillpalette=nil, filltransparency=1, } end function m.radar.processvals(keyvals, keyvalsdata) m.radar.settings=set_hash_values(m.root.settings) m.radar.settings=set_hash_values(m.radar.default(), m.radar.settings) m.radar.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.radar.settings) if m.radar.settings.axisline == "dotted" then m.radar.settings.axisline="dashed withdots" elseif m.radar.settings.axisline == "full" then m.radar.settings.axisline="" else m.radar.settings.axisline="dashed evenly" end if m.radar.settings.layerline == "dotted" then m.radar.settings.layerline="dashed withdots" elseif m.radar.settings.layerline == "full" then m.radar.settings.layerline="" else m.radar.settings.layerline="dashed evenly" end documentdata.statcharts=r.readdata(keyvalsdata) end function m.radar.all() local d,n=documentdata.statcharts,m.radar.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then thirddata.statcharts.subtype= "basic" end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.radar.changelayers()) if n.axes == "yes" then ctx(m.radar.axes()) end ctx(m.radar.layers()) if n.layerslabels == "yes" then ctx(m.radar.layerslabels()) end if n.axes == "yes" then ctx(m.radar.axes()) end m.radar[thirddata.statcharts.subtype].main() ctx.stopMPcode() end function m.radar.basic.main() local d,n=documentdata.statcharts,m.radar.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.radar.decimals() for i=1, rows do line="" for j=1, cols do local y=d.data[i][j]/n.step*n.distance.."u) rotated -(("..j.."-1)*360/"..cols..")" line=line.."((0,"..y..")--" if n.dotslabels == "yes" then ctx(m.dotslabels(y, d.data[i][j], dec, dec2, dec3, j)) end end line=line.."cycle" if n.fill == "yes" then ctx(m.radar.fill(i, line)) end ctx(m.radar.line(i, line)) if n.dots == "yes" then for j=1, cols do ctx(m.radar.dots(i, j, d.data[i][j])) end end end end function m.radar.changelayers() local d,n=documentdata.statcharts,m.radar.settings local rows, cols=#d.data, #d.data[1] local maxdata=0 for i=1, rows do for j=1, cols do if tonumber(d.data[i][j]) > maxdata then maxdata=tonumber(d.data[i][j]) end end end local minlayers=math.ceil(maxdata/n.step) if tonumber(n.layers) < minlayers then n.layers=minlayers end end function m.radar.layers() local d,n=documentdata.statcharts,m.radar.settings local cols=#d.data[1] for i=1, n.layers do ctx("pickup pencircle scaled "..n.layerwidth.." pt; draw for j=1 step 1 until"..cols..": "..i*n.distance.."*1u*up rotated (j*360/"..cols..") --endfor cycle "..n.layerline.." withcolor \\MPcolor {"..n.layercolor.."};") end end function m.radar.line(i, line) local n=m.radar.settings local finalcolor=m.decidecolor(i, n.linecolor, n.linepalette) return "pickup pencircle scaled "..n.linewidth.." pt; draw"..line.." withcolor \\MPcolor {"..finalcolor.."};" end function m.radar.fill(i, line) local n=m.radar.settings local finalcolor=m.decidecolor(i, n.fillcolor, n.fillpalette) return "fill"..line.." withcolor \\MPcolor {"..finalcolor.."} withtransparency (1, "..n.filltransparency..");" end function m.radar.dots(i, j, val) local d,n=documentdata.statcharts,m.radar.settings local cols=#d.data[1] local n=m.radar.settings local finalcolor=m.decidecolor(i, n.dotscolor, n.dotspalette) local dot="(0,"..val/n.step*n.distance.."u) rotated -(("..j.."-1)*360/"..cols..")" return "pickup pencircle scaled "..n.dotswidth.." pt; drawdot"..dot.." withcolor \\MPcolor {"..finalcolor.."};" end function m.radar.decimals() local d,n=documentdata.statcharts,m.radar.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=0, 0, 0 if n.dotslabels == "yes" and n.decimalzero == "yes" then for i=1, rows do for j=1, cols do local val=d.data[i][j] if val*10%10 ~= 0 then dec=1 if val*100%10 ~= 0 then dec2=1 end if val*1000%10 ~= 0 then dec3=1 break end end end end end return dec, dec2, dec3 end function m.radar.layerslabels() local lab=0 local n=m.radar.settings if n.decimalzero == "yes" then local dec, dec2, dec3=0, 0, 0 for i=1, n.layers do lab=n.step*i if lab*10%10 ~= 0 then dec=1 if lab*100%10 ~= 0 then dec2=1 end if lab*1000%10 ~= 0 then dec3=1 break end end end for i=1, n.layers do lab=n.step*i if n.decimals then local decim=m.decim(n.decimals) lab=string.format("%0."..decim.."f", math.round(lab/n.decimals)*n.decimals) else if dec3 == 1 then lab=string.format("%0.3f", math.round(lab*1000)/1000) elseif dec2 == 1 then lab=string.format("%0.2f", math.round(lab*100)/100) elseif dec == 1 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end ctx("label.ulft (btex \\layerslabels{"..lab.."} etex, (0,"..i*n.distance.." cm));") end else for i=1, n.layers do lab=n.step*i if n.decimals then lab=math.round(lab/n.decimals)*n.decimals if lab%1 == 0 then lab=math.round(lab) end else if lab*1000%10 ~= 0 then lab=math.round(lab*1000)/1000 elseif lab*100%10 ~= 0 then lab=math.round(lab*100)/100 elseif lab*10%10 ~= 0 then lab=math.round(lab*10)/10 else lab=math.round(lab) end end ctx("label.ulft (btex \\layerslabels{"..lab.."} etex, (0,"..i*n.distance.." cm));") end end end function m.radar.axes() local d,n=documentdata.statcharts,m.radar.settings local cols=#d.data[1] for i=1, cols do ctx("pickup pencircle scaled "..n.axiswidth.." pt; draw (0, 0)--(0, "..n.layers*n.distance.."u) rotated -(("..i.."-1)*360/"..cols..") "..n.axisline.." withcolor \\MPcolor {"..n.axiscolor.."};") end end ------------------------------------------------------------------------------------------------ SCATTER m.scatter={} m.scatter.basic={} m.scatter.smoothlines={} m.scatter.straightlines={} function m.scatter.default() return { xcoor="no", xaxislabinit=1, xaxislabinc=1, } end function m.scatter.processvals(keyvals, keyvalsdata) m.scatter.settings=set_hash_values(m.root.settings) m.scatter.settings=set_hash_values(m.scatter.default(), m.scatter.settings) m.scatter.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.scatter.settings) if m.scatter.settings.gridline == "dashed" then m.scatter.settings.gridline="dashed evenly" elseif m.scatter.settings.gridline == "full" then m.scatter.settings.gridline="" else m.scatter.settings.gridline="dashed withdots" end if m.scatter.settings.xcoor == "yes" then m.scatter.settings.left, m.scatter.settings.distance=1,1 end documentdata.statcharts=r.readdata(keyvalsdata) end function m.scatter.all() local d,n=documentdata.statcharts,m.scatter.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then thirddata.statcharts.subtype="basic" end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.scatter.changeaxeslength()) if n.grid == "on" then ctx(m.scatter.grid()) end m.scatter[thirddata.statcharts.subtype].main() ctx(m.scatter.axes()) if n.xaxislabels == "yes" then ctx(m.scatter.xaxislabels()) end if n.yaxislabels == "yes" then ctx(m.yaxislabels()) end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.scatter.basic.main() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.scatter.decimals() if n.xcoor == "no" then for i=1, rows do for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale ctx(m.scatter.dots(i, main, val)) if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end elseif n.xcoor == "yes" then local count=0 for i=2, rows, 2 do count=count+1 for j=1, cols do local main=d.data[i-1][j]*n.xscale local val=d.data[i][j]*n.yscale ctx(m.scatter.dots(count, main, val)) if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end end function m.scatter.smoothlines.main() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.scatter.decimals() if n.xcoor == "no" then for i=1, rows do line="" for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale line=line.."("..main.."u,"..val.."u)" if j < cols then line=line..".." end end local finalcolor=m.decidecolor.scatter(i, n.linecolor, n.linepalette) ctx("pickup pencircle scaled"..n.linewidth.."pt; draw"..line.." withcolor \\MPcolor{"..finalcolor.."};") for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale if n.dots == "yes" then ctx(m.scatter.dots(i, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end elseif n.xcoor == "yes" then local count=0 for i=2, rows, 2 do line="" count=count+1 for j=1, cols do local main=d.data[i-1][j]*n.xscale local val=d.data[i][j]*n.yscale line=line.."("..main.."u,"..val.."u)" if j < cols then line=line..".." end end local finalcolor=m.decidecolor(count, n.linecolor, n.linepalette) ctx("pickup pencircle scaled"..n.linewidth.."pt; draw"..line.." withcolor \\MPcolor{"..finalcolor.."};") for j=1, cols do local main=d.data[i-1][j]*n.xscale local val=d.data[i][j]*n.yscale if n.dots == "yes" then ctx(m.scatter.dots(count, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end end function m.scatter.straightlines.main() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=m.scatter.decimals() if n.xcoor == "no" then for i=1, rows do for j=1, cols do local main=(n.left+(j-1)*n.distance)*n.xscale local val=d.data[i][j]*n.yscale if j < cols then local nextval=d.data[i][j+1]*n.yscale local nextmain=main+n.distance*n.xscale ctx(m.scatter.line(i, main, val, nextval, nextmain)) end if n.dots == "yes" then ctx(m.scatter.dots(i, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end elseif n.xcoor == "yes" then local count=0 for i=2, rows, 2 do count=count+1 for j=1, cols do local main=d.data[i-1][j]*n.xscale local val=d.data[i][j]*n.yscale if j < cols then local nextval=d.data[i][j+1]*n.yscale local nextmain=d.data[i-1][j+1]*n.xscale ctx(m.scatter.line(count, main, val, nextval, nextmain)) end if n.dots == "yes" then ctx(m.scatter.dots(count, main, val)) end if n.dotslabels == "yes" then ctx(m.dotslabels(main, val, dec, dec2, dec3)) end end end end end function m.scatter.changeaxeslength() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for i=1, rows do for j=1, cols do if d.data[i][j]*n.yscale > minylength then minylength=d.data[i][j]*n.yscale end end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength+1*n.yscale end if n.xcoor == "yes" then local maxxcoor=0 for i=1, rows, 2 do for j=1, cols do if maxxcoor < d.data[i][j] then maxxcoor=d.data[i][j] end end end minxlength=maxxcoor*n.xscale else minxlength=(n.left+(cols-1)*n.distance)*n.xscale end if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.scatter.line(i, x, y, nexty, nextx) local n=m.scatter.settings local finalcolor=m.decidecolor(i, n.linecolor, n.linepalette) return "pickup pencircle scaled "..n.linewidth.."pt; draw("..x.."u,"..y.."u)--("..nextx.."u,"..nexty.."u) withcolor \\MPcolor{"..finalcolor.."};" end function m.scatter.dots(i, x, y) local n=m.scatter.settings local finalcolor=m.decidecolor(i, n.dotscolor, n.dotspalette) return "pickup pencircle scaled "..n.dotswidth.."pt; drawdot ("..x.."u,"..y.."u) withcolor \\MPcolor{"..finalcolor.."};" end function m.scatter.decimals() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local dec, dec2, dec3=0, 0, 0 if n.dotslabels == "yes" and n.decimalzero == "yes" then if n.xcoor == "no" then for i=1, rows do for j=1, cols do local val=d.data[i][j] if val*10%10 ~= 0 then dec=1 if val*100%10 ~= 0 then dec2=1 end if val*1000%10 ~= 0 then dec3=1 break end end end end elseif n.xcoor == "yes" then for i=2, rows, 2 do for j=1, cols do local val=d.data[i][j] if val*10%10 ~= 0 then dec=1 if val*100%10 ~= 0 then dec2=1 end if val*1000%10 ~= 0 then dec3=1 break end end end end end end return dec, dec2, dec3 end function m.scatter.axes() local n=m.scatter.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.scatter.xaxislabels() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local lab, count=0, 0 if n.xcoor == "yes" then if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 else local maxxcoor=0 for i=1, rows, 2 do for j=1, cols do if maxxcoor < d.data[i][j] then maxxcoor=d.data[i][j] end end end count=math.round(maxxcoor) end for i=1, count do local x=(n.left+(i-1)*n.distance)*n.xscale lab=math.round(n.xaxislabinit+(i-1)*n.xaxislabinc) if x <= tonumber(n.xlength) then if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end else if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 else count=cols end for i=1, count do if #d.xlabels == 1 and d.xlabels[1] == "" then lab=i else if d.xlabels[i] then lab=d.xlabels[i] else lab="" end end local x=(n.left+(i-1)*n.distance)*n.xscale if x <= tonumber(n.xlength) then if tonumber(n.xgridlinesdensity) < 1 then if i*n.xgridlinesdensity%1 == 0 then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end else ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end end end function m.scatter.grid() local d,n=documentdata.statcharts,m.scatter.settings local rows, cols=#d.data, #d.data[1] local count=0 if n.xgridlines == "yes" then if n.xgridlinesnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale)*n.xgridlinesdensity)+1 else if n.xcoor == "yes" then local maxxcoor=0 for i=1, rows, 2 do for j=1, cols do if maxxcoor < d.data[i][j] then maxxcoor=d.data[i][j] end end end count=math.round(maxxcoor*n.xgridlinesdensity) elseif n.xcoor == "no" then count=math.round(cols*n.xgridlinesdensity) end if tonumber(n.xgridlinesdensity) > 1 then count=count-(n.xgridlinesdensity-1) end end for i=1, count do -- local main if tonumber(n.xgridlinesdensity) > 1 then main=((n.left+(i-1)*n.distance/n.xgridlinesdensity))*n.xscale else iter=i/n.xgridlinesdensity main=((n.left+(iter-1)*n.distance))*n.xscale end if main > 0 and main <= tonumber(n.xlength) then ctx(m.xgridlines(main, n)) end end if n.xgridlinesleft == "yes" then local leftcount=n.left*n.xgridlinesdensity/n.distance for i=1, leftcount do local main=((n.left-i*n.distance/n.xgridlinesdensity)*n.xscale) if main > 0 then ctx(m.xgridlines(main, n)) end end end end if n.ygridlines == "yes" then local xcount=math.floor(n.ylength)*n.ygridlinesdensity for i=1, xcount do local main=i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end end end ------------------------------------------------------------------------------------------------ STOCK m.stock={} function m.stock.default() return { rightlinecolor="black", rightlinewidth=2, rightlinelength=0.2, rectanglewidth=1, ogtcrectcolor="black", oltcrectcolor="white", ocrecttransparency=1, ocrectcontour="yes", ocrectcontourcolor="black", ocrectcontourwidth=0.5, vrectcolor="gray", vrecttransparency=1, vrectcontour="yes", vrectcontourcolor="black", vrectcontourwidth=0.5, } end function m.stock.processvals(keyvals, keyvalsdata) m.stock.settings=set_hash_values(m.root.settings) m.stock.settings=set_hash_values(m.stock.default(), m.stock.settings) m.stock.settings=set_hash_values(utilities.parsers.settings_to_hash(keyvals), m.stock.settings) if m.stock.settings.gridline == "dashed" then m.stock.settings.gridline="dashed evenly" elseif m.stock.settings.gridline == "full" then m.stock.settings.gridline="" else m.stock.settings.gridline="dashed withdots" end documentdata.statcharts=r.readdata(keyvalsdata) end function m.stock.all() local d,n=documentdata.statcharts,m.stock.settings if not thirddata.statcharts.subtype or thirddata.statcharts.subtype == "" then ctx("\\errmessage{Missing subtype.}") inspect("\\errmessage{Missing subtype.}") os.exit() end ctx.startMPcode() ctx("save u; u="..n.unit..";") ctx(m.stock.changeaxeslength()) if n.grid == "on" then ctx(m.stock.grid()) end m.stock[thirddata.statcharts.subtype]() ctx(m.stock.axes()) if n.xaxislabels == "yes" then ctx(m.stock.xaxislabels()) end if n.yaxislabels == "yes" then ctx(m.yaxislabels()) end if n.axesunits == "yes" then ctx(m.axesunits()) end ctx.stopMPcode() end function m.stock.hlc() local d,n=documentdata.statcharts,m.stock.settings local rows=#d.data local q=1 -- position (for hlc) for i=1, rows do local main=(n.left+(i-1)*n.distance)*n.xscale ctx(m.stock.line(i, main, q)) ctx(m.stock.rightline(i, main, q)) end end function m.stock.ohlc() local d,n=documentdata.statcharts,m.stock.settings local rows=#d.data local q=2 -- position (for ohlc) local color="" for i=1, rows do local main=(n.left+(i-1)*(n.rectanglewidth+n.distance))*n.xscale ctx(m.stock.line(i, main, q)) if d.data[i][1] > d.data[i][4] then color=n.ogtcrectcolor else color=n.oltcrectcolor end ctx(m.stock.ocrectangle(i, main, q, color)) end end function m.stock.vhlc() local d,n=documentdata.statcharts,m.stock.settings local rows=#d.data local q=2 -- position (for vhlc) for i=1, rows do local main=(n.left+(i-1)*(n.rectanglewidth+n.distance))*n.xscale ctx(m.stock.vrectangle(i, main, q)) ctx(m.stock.line(i, main, q)) ctx(m.stock.rightline(i, main, q)) end end function m.stock.vohlc() local d,n=documentdata.statcharts,m.stock.settings local rows=#d.data for i=1, rows do local q=2 -- position (for v) local main=(n.left+(i-1)*(n.rectanglewidth+n.distance))*n.xscale ctx(m.stock.vrectangle(i, main, q)) q=3 -- position (for ohlc) ctx(m.stock.line(i, main, q)) if d.data[i][2] > d.data[i][5] then color=n.ogtcrectcolor else color=n.oltcrectcolor end ctx(m.stock.ocrectangle(i, main, q, color)) end end function m.stock.changeaxeslength() local d,n=documentdata.statcharts,m.stock.settings local rows, cols=#d.data, #d.data[1] local minxlength, minylength=0, 0 for i=1, rows do for j=1, cols do if d.data[i][j]*n.yscale > minylength then minylength=d.data[i][j]*n.yscale end end end if not n.ylength or n.ylength == "" or tonumber(n.ylength) < minylength then n.ylength=minylength+1*n.yscale end if thirddata.statcharts.subtype == "hlc" then minxlength=(n.left+(rows-1)*n.distance)*n.xscale else minxlength=(n.left+rows*n.rectanglewidth+(rows-1)*n.distance)*n.xscale end if not n.xlength or n.xlength == "" or minxlength > tonumber(n.xlength) then n.xlength=minxlength+n.left*n.xscale end thirddata.statcharts.minxlength=minxlength end function m.stock.line(i, main, q) local d,n=documentdata.statcharts,m.stock.settings if thirddata.statcharts.subtype == "hlc" then return "pickup pencircle scaled "..n.linewidth.."pt; draw ("..main.."u," ..d.data[i][q]*n.yscale.."u)--("..main.."u," ..d.data[i][q+1]*n.yscale.."u ) withcolor \\MPcolor{"..n.linecolor.."};" else return "pickup pencircle scaled "..n.linewidth.."pt; draw ("..(main+n.rectanglewidth*n.xscale/2).."u," ..d.data[i][q]*n.yscale.."u)--("..(main+n.rectanglewidth*n.xscale/2).."u," ..d.data[i][q+1]*n.yscale.."u ) withcolor \\MPcolor{"..n.linecolor.."};" end end function m.stock.rightline(i, main, q) local d,n=documentdata.statcharts,m.stock.settings if thirddata.statcharts.subtype == "hlc" then return "pickup pencircle scaled "..n.rightlinewidth.."pt; draw ("..main.."u, "..d.data[i][q+2]*n.yscale.."u)--("..main+n.rightlinelength.."u, "..d.data[i][q+2]*n.yscale.."u);" else return "pickup pencircle scaled "..n.rightlinewidth.."pt; draw ("..(main+n.rectanglewidth*n.xscale/2).."u, "..d.data[i][q+2]*n.yscale.."u)--("..(main+n.rectanglewidth*n.xscale/2)+n.rightlinelength.."u, "..d.data[i][q+2]*n.yscale.."u);" end end function m.stock.ocrectangle(i, main, q, color) local d,n=documentdata.statcharts,m.stock.settings string="" string="path p; p=("..main.."u, "..d.data[i][q-1]*n.yscale.."u)--("..(main+n.rectanglewidth*n.xscale).."u, "..d.data[i][q-1]*n.yscale.."u)--("..(main+n.rectanglewidth*n.xscale).."u, "..d.data[i][q+2]*n.yscale.."u)--("..main.."u, "..d.data[i][q+2]*n.yscale.."u)--cycle;" if n.ocrectcontour == "yes" then string=string.."pickup pencircle scaled "..n.ocrectcontourwidth.."pt; draw p withcolor \\MPcolor{"..n.ocrectcontourcolor.."};" end string=string.."fill p withcolor \\MPcolor{"..color.."} withtransparency (1, "..n.ocrecttransparency..");" return string end function m.stock.vrectangle(i, main, q) local d,n=documentdata.statcharts,m.stock.settings string="" string="path p; p=("..main.."u, 0)--("..main.."u, "..d.data[i][q-1]*n.yscale.."u)--("..(main+n.rectanglewidth*n.xscale).."u, "..d.data[i][q-1]*n.yscale.."u)--("..(main+n.rectanglewidth*n.xscale).."u, 0)--cycle;" if n.vrectcontour == "yes" then string=string.."pickup pencircle scaled "..n.vrectcontourwidth.."pt; draw p withcolor \\MPcolor{"..n.vrectcontourcolor.."};" end string=string.."fill p withcolor \\MPcolor{"..n.vrectcolor.."} withtransparency (1, "..n.vrecttransparency..");" return string end function m.stock.axes() local n=m.stock.settings return "pickup pencircle scaled "..n.ywidth.." pt; draw (0,"..n.yshift.." u)--(0,"..n.ylength.." u); pickup pencircle scaled "..n.xwidth.." pt; draw ("..n.xshift.." u,0)--("..n.xlength.." u,0);" end function m.stock.xaxislabels() local d,n=documentdata.statcharts,m.stock.settings local rows=#d.data local lab, count=0, 0 if n.xaxislabelsnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then if thirddata.statcharts.subtype == "hlc" then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 elseif thirddata.statcharts.subtype == "ohlc" or thirddata.statcharts.subtype == "vhlc" or thirddata.statcharts.subtype == "vohlc" then count=math.round((n.xlength-(n.left*n.xscale))/((n.rectanglewidth+n.distance)*n.xscale))+1 end else count=rows end for i=1, count do if #d.xlabels == 1 and d.xlabels[1] == "" then lab=i else if d.xlabels[i] then lab=d.xlabels[i] else lab="" end end if thirddata.statcharts.subtype == "hlc" then x=(n.left+(i-1)*n.distance)*n.xscale elseif thirddata.statcharts.subtype == "ohlc" or thirddata.statcharts.subtype == "vhlc" or thirddata.statcharts.subtype == "vohlc" then x=(n.left+n.rectanglewidth/2+(i-1)*(n.rectanglewidth+n.distance))*n.xscale end if x <= tonumber(n.xlength) then ctx("label.bot (btex \\xaxislabels{"..lab.."} etex, ("..x.."u, 0));") end end end function m.stock.grid() local d,n=documentdata.statcharts,m.stock.settings local rows=#d.data local count=0 if n.xgridlines == "yes" then if thirddata.statcharts.subtype == "hlc" then if n.xgridlinesnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/(n.distance*n.xscale))+1 else count=rows end for i=1, count do local main=(n.left+(i-1)*n.distance)*n.xscale if main > 0 and main <= tonumber(n.xlength) then ctx(m.xgridlines(main, n)) end end elseif thirddata.statcharts.subtype == "ohlc" or thirddata.statcharts.subtype == "vhlc" or thirddata.statcharts.subtype == "vohlc" then if n.xgridlinesnoval == "yes" and tonumber(n.xlength) > thirddata.statcharts.minxlength+n.left*n.xscale then count=math.round((n.xlength-(n.left*n.xscale))/((n.distance+n.rectanglewidth)*n.xscale))+1 else count=rows end for i=1, count do local main=(n.left+n.rectanglewidth/2+(i-1)*(n.rectanglewidth+n.distance))*n.xscale if main > 0 and main <= tonumber(n.xlength) then ctx(m.xgridlines(main, n)) end end end end if n.ygridlines == "yes" then local xcount=math.floor(n.ylength)*n.ygridlinesdensity for i=1,xcount do local main=i/n.ygridlinesdensity ctx(m.ygridlines(main, n)) end end end ------------------------------------------------------------------------------------------------ function m.showpalette(name) local p = m.palette[name] or {} if not p then for i=1,#p do ctx("\\showpalettecolor["..i.."]") end end end function m.showpalettes() local p = m.palette[name] or {} for pn,pv in pairs(p) do ctx("\\showpalette["..pn.."]") end end