<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FWnt%2FPlotter</id>
	<title>Module:Sandbox/Wnt/Plotter - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ASandbox%2FWnt%2FPlotter"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Wnt/Plotter&amp;action=history"/>
	<updated>2026-05-28T00:01:00Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Sandbox/Wnt/Plotter&amp;diff=146422&amp;oldid=prev</id>
		<title>imported&gt;Pppery: Pppery moved page Module:Plotter to Module:Sandbox/Wnt/Plotter without leaving a redirect: Userfying module take 2</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Sandbox/Wnt/Plotter&amp;diff=146422&amp;oldid=prev"/>
		<updated>2020-10-04T00:54:14Z</updated>

		<summary type="html">&lt;p&gt;Pppery moved page &lt;a href=&quot;/index.php?title=Module:Plotter&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Module:Plotter (page does not exist)&quot;&gt;Module:Plotter&lt;/a&gt; to &lt;a href=&quot;/research/Module:Sandbox/Wnt/Plotter&quot; title=&quot;Module:Sandbox/Wnt/Plotter&quot;&gt;Module:Sandbox/Wnt/Plotter&lt;/a&gt; without leaving a redirect: Userfying module take 2&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p={}&lt;br /&gt;
&lt;br /&gt;
function pick(a,n)&lt;br /&gt;
    return a[n+1]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function loadColorSet(page)&lt;br /&gt;
    if not(page) then page=&amp;quot;&amp;quot; end&lt;br /&gt;
    if mw.ustring.sub(page,1,7) ~= &amp;quot;Module:&amp;quot; then page=&amp;quot;Module:Chart/Default colors&amp;quot; end&lt;br /&gt;
    local ct=mw.loadData(page)&lt;br /&gt;
    if not ct then ct=mw.loadData(&amp;quot;Module:Chart/Default colors&amp;quot;) end&lt;br /&gt;
    local x=0&lt;br /&gt;
    local color={}&lt;br /&gt;
    local name={}&lt;br /&gt;
    repeat&lt;br /&gt;
        x=x+1&lt;br /&gt;
        local n=ct[x*2-1]&lt;br /&gt;
        local c=ct[x*2]&lt;br /&gt;
        if not (n and c) then break end&lt;br /&gt;
        table.insert(color,c)&lt;br /&gt;
        table.insert(name,n)&lt;br /&gt;
    until false&lt;br /&gt;
    return color, name&lt;br /&gt;
end&lt;br /&gt;
    &lt;br /&gt;
