Production:->Weight Loss By Item and Operator Print... 0 AND approval = true) SELECT roasted_id, (SELECT name FROM items WHERE id = roasted_id) AS name, count(1), min(loss), percentile_cont(0.25) WITHIN GROUP (ORDER BY loss) AS lower_quart, percentile_cont(0.5) WITHIN GROUP (ORDER BY loss) AS median, percentile_cont(0.75) WITHIN GROUP (ORDER BY loss) AS upper_quart, max(loss), avg(loss) FROM c GROUP BY roasted_id ORDER BY name ASC"); var items = new Array; while(query.next()) { var item = new Object; item.roasted_id = query.value(0); item.name = query.value(1); item.mean = query.value(8); item.min = query.value(3); item.max = query.value(7); item.plots = new Array; var plot = new Object; plot.count = query.value(2); plot.min = item.min; plot.max = item.max; plot.lower_quart = query.value(4); plot.median = query.value(5); plot.upper_quart = query.value(6); plot.name = "All"; item.plots.push(plot); items.push(item); } query.exec("WITH a AS (SELECT roasted_id, max(time) AS last_batch FROM roasting_log WHERE roasted_id IN (SELECT item FROM current_items) GROUP BY roasted_id), b AS (SELECT roasted_id, last_batch, (SELECT unroasted_id FROM roasting_log WHERE roasted_id = a.roasted_id AND time = last_batch) FROM a), c AS (SELECT roasting_log.roasted_id, ((unroasted_total_quantity - roasted_quantity)/unroasted_total_quantity) AS loss, person FROM roasting_log, b WHERE roasting_log.roasted_id = b.roasted_id AND roasting_log.unroasted_id = b.unroasted_id AND unroasted_total_quantity > 0 AND approval = true) SELECT roasted_id, person, count(1), min(loss), percentile_cont(0.25) WITHIN GROUP (ORDER BY loss) AS lower_quart, percentile_cont(0.5) WITHIN GROUP (ORDER BY loss) AS median, percentile_cont(0.75) WITHIN GROUP (ORDER BY loss) AS upper_quart, max(loss) FROM c GROUP BY roasted_id, person"); while(query.next()) { var plot = new Object; plot.count = query.value(2); plot.min = query.value(3); plot.max = query.value(7); plot.lower_quart = query.value(4); plot.median = query.value(5); plot.upper_quart = query.value(6); plot.name = query.value(1); for(var i = 0; i < items.length; i++) { if(items[i].roasted_id == query.value(0)) { items[i].plots.push(plot); break; } } } query = query.invalidate(); var buffer = new QBuffer; buffer.open(3); var output = new XmlWriter(buffer); output.writeStartDocument("1.0"); output.writeDTD(''); output.writeStartElement("html"); output.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml"); output.writeStartElement("head"); output.writeTextElement("style", ".box {font: 10px sans-serif;} .whisker {font: 10px sans-serif;} .axis {font: 12px sans-serif;} .axis path {fill: none; stroke: #000; shape-rendering: crispEdges;} .axis line {fill: none; stroke: #000; shape-rendering: crispEdges;} .x.axis path {fill: none; stroke: #000; shape-rendering: crispEdges;}"); output.writeEndElement(); //head output.writeStartElement("body"); var cdt = new Date(Date.now()); output.writeTextElement("p", cdt.toLocaleDateString(TTR("reports", "en-US")) + " " + cdt.toLocaleTimeString(TTR("reports", "en-US"))); function position(value, min, max) { return 300 - (((Number(value)-Number(min))/(Number(max)-Number(min)))*300); } for(var i = 0; i < items.length; i++) { output.writeStartElement("svg"); output.writeAttribute("xmlns", "http://www.w3.org/2000/svg"); output.writeAttribute("height", "420"); output.writeAttribute("width", 84 + (items[i].plots.length * 179)); output.writeStartElement("g"); //plots output.writeAttribute("transform", "translate(50,30)"); var plotMin = items[i].min; var plotMax = items[i].max; for(var j = 0; j < items[i].plots.length; j++) { output.writeStartElement("g"); //plot output.writeAttribute("transform", "translate(" + (55 + (179 * j)).toString() + ",30)"); output.writeStartElement("line"); //center line output.writeAttribute("class", "center"); output.writeAttribute("style", "fill: #000; stroke: #000; stroke-width: 1px;"); output.writeAttribute("x1", "27"); output.writeAttribute("x2", "27"); output.writeAttribute("y1", position(items[i].plots[j].min, plotMin, plotMax)); output.writeAttribute("y2", position(items[i].plots[j].max, plotMin, plotMax)); output.writeEndElement(); //line output.writeStartElement("rect"); //upper and lower quartiles box output.writeAttribute("class", "box"); output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;"); output.writeAttribute("x", "0"); output.writeAttribute("width", "54"); output.writeAttribute("y", position(items[i].plots[j].upper_quart, plotMin, plotMax)); output.writeAttribute("height", position(items[i].plots[j].lower_quart, plotMin, plotMax) - position(items[i].plots[j].upper_quart, plotMin, plotMax)); output.writeEndElement(); //rect output.writeStartElement("line"); //median line output.writeAttribute("class", "median"); output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;"); output.writeAttribute("x1", "0"); output.writeAttribute("x2", "54"); output.writeAttribute("y1", position(items[i].plots[j].median, plotMin, plotMax)); output.writeAttribute("y2", position(items[i].plots[j].median, plotMin, plotMax)); output.writeEndElement(); //line output.writeStartElement("line"); //minimum whisker output.writeAttribute("class", "whisker"); output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;"); output.writeAttribute("x1", "0"); output.writeAttribute("x2", "54"); output.writeAttribute("y1", position(items[i].plots[j].min, plotMin, plotMax)); output.writeAttribute("y2", position(items[i].plots[j].min, plotMin, plotMax)); output.writeEndElement(); //line output.writeStartElement("line"); //maximum whisker output.writeAttribute("class", "whisker"); output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;"); output.writeAttribute("x1", "0"); output.writeAttribute("x2", "54"); output.writeAttribute("y1", position(items[i].plots[j].max, plotMin, plotMax)); output.writeAttribute("y2", position(items[i].plots[j].max, plotMin, plotMax)); output.writeEndElement(); //line output.writeStartElement("text"); //upper quartile label output.writeAttribute("class", "box"); output.writeAttribute("dy", ".3em"); output.writeAttribute("dx", "-6"); output.writeAttribute("x", "0"); output.writeAttribute("y", position(items[i].plots[j].upper_quart, plotMin, plotMax)); output.writeAttribute("text-anchor", "end"); output.writeCharacters(Number(items[i].plots[j].upper_quart * 100).toFixed(2) + "%"); output.writeEndElement(); //text output.writeStartElement("text"); //lower quartile label output.writeAttribute("class", "box"); output.writeAttribute("dy", ".3em"); output.writeAttribute("dx", "-6"); output.writeAttribute("x", "0"); output.writeAttribute("y", position(items[i].plots[j].lower_quart, plotMin, plotMax)); output.writeAttribute("text-anchor", "end"); output.writeCharacters(Number(items[i].plots[j].lower_quart * 100).toFixed(2) + "%"); output.writeEndElement(); //text output.writeStartElement("text"); //median label output.writeAttribute("class", "box"); output.writeAttribute("dy", ".3em"); output.writeAttribute("dx", "6"); output.writeAttribute("x", "54"); output.writeAttribute("y", position(items[i].plots[j].median, plotMin, plotMax)); output.writeAttribute("text-anchor", "start"); output.writeCharacters(Number(items[i].plots[j].median * 100).toFixed(2) + "%"); output.writeEndElement(); //text output.writeStartElement("text"); //minimum label output.writeAttribute("class", "whisker"); output.writeAttribute("dy", ".3em"); output.writeAttribute("dx", "6"); output.writeAttribute("x", "54"); output.writeAttribute("y", position(items[i].plots[j].min, plotMin, plotMax)); output.writeAttribute("text-anchor", "start"); output.writeCharacters(Number(items[i].plots[j].min * 100).toFixed(2) + "%"); output.writeEndElement(); //text output.writeStartElement("text"); //maximum label output.writeAttribute("class", "whisker"); output.writeAttribute("dy", ".3em"); output.writeAttribute("dx", "6"); output.writeAttribute("x", "54"); output.writeAttribute("y", position(items[i].plots[j].max, plotMin, plotMax)); output.writeAttribute("text-anchor", "start"); output.writeCharacters(Number(items[i].plots[j].max * 100).toFixed(2) + "%"); output.writeEndElement(); //text output.writeEndElement(); //g } output.writeStartElement("g"); //mean line and label output.writeAttribute("transform", "translate(0, 30)"); output.writeStartElement("line"); output.writeAttribute("class", "center"); output.writeAttribute("style", "stroke: #000; stroke-width: 1px;"); output.writeAttribute("x1", "0"); output.writeAttribute("x2", (items[i].plots.length * 179) - 16); output.writeAttribute("y1", position(items[i].mean, plotMin, plotMax)); output.writeAttribute("y2", position(items[i].mean, plotMin, plotMax)); output.writeEndElement(); //line output.writeStartElement("text"); output.writeAttribute("class", "box"); output.writeAttribute("dy", ".3em"); output.writeAttribute("dx", "-6"); output.writeAttribute("x", "0"); output.writeAttribute("y", position(items[i].mean, plotMin, plotMax)); output.writeAttribute("text-anchor", "end"); output.writeCharacters(Number(items[i].mean * 100).toFixed(2) + "%"); output.writeEndElement(); //text output.writeEndElement(); //g output.writeStartElement("g") //x axis output.writeAttribute("class", "x axis"); output.writeAttribute("transform", "translate(0,340)"); for(var j = 0; j < items[i].plots.length; j++) { output.writeStartElement("g"); //name and population size output.writeAttribute("class", "tick"); output.writeAttribute("transform", "translate(" + (82 + (j * 179)) + ",0)"); output.writeStartElement("line"); //tick output.writeAttribute("y2", "6"); output.writeAttribute("x2", "0"); output.writeEndElement(); //line output.writeStartElement("text"); //label output.writeAttribute("style", "text-anchor: middle"); output.writeAttribute("y", "9"); output.writeAttribute("x", "0"); output.writeStartElement("tspan"); output.writeAttribute("x", "0"); output.writeAttribute("dy", ".71em"); output.writeCharacters(items[i].plots[j].name); output.writeEndElement(); //tspan output.writeStartElement("tspan"); output.writeAttribute("x", "0"); output.writeAttribute("dy", "1.42em"); output.writeCharacters("(n=" + items[i].plots[j].count + ")"); output.writeEndElement(); //tspan output.writeEndElement(); //text output.writeEndElement(); //g } output.writeStartElement("path"); output.writeAttribute("class", "domain"); output.writeAttribute("d", "M0,6V0H" + ((items[i].plots.length * 179) - 16) + "V6"); output.writeEndElement(); //path output.writeEndElement(); //g output.writeStartElement("text") //chart title output.writeAttribute("x", (84 + (items[i].plots.length * 179))/2); output.writeAttribute("y", "15"); output.writeAttribute("text-anchor", "middle"); output.writeAttribute("style", "font-size: 18px;"); output.writeCharacters(items[i].name); output.writeEndElement(); //text output.writeEndElement(); //g output.writeEndElement(); //svg } output.writeEndElement(); //body output.writeEndElement(); //html output.writeEndDocument(); report.setContent(buffer); buffer.close(); }; refresh(); var notifier = Application.subscribe("roastinglogchange"); notifier.notify.connect(function() { refresh(); }); ]]>