local p=
function pick(a,n) return a[n+1]end
function loadColorSet(page) if not(page) then page="" end if mw.ustring.sub(page,1,7) ~= "Module:" then page="Module:Chart/Default colors" end local ct=mw.loadData(page) if not ct then ct=mw.loadData("Module:Chart/Default colors") end local x=0 local color= local name= repeat x=x+1 local n=ct[x*2-1] local c=ct[x*2] if not (n and c) then break end table.insert(color,c) table.insert(name,n) until false return color, nameend function piechartslice(color,percent,radius,link) radius=radius or 100 local quadrant=math.floor(percent/25) local sin=math.floor(radius*math.sin(percent*math.pi/50)) local cos=math.floor(radius*math.cos(percent*math.pi/50)) local tan25=math.floor(-1*radius*math.cos(percent*math.pi/50)/math.sin(percent*math.pi/50)) local output,lr,lrv,tv,bw1,bw2,bw3,bw4,bd,lrB,bw2B local a= -- throwaway array to make value matrix more apparent -- quadrant 1 is upper left, quadrant 2 is lower left lr=pick(quadrant) lrv=pick(quadrant) tv=pick(quadrant) -- border width:bw1 (top) bw2 (right) bw3 (bottom) bw4 (left) bw1=pick(quadrant) bw2=pick(quadrant) bw3=pick(quadrant) bw4=pick(quadrant) bd=pick(quadrant) lrB=pick(quadrant) -- right border for second div (the bottom border is radius and others are zero) bw2B=pick(quadrant)
local output='
' if quadrant
2 or quadrant
' if quadrant
' end end return outputend function p.piechart(frame) local parent=frame.getParent(frame) or local color=loadColorSet(frame.args.colorset or parent.args.colorset) or local value= local label= local link= local slicecount=0 local thumb,nowiki,radius if parent.args then thumb=parent.args.thumb nowik=parent.args.nowiki radius=parent.args.radius end thumb=frame.args.thumb or thumb nowiki=frame.args.nowiki or nowiki radius=frame.args.radius or radius or 100 radius=tonumber(radius) if radius<1 then radius=100 end if not(thumb) then thumb="right" end if not(mw.ustring.match(thumb,"%S")) then thumb="right" end for i,j in pairs(parent.args or) do -- I should look up if there's a way to union parent.args AND frame.args local k=tonumber(mw.ustring.match(i,"color(%d*)")) if k then color[k]=j else k=tonumber(mw.ustring.match(i,"value(%d*)")) if k then value[k]=tonumber(j) if k>slicecount then slicecount=k end -- not using #value to avoid randomness if some values are left out else k=tonumber(mw.ustring.match(i,"label(%d*)")) if k then label[k]=j end end end end --- innermost absolute div around circle, then a second thumbcaption div around legend. Note (/div)(div) at core between circle and legend. The rest are accreted around this center. output='
' for i,j in pairs(frame.args or) do -- supersede parent.args values local k=tonumber(mw.ustring.match(i,"color(%d*)")) if k then color[k]=j or "" else k=tonumber(mw.ustring.match(i,"value(%d*)")) if k then value[k]=tonumber(j) if k>slicecount then slicecount=k end -- not using #value to avoid randomness if some values are left out else k=tonumber(mw.ustring.match(i,"label(%d*)")) if k then label[k]=j or "" else k=tonumber(mw.ustring.match(i,"link(%d*)")) if k then link[k]=j or "" end end end end end local valuesum=0 -- sum of all slices local imgmap="" -- beginning of a polygon specification for
\n
' if #link
'..output..'
' output=mw.ustring.gsub(output,"
<nowiki>"..output.."</nowiki>") else return frame.preprocess(frame,output) endend function p.main(frame) local args=frame.args local parent=frame.getParent(frame) local pargs=parent.args or local icon=args.icon or pargs.icon local iconradius=args.iconradius or pargs.iconradius or 10 local lineicon=args.lineicon or pargs.lineicon or "•" local lineiconradius=args.lineiconradius or pargs.lineiconradius or 5 local linefix=iconradius-lineiconradius local plotsizex = args.plotsizex or pargs.plotsizex or 100 local plotsizey = args.plotsizey or pargs.plotsizey or 100 local plotstep = args.plotstep or pargs.plotstep or 10 local output = .. plotsizex+(2*iconradius) .. .. plotsizey+(2*iconradius) .. px;"> if (args[2] or pargs[2]) ~= nil then local x=(args[1] or pargs[1])+0 local y=(args[2] or pargs[2])+0 local xmin = x local xmax = x local ymin = y local ymax = y local index = 3 while (args[index+1] or pargs[index+1]) ~= nil do local x=(args[index]+0 or pargs[index]+0) local y=(args[index+1]+0 or pargs[index+1]+0) if (x < xmin) then xmin = x end if (x > xmax) then xmax = x end if (y < ymin) then ymin = y end if (y > ymax) then ymax = y end index = index + 2 end local lastx=0 local lasty=0 if args[2] ~= nil then local x=(args[1] or pargs[1])+0 local y=(args[2] or pargs[2])+0 local plotx=math.floor(plotsizex*(x-xmin)/(xmax-xmin)) local ploty=math.floor((plotsizey-plotsizey*(y-ymin)/(ymax-ymin))) output = output .. .. plotx .. .. ploty .. px;"> .. icon .. "" lastx = plotx lasty = ploty end index = 3 while (args[index+1] or pargs[index+1]) ~= nil do local x=(args[index] or pargs[index])+0 local y=(args[index+1] or pargs[index+1])+0 local plotx=math.floor(plotsizex*(x-xmin)/(xmax-xmin)) local ploty=math.floor((plotsizey-plotsizey*(y-ymin)/(ymax-ymin))) if plotstep+0 ~= 0 then local delx=plotx-lastx local dely=ploty-lasty plotdist=math.sqrt(delx*delx+dely*dely) plotparm=plotdist-iconradius-plotstep/2 while plotparm>iconradius+lineiconradius+plotstep/2 do output = output .. .. lastx+linefix+math.floor(delx*(plotparm/plotdist)) .. .. lasty+linefix+math.floor(dely*(plotparm/plotdist)) .. px;"> .. lineicon .. "" plotparm = plotparm - plotstep end lastx = plotx lasty = ploty end output = output .. .. plotx .. .. ploty .. px;"> .. icon .. "" index = index + 2 end else output = "error" end output = output .. "
" return outputend
-- data structure is-- data[y][x].value-- maxyval[y]-- data[y].color-- data[y].legend-- data.legend[x]
function p.bar(frame) local debuglog="" local args=frame.args local parent=frame.getParent(frame) local pargs=parent.args or local delimiter = args.delimiter or pargs.delimiter or "," local width = args.width or pargs.width or 200 local height = args.height or pargs.height or 200 ---- Set up the table of "norms". Series 1 to N normalize to (%d+) local normalize = args.normalize or pargs.normalize or "" local prowl=mw.ustring.gmatch(normalize,"(%d+)") norm= local ngroup= -- ngroup[yseries] identifies an index for ymax local nngroup=0 -- the current maximum ngroup assigned repeat local t=prowl if not(t) then break end t=tonumber(t) table.insert(norm,t) until false --- import the actual data in group1 .. groupN local yseries=0;local x=0 local data= -- main data storage array local maxy=0;local maxx=0; local maxyval=; local minyval= -- keeping these out of the data array after being driven half mad giving them cutesy names in the array! repeat yseries=yseries+1 data[yseries]= --- pull in the "groupN" data (delimited) --> text local text=args["group"..yseries] -- each _group_ is a group of x-values in a y-series if not (text) then maxy=yseries-1 break end ---- pull in the originN=some number data[yseries].origin=args["origin"..yseries] or 0 data[yseries].origin=tonumber(data[yseries].origin) data[yseries].max=data[yseries].origin;data[yseries].min=data[yseries].origin debuglog=debuglog.."I"..yseries..tostring(norm[yseries]) --- set ngroup[yseries] to whatever its norm points at, or new if norm[yseries] then if ngroup[norm[yseries]] then ngroup[yseries]=ngroup[norm[yseries]] else nngroup=nngroup+1 ngroup[yseries]=nngroup end else ngroup[yseries]=1 -- if no norm specified, just dump to the first series group end ---- pull in the actual values prowl=mw.ustring.gmatch(text,"([^" .. delimiter .. "]+)") x=0 repeat x=x+1 data[yseries][x]= data[yseries][x].value=prowl debuglog=debuglog.."V"..x..yseries..tostring(data[yseries][x].value) if not(data[yseries][x].value) then if x>maxx then maxx = x-1 end; break end data[yseries][x].value=tonumber(data[yseries][x].value) if data[yseries].max then if data[yseries][x].value>data[yseries].max then data[yseries].max=data[yseries][x].value end else data[yseries].max=data[yseries][x].value end if data[yseries].min then if data[yseries][x].value
until false --- Draw the output local output = .. width .. .. height .. px;"> local output=' ' local topreserve=20*(maxy) local bottomreserve=20 local leftreserve=20 local rightreserve=20 local reducedheight=height-topreserve-bottomreserve local reducedwidth=width-leftreserve-rightreserve local ew=math.floor(reducedwidth/((maxx)*(maxy+1))) for y = 1,maxy do for x = 1, maxx do debuglog=debuglog..y..x..tostring(ngroup[y])..tostring(data[y][x]) .. tostring(maxyval[ngroup[y]])..tostring(minyval[ngroup[y]]) if data[y][x] and maxyval[ngroup[y]] then local pw=(data[y][x].value-data[y].origin)/(maxyval[ngroup[y]]-minyval[ngroup[y]]) -- proportion of value to the max value for that y-series local po=(data[y].origin-minyval[ngroup[y]])/(maxyval[ngroup[y]]-minyval[ngroup[y]]) local eh=math.floor(pw*reducedheight) local et=topreserve+math.floor(reducedheight - eh - po*reducedheight) if eh<0 then eh=-1*eh;et=et-eh end -- pw can be negative; plot "backwards" looks the same local el=leftreserve+math.floor(((x-1)*(maxy+1) + (y-1) + 0.5)*ew) output=output..' ' end -- if data[y][x] and maxval[ngroup[y]] end -- for x = 1, maxx end -- for y=1,maxy ---- draw the ylegends for x = 1,maxx do output=output .. ' \n" if (args.debug or pargs.debug) then output=output..debuglog end return outputend return p"" then data[yseries].color="black" end until false --- import the xlegends for each group prowl=mw.ustring.gmatch(args.xlegend,"[^" .. delimiter .. "]+") x=0 data.legend= -- for x legends, y="legend" repeat x=x+1 data.legend[x]=prowl if not (data.legend[x]) then break end data.legend[x]=data.legend[x] until false --- import the ylegends for each group prowl=mw.ustring.gmatch(args.ylegend,"[^" .. delimiter .. "]+") yseries=0 repeat yseries=yseries+1 data[yseries].legend=prowl until not (data[yseries].legend) -- set the maxval[ngroup[(each series)]] = data[(any series in ngroup).max
yseries=0
repeat
yseries=yseries+1
if not(data[yseries].max) then break end debuglog=debuglog..tostring(yseries)..":"..tostring(ngroup[yseries]) .. ">"..tostring(data[yseries].max) if maxyval[ngroup[yseries]] then if data[yseries].max>maxyval[ngroup[yseries]] then maxyval[ngroup[yseries]]=data[yseries].max end else maxyval[ngroup[yseries]]=data[yseries].max;debuglog=debuglog.."A"..tostring(data[yseries].max)..tostring(data[yseries].min) end if minyval[ngroup[yseries]] then if data[yseries].min
1 then debuglog=debuglog.."left";output=output .. '
'.. j .. '' else debuglog=debuglog.."right";output=output .. ''.. j .. '' end end end debuglog=debuglog..tostring(maxyval[1])..tostring(maxyval[2])..tostring(maxyval[3])..tostring(data[1].max)..tostring(data[2].max)..tostring(data[3].max)..tostring(minyval[1])..tostring(minyval[2])..tostring(minyval[3])..tostring(data[1].min)..tostring(data[2].min)..tostring(data[3].min)..data.legend[1]..data.legend[2]..data.legend[3] output = output .. "