function piechartslice(color,percent,radius,link)&lt;br /&gt;
    radius=radius or 100&lt;br /&gt;
    local quadrant=math.floor(percent/25)&lt;br /&gt;
    local sin=math.floor(radius*math.sin(percent*math.pi/50))&lt;br /&gt;
    local cos=math.floor(radius*math.cos(percent*math.pi/50))&lt;br /&gt;
    local tan25=math.floor(-1*radius*math.cos(percent*math.pi/50)/math.sin(percent*math.pi/50))&lt;br /&gt;
    local output,lr,lrv,tv,bw1,bw2,bw3,bw4,bd,lrB,bw2B&lt;br /&gt;
    local a={} -- throwaway array to make value matrix more apparent&lt;br /&gt;
     -- quadrant 1 is upper left, quadrant 2 is lower left&lt;br /&gt;
    lr=pick({&amp;#039;left&amp;#039;,&amp;#039;right&amp;#039;,&amp;#039;right&amp;#039;,&amp;#039;left&amp;#039;,&amp;#039;left&amp;#039;},quadrant)&lt;br /&gt;
    lrv=pick({radius,radius,radius,radius,0},quadrant)&lt;br /&gt;
    tv=pick({radius-sin,0,radius,radius,0},quadrant)&lt;br /&gt;
     -- border width:bw1 (top) bw2 (right) bw3 (bottom) bw4 (left)&lt;br /&gt;
    bw1=pick({0,0,-1*sin,radius,0},quadrant)&lt;br /&gt;
    bw2=pick({0,tan25,-1*cos,0,2*radius},quadrant)&lt;br /&gt;
    bw3=pick({sin,radius,0,0,2*radius},quadrant)&lt;br /&gt;
    bw4=pick({cos,0,0,tan25,0},quadrant)&lt;br /&gt;
    bd=pick({&amp;#039;bottom-&amp;#039;,&amp;#039;right-&amp;#039;,&amp;#039;top-&amp;#039;,&amp;#039;left-&amp;#039;,&amp;#039;&amp;#039;},quadrant)&lt;br /&gt;
    lrB=pick({&amp;#039;n/a&amp;#039;,&amp;#039;right&amp;#039;,&amp;#039;left&amp;#039;,&amp;#039;left&amp;#039;,&amp;#039;n/a&amp;#039;},quadrant)&lt;br /&gt;
     -- right border for second div (the bottom border is radius and others are zero)&lt;br /&gt;
    bw2B=pick({&amp;#039;n/a&amp;#039;,radius,2*radius,2*radius,&amp;#039;n/a&amp;#039;},quadrant)&lt;br /&gt;
&lt;br /&gt;
    local output=&amp;#039;&amp;lt;div style=&amp;quot;border:solid transparent;position:absolute;width:&amp;#039;..radius..&amp;#039;px;line-height:0px;&amp;#039;..lr..&amp;#039;:&amp;#039;..lrv..&amp;#039;px;top:&amp;#039;..tv..&amp;#039;px;border-width:&amp;#039;..bw1..&amp;#039;px &amp;#039;..bw2..&amp;#039;px &amp;#039;..bw3..&amp;#039;px &amp;#039;..bw4..&amp;#039;px;border-&amp;#039;..bd..&amp;#039;color:&amp;#039;..color..&amp;#039;;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
    if quadrant==1 or quadrant==2 or quadrant==3 then&lt;br /&gt;
        output=output..&amp;#039;&amp;lt;div style=&amp;quot;position:absolute;line-height:0px;border-style:solid;&amp;#039;..lrB..&amp;#039;:0px;top:0px;border-width:0px &amp;#039;..bw2B..&amp;#039;px &amp;#039;..radius..&amp;#039;px 0px;border-color:&amp;#039;..color..&amp;#039;;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
        if quadrant==3 then&lt;br /&gt;
            output=output.. &amp;#039;&amp;lt;div style=&amp;quot;position:absolute;line-height:0px;border-style:solid;left:0px;top:0px;border-width:0px &amp;#039;..radius..&amp;#039;px &amp;#039;..2*radius..&amp;#039;px 0px;border-color:&amp;#039;..color..&amp;#039;;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return output&lt;br /&gt;
end&lt;br /&gt;
    &lt;br /&gt;
function p.piechart(frame)&lt;br /&gt;
    local parent=frame.getParent(frame) or {}&lt;br /&gt;
    local color=loadColorSet(frame.args.colorset or parent.args.colorset) or {&amp;#039;red&amp;#039;,&amp;#039;green&amp;#039;,&amp;#039;blue&amp;#039;,&amp;#039;yellow&amp;#039;,&amp;#039;fuchsia&amp;#039;,&amp;#039;aqua&amp;#039;,&amp;#039;brown&amp;#039;,&amp;#039;orange&amp;#039;,&amp;#039;purple&amp;#039;,&amp;#039;sienna&amp;#039;}&lt;br /&gt;
    local value={}&lt;br /&gt;
    local label={}&lt;br /&gt;
    local link={}&lt;br /&gt;
    local slicecount=0&lt;br /&gt;
    local thumb,nowiki,radius&lt;br /&gt;
    if parent.args then&lt;br /&gt;
        thumb=parent.args.thumb&lt;br /&gt;
        nowik=parent.args.nowiki&lt;br /&gt;
        radius=parent.args.radius&lt;br /&gt;
    end&lt;br /&gt;
    thumb=frame.args.thumb or thumb&lt;br /&gt;
    nowiki=frame.args.nowiki or nowiki&lt;br /&gt;
    radius=frame.args.radius or radius or 100&lt;br /&gt;
    radius=tonumber(radius)&lt;br /&gt;
    if radius&amp;lt;1 then radius=100 end&lt;br /&gt;
    if not(thumb) then thumb=&amp;quot;right&amp;quot; end&lt;br /&gt;
    if not(mw.ustring.match(thumb,&amp;quot;%S&amp;quot;)) then thumb=&amp;quot;right&amp;quot; end&lt;br /&gt;
    for i,j in pairs(parent.args or {}) do -- I should look up if there&amp;#039;s a way to union parent.args AND frame.args&lt;br /&gt;
        local k=tonumber(mw.ustring.match(i,&amp;quot;color(%d*)&amp;quot;))&lt;br /&gt;
        if k then color[k]=j&lt;br /&gt;
        else k=tonumber(mw.ustring.match(i,&amp;quot;value(%d*)&amp;quot;))&lt;br /&gt;
            if k then&lt;br /&gt;
                value[k]=tonumber(j)&lt;br /&gt;
                if k&amp;gt;slicecount then slicecount=k end -- not using #value to avoid randomness if some values are left out&lt;br /&gt;
            else k=tonumber(mw.ustring.match(i,&amp;quot;label(%d*)&amp;quot;))&lt;br /&gt;
                if k then label[k]=j&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
     --- 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.&lt;br /&gt;
    output=&amp;#039;&amp;lt;div style=&amp;quot;position:absolute;left:0;top:0&amp;quot;&amp;gt;[[File:Circle frame.svg|&amp;#039;..(radius*2)..&amp;#039;px|link=]]&amp;lt;Module:Plotter internal imgmap insertion token&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;!-- Legend --&amp;gt; &amp;lt;div class=&amp;quot;thumbcaption&amp;quot;&amp;gt; &amp;#039;&lt;br /&gt;
    for i,j in pairs(frame.args or {}) do -- supersede parent.args values&lt;br /&gt;
        local k=tonumber(mw.ustring.match(i,&amp;quot;color(%d*)&amp;quot;))&lt;br /&gt;
        if k then color[k]=j or &amp;quot;&amp;quot;&lt;br /&gt;
        else k=tonumber(mw.ustring.match(i,&amp;quot;value(%d*)&amp;quot;))&lt;br /&gt;
            if k then&lt;br /&gt;
                value[k]=tonumber(j)&lt;br /&gt;
                if k&amp;gt;slicecount then slicecount=k end -- not using #value to avoid randomness if some values are left out&lt;br /&gt;
            else k=tonumber(mw.ustring.match(i,&amp;quot;label(%d*)&amp;quot;))&lt;br /&gt;
                if k then label[k]=j or &amp;quot;&amp;quot;&lt;br /&gt;
                else k=tonumber(mw.ustring.match(i,&amp;quot;link(%d*)&amp;quot;))&lt;br /&gt;
                    if k then link[k]=j or &amp;quot;&amp;quot;&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    local valuesum=0 -- sum of all slices&lt;br /&gt;
    local imgmap=&amp;quot;&amp;quot; -- beginning of a polygon specification for &amp;lt;imagemap&amp;gt;&lt;br /&gt;
    for slice=1,slicecount do&lt;br /&gt;
        if value[slice] then&lt;br /&gt;
            if link[slice] then&lt;br /&gt;
                 -- center of the circle, NOTE coords are relative to 600 px image before scaling NOT the radius&lt;br /&gt;
                imgmap=imgmap..&amp;quot;poly 300 300&amp;quot; &lt;br /&gt;
                for x=valuesum,valuesum+value[slice] do&lt;br /&gt;
                    local sin=math.floor(300*math.sin(x*math.pi/50))&lt;br /&gt;
                    local cos=math.floor(300*math.cos(x*math.pi/50))&lt;br /&gt;
                    imgmap=imgmap..&amp;quot; &amp;quot;..300+cos..&amp;quot; &amp;quot;..300-sin&lt;br /&gt;
                end&lt;br /&gt;
                imgmap=imgmap..&amp;quot; [[&amp;quot;..link[slice]..&amp;quot;]]\n&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            valuesum=valuesum+value[slice]&lt;br /&gt;
            output=piechartslice(color[slice],valuesum,radius)..output..&amp;quot;{{legend|&amp;quot;..(color[slice] or &amp;quot;&amp;quot;)..&amp;quot;|&amp;quot;..(label[slice] or &amp;quot;&amp;quot;)..&amp;quot; (&amp;quot;..valuesum..&amp;quot;%)}}&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
     --- imagemap has its own absolute div to position with a separate transparent image&lt;br /&gt;
    imgmap=&amp;#039;&amp;lt;div style=&amp;quot;position:absolute;top:0px;left:0px;width:&amp;#039;..2*radius..&amp;#039;px;height:&amp;#039;..2*radius..&amp;#039;px;z-index:1000;&amp;quot;&amp;gt;\n&amp;lt;imagemap&amp;gt;\nFile:transparent600.gif|&amp;#039;..2*radius..&amp;#039;px\n&amp;#039;..imgmap..&amp;#039;desc none\n&amp;lt;/imagemap&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
    if #link==0 then imgmap=&amp;quot;&amp;quot; end -- make sure imgmap is blank if no links&lt;br /&gt;
     --- outer thumb tleft/tright is float/clear left or right&lt;br /&gt;
     --- thumbinner encapsulates the graph&lt;br /&gt;
     --- third relative div container ends in the middle of ..output..&lt;br /&gt;
     --- next third div style &amp;quot;thumbcaption&amp;quot; begins in ..output..&lt;br /&gt;
     --- all three end at end&lt;br /&gt;
    output=&amp;#039;&amp;lt;div class=&amp;quot;thumb t&amp;#039;..thumb..&amp;#039;&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;thumbinner&amp;quot; style=&amp;quot;width:&amp;#039;..2*radius..&amp;#039;px&amp;quot;&amp;gt; &amp;lt;!-- Graph --&amp;gt; &amp;lt;div style=&amp;quot;background-color:white;margin:auto;position:relative;width:&amp;#039;..2*radius..&amp;#039;px;height:&amp;#039;..2*radius..&amp;#039;px;overflow:hidden;&amp;quot;&amp;gt; &amp;#039;..output..&amp;#039;{{legend|white|Other (&amp;#039;..tostring(math.floor((100-valuesum)*1000000)/1000000)..&amp;#039;%)}}&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
    output=mw.ustring.gsub(output,&amp;quot;&amp;lt;Module:Plotter internal imgmap insertion token&amp;gt;&amp;quot;, imgmap)&lt;br /&gt;
    if nowiki then return frame.preprocess(frame,&amp;quot;&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&amp;quot;..output..&amp;quot;&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&amp;quot;) else return frame.preprocess(frame,output) end&lt;br /&gt;
end&lt;br /&gt;
    &lt;br /&gt;
function p.main(frame)&lt;br /&gt;
    local args=frame.args&lt;br /&gt;
    local parent=frame.getParent(frame)&lt;br /&gt;
    local pargs=parent.args or {}&lt;br /&gt;
    local icon=args.icon or pargs.icon&lt;br /&gt;
    local iconradius=args.iconradius or pargs.iconradius or 10&lt;br /&gt;
    local lineicon=args.lineicon or pargs.lineicon or &amp;quot;•&amp;quot;&lt;br /&gt;
    local lineiconradius=args.lineiconradius or pargs.lineiconradius or 5&lt;br /&gt;
    local linefix=iconradius-lineiconradius&lt;br /&gt;
    local plotsizex = args.plotsizex or pargs.plotsizex or 100&lt;br /&gt;
    local plotsizey = args.plotsizey or pargs.plotsizey or 100&lt;br /&gt;
    local plotstep = args.plotstep or pargs.plotstep or 10&lt;br /&gt;
    local output = [[&amp;lt;div style=&amp;quot;position:relative;border-style:solid;border-color: #0077ff;width:]] .. plotsizex+(2*iconradius) .. [[px;height:]] .. plotsizey+(2*iconradius) .. [[px;&amp;quot;&amp;gt;]]&lt;br /&gt;
    if (args[2] or pargs[2]) ~= nil then&lt;br /&gt;
        local x=(args[1] or pargs[1])+0&lt;br /&gt;
        local y=(args[2] or pargs[2])+0&lt;br /&gt;
        local xmin = x&lt;br /&gt;
        local xmax = x&lt;br /&gt;
        local ymin = y&lt;br /&gt;
        local ymax = y&lt;br /&gt;
        local index = 3&lt;br /&gt;
        while (args[index+1] or pargs[index+1]) ~= nil do&lt;br /&gt;
           local x=(args[index]+0 or pargs[index]+0)&lt;br /&gt;
           local y=(args[index+1]+0 or pargs[index+1]+0)&lt;br /&gt;
           if (x &amp;lt; xmin) then xmin = x end&lt;br /&gt;
           if (x &amp;gt; xmax) then xmax = x end&lt;br /&gt;
           if (y &amp;lt; ymin) then ymin = y end&lt;br /&gt;
           if (y &amp;gt; ymax) then ymax = y end&lt;br /&gt;
           index = index + 2&lt;br /&gt;
        end&lt;br /&gt;
        local lastx=0&lt;br /&gt;
        local lasty=0&lt;br /&gt;
        if args[2] ~= nil then&lt;br /&gt;
            local x=(args[1] or pargs[1])+0&lt;br /&gt;
            local y=(args[2] or pargs[2])+0&lt;br /&gt;
            local plotx=math.floor(plotsizex*(x-xmin)/(xmax-xmin))&lt;br /&gt;
            local ploty=math.floor((plotsizey-plotsizey*(y-ymin)/(ymax-ymin)))&lt;br /&gt;
            output = output .. [[&amp;lt;span style=&amp;quot;position:absolute;left:]] .. plotx .. [[px; top:]] .. ploty .. [[px;&amp;quot;&amp;gt;]] .. icon .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
            lastx = plotx&lt;br /&gt;
            lasty = ploty&lt;br /&gt;
        end&lt;br /&gt;
        index = 3&lt;br /&gt;
        while (args[index+1] or pargs[index+1]) ~= nil do&lt;br /&gt;
            local x=(args[index] or pargs[index])+0&lt;br /&gt;
            local y=(args[index+1] or pargs[index+1])+0&lt;br /&gt;
            local plotx=math.floor(plotsizex*(x-xmin)/(xmax-xmin))&lt;br /&gt;
            local ploty=math.floor((plotsizey-plotsizey*(y-ymin)/(ymax-ymin)))&lt;br /&gt;
            if plotstep+0 ~= 0 then&lt;br /&gt;
               local delx=plotx-lastx&lt;br /&gt;
               local dely=ploty-lasty&lt;br /&gt;
               plotdist=math.sqrt(delx*delx+dely*dely)&lt;br /&gt;
               plotparm=plotdist-iconradius-plotstep/2&lt;br /&gt;
               while plotparm&amp;gt;iconradius+lineiconradius+plotstep/2 do&lt;br /&gt;
                  output = output .. [[&amp;lt;span style=&amp;quot;position:absolute;left:]] .. lastx+linefix+math.floor(delx*(plotparm/plotdist)) .. [[px; top:]] .. lasty+linefix+math.floor(dely*(plotparm/plotdist)) .. [[px;&amp;quot;&amp;gt;]] .. lineicon .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
                  plotparm = plotparm - plotstep&lt;br /&gt;
               end&lt;br /&gt;
               lastx = plotx&lt;br /&gt;
               lasty = ploty&lt;br /&gt;
            end&lt;br /&gt;
            output = output .. [[&amp;lt;span style=&amp;quot;position:absolute;left:]] .. plotx .. [[px; top:]] .. ploty .. [[px;&amp;quot;&amp;gt;]] .. icon .. &amp;quot;&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
            index = index + 2&lt;br /&gt;
        end&lt;br /&gt;
    else output = &amp;quot;error&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    output = output .. &amp;quot;&amp;lt;/div&amp;gt;&amp;quot;&lt;br /&gt;
    return output&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- data structure is&lt;br /&gt;
-- data[y][x].value&lt;br /&gt;
-- maxyval[y]&lt;br /&gt;
-- data[y].color&lt;br /&gt;
-- data[y].legend&lt;br /&gt;
-- data.legend[x]&lt;br /&gt;
&lt;br /&gt;
function p.bar(frame)&lt;br /&gt;
    local debuglog=&amp;quot;&amp;quot;&lt;br /&gt;
    local args=frame.args&lt;br /&gt;
    local parent=frame.getParent(frame)&lt;br /&gt;
    local pargs=parent.args or {}&lt;br /&gt;
    local delimiter = args.delimiter or pargs.delimiter or &amp;quot;,&amp;quot;&lt;br /&gt;
    local width = args.width or pargs.width or 200&lt;br /&gt;
    local height = args.height or pargs.height or 200&lt;br /&gt;
    &lt;br /&gt;
     ---- Set up the table of &amp;quot;norms&amp;quot;.  Series 1 to N normalize to (%d+)&lt;br /&gt;
    local normalize = args.normalize or pargs.normalize or &amp;quot;&amp;quot;&lt;br /&gt;
    local prowl=mw.ustring.gmatch(normalize,&amp;quot;(%d+)&amp;quot;)&lt;br /&gt;
    norm={}&lt;br /&gt;
    local ngroup={} -- ngroup[yseries] identifies an index for ymax&lt;br /&gt;
    local nngroup=0 -- the current maximum ngroup assigned&lt;br /&gt;
    repeat&lt;br /&gt;
       local t=prowl()&lt;br /&gt;
       if not(t) then break end&lt;br /&gt;
       t=tonumber(t)&lt;br /&gt;
       table.insert(norm,t)&lt;br /&gt;
    until false&lt;br /&gt;
    &lt;br /&gt;
     --- import the actual data in group1 .. groupN&lt;br /&gt;
    local yseries=0;local x=0&lt;br /&gt;
    local data={} -- main data storage array&lt;br /&gt;
    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!&lt;br /&gt;
    repeat&lt;br /&gt;
       yseries=yseries+1&lt;br /&gt;
       data[yseries]={}&lt;br /&gt;
        --- pull in the &amp;quot;groupN&amp;quot; data (delimited) --&amp;gt; text&lt;br /&gt;
       local text=args[&amp;quot;group&amp;quot;..yseries] -- each _group_ is a group of x-values in a y-series&lt;br /&gt;
       if not (text) then maxy=yseries-1 break end&lt;br /&gt;
               ---- pull in the originN=some number&lt;br /&gt;
       data[yseries].origin=args[&amp;quot;origin&amp;quot;..yseries] or 0&lt;br /&gt;
       data[yseries].origin=tonumber(data[yseries].origin)&lt;br /&gt;
       data[yseries].max=data[yseries].origin;data[yseries].min=data[yseries].origin&lt;br /&gt;
       debuglog=debuglog..&amp;quot;I&amp;quot;..yseries..tostring(norm[yseries])&lt;br /&gt;
        --- set ngroup[yseries] to whatever its norm points at, or new&lt;br /&gt;
       if norm[yseries]&lt;br /&gt;
       then if ngroup[norm[yseries]]&lt;br /&gt;
           then ngroup[yseries]=ngroup[norm[yseries]]&lt;br /&gt;
           else nngroup=nngroup+1&lt;br /&gt;
               ngroup[yseries]=nngroup&lt;br /&gt;
           end&lt;br /&gt;
       else ngroup[yseries]=1 -- if no norm specified, just dump to the first series group&lt;br /&gt;
       end&lt;br /&gt;
        ---- pull in the actual values&lt;br /&gt;
       prowl=mw.ustring.gmatch(text,&amp;quot;([^&amp;quot; .. delimiter .. &amp;quot;]+)&amp;quot;)&lt;br /&gt;
       x=0&lt;br /&gt;
       repeat&lt;br /&gt;
          x=x+1&lt;br /&gt;
          data[yseries][x]={}&lt;br /&gt;
          data[yseries][x].value=prowl()&lt;br /&gt;
          debuglog=debuglog..&amp;quot;V&amp;quot;..x..yseries..tostring(data[yseries][x].value)&lt;br /&gt;
          if not(data[yseries][x].value) then if x&amp;gt;maxx then maxx = x-1 end; break end&lt;br /&gt;
          data[yseries][x].value=tonumber(data[yseries][x].value)&lt;br /&gt;
          if data[yseries].max then if data[yseries][x].value&amp;gt;data[yseries].max then data[yseries].max=data[yseries][x].value end else data[yseries].max=data[yseries][x].value end&lt;br /&gt;
          if data[yseries].min then if data[yseries][x].value&amp;lt;data[yseries].min then data[yseries].min=data[yseries][x].value end else data[yseries].min=data[yseries][x].value end&lt;br /&gt;
       until false&lt;br /&gt;
        ---- pull in the colorN=&amp;quot;whatever&amp;quot;&lt;br /&gt;
       data[yseries].color=args[&amp;quot;color&amp;quot;..yseries] or &amp;quot;&amp;quot; -- one color for yseries group; can be nil&lt;br /&gt;
       if data[yseries].color==&amp;quot;&amp;quot; then data[yseries].color=&amp;quot;black&amp;quot; end&lt;br /&gt;
    until false&lt;br /&gt;
    &lt;br /&gt;
     --- import the xlegends for each group&lt;br /&gt;
    prowl=mw.ustring.gmatch(args.xlegend,&amp;quot;[^&amp;quot; .. delimiter .. &amp;quot;]+&amp;quot;)&lt;br /&gt;
    x=0&lt;br /&gt;
    data.legend={} -- for x legends, y=&amp;quot;legend&amp;quot;&lt;br /&gt;
    repeat&lt;br /&gt;
       x=x+1&lt;br /&gt;
       data.legend[x]=prowl()&lt;br /&gt;
       if not (data.legend[x]) then break end&lt;br /&gt;
       data.legend[x]=data.legend[x]&lt;br /&gt;
    until false&lt;br /&gt;
    &lt;br /&gt;
     --- import the ylegends for each group&lt;br /&gt;
    prowl=mw.ustring.gmatch(args.ylegend,&amp;quot;[^&amp;quot; .. delimiter .. &amp;quot;]+&amp;quot;)&lt;br /&gt;
    yseries=0&lt;br /&gt;
    repeat&lt;br /&gt;
       yseries=yseries+1&lt;br /&gt;
       data[yseries].legend=prowl()&lt;br /&gt;
    until not (data[yseries].legend)&lt;br /&gt;
    &lt;br /&gt;
     -- set the maxval[ngroup[(each series)]] = data[(any series in ngroup).max&lt;br /&gt;
    yseries=0&lt;br /&gt;
    repeat&lt;br /&gt;
       yseries=yseries+1&lt;br /&gt;
       if not(data[yseries].max) then break end&lt;br /&gt;
       debuglog=debuglog..tostring(yseries)..&amp;quot;:&amp;quot;..tostring(ngroup[yseries]) .. &amp;quot;&amp;gt;&amp;quot;..tostring(data[yseries].max)&lt;br /&gt;
       if maxyval[ngroup[yseries]]&lt;br /&gt;
       then if data[yseries].max&amp;gt;maxyval[ngroup[yseries]]&lt;br /&gt;
           then maxyval[ngroup[yseries]]=data[yseries].max&lt;br /&gt;
           end&lt;br /&gt;
       else maxyval[ngroup[yseries]]=data[yseries].max;debuglog=debuglog..&amp;quot;A&amp;quot;..tostring(data[yseries].max)..tostring(data[yseries].min)&lt;br /&gt;
       end&lt;br /&gt;
       if minyval[ngroup[yseries]]&lt;br /&gt;
       then if data[yseries].min&amp;lt;minyval[ngroup[yseries]]&lt;br /&gt;
           then minyval[ngroup[yseries]]=data[yseries].min&lt;br /&gt;
           end&lt;br /&gt;
       else minyval[ngroup[yseries]]=data[yseries].min;debuglog=debuglog..&amp;quot;A&amp;quot;..tostring(data[yseries].min)&lt;br /&gt;
       end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    until false&lt;br /&gt;
&lt;br /&gt;
     --- Draw the output&lt;br /&gt;
    local output = [[&amp;lt;div style=&amp;quot;position:relative;border-style:solid;border-color: #0077ff;width:]] .. width .. [[px;height:]] .. height .. [[px;&amp;quot;&amp;gt;]]&lt;br /&gt;
    local output=&amp;#039;&amp;lt;div style=&amp;quot;position:relative;overflow:visible;border-style:solid;border-color: #0077ff;width:&amp;#039; .. width .. &amp;#039;px;height:&amp;#039; .. height .. &amp;#039;px;&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
    local topreserve=20*(maxy)&lt;br /&gt;
    local bottomreserve=20&lt;br /&gt;
    local leftreserve=20&lt;br /&gt;
    local rightreserve=20&lt;br /&gt;
    local reducedheight=height-topreserve-bottomreserve&lt;br /&gt;
    local reducedwidth=width-leftreserve-rightreserve&lt;br /&gt;
    local ew=math.floor(reducedwidth/((maxx)*(maxy+1)))&lt;br /&gt;
    for y = 1,maxy do&lt;br /&gt;
        for x = 1, maxx do&lt;br /&gt;
            debuglog=debuglog..y..x..tostring(ngroup[y])..tostring(data[y][x]) .. tostring(maxyval[ngroup[y]])..tostring(minyval[ngroup[y]])&lt;br /&gt;
            if data[y][x] and maxyval[ngroup[y]]&lt;br /&gt;
            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&lt;br /&gt;
               local po=(data[y].origin-minyval[ngroup[y]])/(maxyval[ngroup[y]]-minyval[ngroup[y]])&lt;br /&gt;
               local eh=math.floor(pw*reducedheight)&lt;br /&gt;
               local et=topreserve+math.floor(reducedheight - eh - po*reducedheight)&lt;br /&gt;
               if eh&amp;lt;0 then eh=-1*eh;et=et-eh end -- pw can be negative; plot &amp;quot;backwards&amp;quot; looks the same&lt;br /&gt;
               local el=leftreserve+math.floor(((x-1)*(maxy+1) + (y-1) + 0.5)*ew)&lt;br /&gt;
               output=output..&amp;#039;&amp;lt;div style=&amp;quot;position:absolute;background-color:&amp;#039; .. data[y].color .. &amp;#039;;width:&amp;#039; .. ew .. &amp;#039;px;height:&amp;#039; .. eh .. &amp;#039;px;top:&amp;#039; .. et .. &amp;#039;px;left:&amp;#039; .. el .. &amp;#039;px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
            end -- if data[y][x] and maxval[ngroup[y]]&lt;br /&gt;
        end -- for x = 1, maxx&lt;br /&gt;
    end -- for y=1,maxy&lt;br /&gt;
     ---- draw the ylegends&lt;br /&gt;
    for x = 1,maxx do&lt;br /&gt;
        output=output .. &amp;#039;&amp;lt;span style=&amp;quot;position:absolute;top:&amp;#039;.. reducedheight+topreserve .. &amp;#039;px;left:&amp;#039;..leftreserve+math.floor(( (x-1)*(maxy+1)+(maxx/2) )*ew)..&amp;#039;px;&amp;quot;&amp;gt;&amp;#039;..data.legend[x]..&amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    for y = 1,maxy do&lt;br /&gt;
        output=output .. &amp;#039;&amp;lt;span style=&amp;quot;position:absolute;color:&amp;#039;.. data[y].color .. &amp;#039;;top:&amp;#039; .. (y-1)*20 .. &amp;#039;px;left:&amp;#039;.. (leftreserve+10) ..&amp;#039;px;&amp;quot;&amp;gt;&amp;#039;.. (data[y].legend or &amp;quot;&amp;quot;) ..&amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
        local point={minyval[ngroup[y]],data[y].origin,maxyval[ngroup[y]]}&lt;br /&gt;
        for i,j in ipairs(point) do&lt;br /&gt;
           local po=(j-minyval[ngroup[y]])/(maxyval[ngroup[y]]-minyval[ngroup[y]])&lt;br /&gt;
           local et=topreserve+math.floor((1-po)*reducedheight)&lt;br /&gt;
           debuglog=debuglog..&amp;quot;pass&amp;quot; .. y .. ngroup[y]&lt;br /&gt;
           if tonumber(ngroup[y])==1&lt;br /&gt;
           then debuglog=debuglog..&amp;quot;left&amp;quot;;output=output .. &amp;#039;&amp;lt;span style=&amp;quot;position:absolute;color:&amp;#039;.. data[y].color .. &amp;#039;;&amp;#039;..data[y].color .. &amp;#039;;text-align:right;top:&amp;#039; .. et-10 .. &amp;#039;px;width:&amp;#039;..leftreserve..&amp;#039;px;left:0px;&amp;quot;&amp;gt;&amp;#039;.. j .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
           else debuglog=debuglog..&amp;quot;right&amp;quot;;output=output .. &amp;#039;&amp;lt;span style=&amp;quot;position:absolute;color:&amp;#039;.. data[y].color .. &amp;#039;;&amp;#039;..data[y].color .. &amp;#039;;text-align:left;top:&amp;#039; .. et-10 .. &amp;#039;px;width:&amp;#039;..rightreserve..&amp;#039;px;left:&amp;#039;..leftreserve+reducedwidth..&amp;#039;px;&amp;quot;&amp;gt;&amp;#039;.. j .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
           end&lt;br /&gt;
       end&lt;br /&gt;
    end&lt;br /&gt;
    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]&lt;br /&gt;
    output = output .. &amp;quot;&amp;lt;/div&amp;gt;\n&amp;quot;&lt;br /&gt;
    if (args.debug or pargs.debug) then output=output..debuglog end&lt;br /&gt;
    return output&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Pppery</name></author>
	</entry>
</feed>