Typica is a free program for professional coffee roasters. https://typica.us
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <window id="lossplots">
  2. <reporttitle>Production:->Weight Loss By Item and Operator</reporttitle>
  3. <layout type="vertical">
  4. <webview id="report" />
  5. </layout>
  6. <menu name="File">
  7. <item id="print" shortcut="Ctrl+P">Print...</item>
  8. </menu>
  9. <program>
  10. <![CDATA[
  11. this.windowTitle = TTR("lossplots", "Typica - Weight Loss By Item and Operator");
  12. var report = findChildObject(this, 'report');
  13. var printMenu = findChildObject(this, 'print');
  14. printMenu.triggered.connect(function() {
  15. report.print();
  16. });
  17. var refresh = function() {
  18. var query = new QSqlQuery;
  19. 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 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, (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");
  20. var items = new Array;
  21. while(query.next()) {
  22. var item = new Object;
  23. item.roasted_id = query.value(0);
  24. item.name = query.value(1);
  25. item.mean = query.value(8);
  26. item.min = query.value(3);
  27. item.max = query.value(7);
  28. item.plots = new Array;
  29. var plot = new Object;
  30. plot.count = query.value(2);
  31. plot.min = item.min;
  32. plot.max = item.max;
  33. plot.lower_quart = query.value(4);
  34. plot.median = query.value(5);
  35. plot.upper_quart = query.value(6);
  36. plot.name = "All";
  37. item.plots.push(plot);
  38. items.push(item);
  39. }
  40. 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");
  41. while(query.next()) {
  42. var plot = new Object;
  43. plot.count = query.value(2);
  44. plot.min = query.value(3);
  45. plot.max = query.value(7);
  46. plot.lower_quart = query.value(4);
  47. plot.median = query.value(5);
  48. plot.upper_quart = query.value(6);
  49. plot.name = query.value(1);
  50. for(var i = 0; i < items.length; i++) {
  51. if(items[i].roasted_id == query.value(0)) {
  52. items[i].plots.push(plot);
  53. break;
  54. }
  55. }
  56. }
  57. query = query.invalidate();
  58. var buffer = new QBuffer;
  59. buffer.open(3);
  60. var output = new XmlWriter(buffer);
  61. output.writeStartDocument("1.0");
  62. output.writeDTD('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg.dtd">');
  63. output.writeStartElement("html");
  64. output.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml");
  65. output.writeStartElement("head");
  66. 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;}");
  67. output.writeEndElement(); //head
  68. output.writeStartElement("body");
  69. var cdt = new Date(Date.now());
  70. output.writeTextElement("p", cdt.toLocaleDateString(TTR("reports", "en-US")) + " " + cdt.toLocaleTimeString(TTR("reports", "en-US")));
  71. function position(value, min, max) {
  72. return 300 - (((Number(value)-Number(min))/(Number(max)-Number(min)))*300);
  73. }
  74. for(var i = 0; i < items.length; i++) {
  75. output.writeStartElement("svg");
  76. output.writeAttribute("xmlns", "http://www.w3.org/2000/svg");
  77. output.writeAttribute("height", "420");
  78. output.writeAttribute("width", 84 + (items[i].plots.length * 179));
  79. output.writeStartElement("g"); //plots
  80. output.writeAttribute("transform", "translate(50,30)");
  81. var plotMin = items[i].min;
  82. var plotMax = items[i].max;
  83. for(var j = 0; j < items[i].plots.length; j++) {
  84. output.writeStartElement("g"); //plot
  85. output.writeAttribute("transform", "translate(" + (55 + (179 * j)).toString() + ",30)");
  86. output.writeStartElement("line"); //center line
  87. output.writeAttribute("class", "center");
  88. output.writeAttribute("style", "fill: #000; stroke: #000; stroke-width: 1px;");
  89. output.writeAttribute("x1", "27");
  90. output.writeAttribute("x2", "27");
  91. output.writeAttribute("y1", position(items[i].plots[j].min, plotMin, plotMax));
  92. output.writeAttribute("y2", position(items[i].plots[j].max, plotMin, plotMax));
  93. output.writeEndElement(); //line
  94. output.writeStartElement("rect"); //upper and lower quartiles box
  95. output.writeAttribute("class", "box");
  96. output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;");
  97. output.writeAttribute("x", "0");
  98. output.writeAttribute("width", "54");
  99. output.writeAttribute("y", position(items[i].plots[j].upper_quart, plotMin, plotMax));
  100. output.writeAttribute("height", position(items[i].plots[j].lower_quart, plotMin, plotMax) - position(items[i].plots[j].upper_quart, plotMin, plotMax));
  101. output.writeEndElement(); //rect
  102. output.writeStartElement("line"); //median line
  103. output.writeAttribute("class", "median");
  104. output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;");
  105. output.writeAttribute("x1", "0");
  106. output.writeAttribute("x2", "54");
  107. output.writeAttribute("y1", position(items[i].plots[j].median, plotMin, plotMax));
  108. output.writeAttribute("y2", position(items[i].plots[j].median, plotMin, plotMax));
  109. output.writeEndElement(); //line
  110. output.writeStartElement("line"); //minimum whisker
  111. output.writeAttribute("class", "whisker");
  112. output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;");
  113. output.writeAttribute("x1", "0");
  114. output.writeAttribute("x2", "54");
  115. output.writeAttribute("y1", position(items[i].plots[j].min, plotMin, plotMax));
  116. output.writeAttribute("y2", position(items[i].plots[j].min, plotMin, plotMax));
  117. output.writeEndElement(); //line
  118. output.writeStartElement("line"); //maximum whisker
  119. output.writeAttribute("class", "whisker");
  120. output.writeAttribute("style", "fill: #12DD11; stroke: #000; stroke-width: 1px;");
  121. output.writeAttribute("x1", "0");
  122. output.writeAttribute("x2", "54");
  123. output.writeAttribute("y1", position(items[i].plots[j].max, plotMin, plotMax));
  124. output.writeAttribute("y2", position(items[i].plots[j].max, plotMin, plotMax));
  125. output.writeEndElement(); //line
  126. output.writeStartElement("text"); //upper quartile label
  127. output.writeAttribute("class", "box");
  128. output.writeAttribute("dy", ".3em");
  129. output.writeAttribute("dx", "-6");
  130. output.writeAttribute("x", "0");
  131. output.writeAttribute("y", position(items[i].plots[j].upper_quart, plotMin, plotMax));
  132. output.writeAttribute("text-anchor", "end");
  133. output.writeCharacters(Number(items[i].plots[j].upper_quart * 100).toFixed(2) + "%");
  134. output.writeEndElement(); //text
  135. output.writeStartElement("text"); //lower quartile label
  136. output.writeAttribute("class", "box");
  137. output.writeAttribute("dy", ".3em");
  138. output.writeAttribute("dx", "-6");
  139. output.writeAttribute("x", "0");
  140. output.writeAttribute("y", position(items[i].plots[j].lower_quart, plotMin, plotMax));
  141. output.writeAttribute("text-anchor", "end");
  142. output.writeCharacters(Number(items[i].plots[j].lower_quart * 100).toFixed(2) + "%");
  143. output.writeEndElement(); //text
  144. output.writeStartElement("text"); //median label
  145. output.writeAttribute("class", "box");
  146. output.writeAttribute("dy", ".3em");
  147. output.writeAttribute("dx", "6");
  148. output.writeAttribute("x", "54");
  149. output.writeAttribute("y", position(items[i].plots[j].median, plotMin, plotMax));
  150. output.writeAttribute("text-anchor", "start");
  151. output.writeCharacters(Number(items[i].plots[j].median * 100).toFixed(2) + "%");
  152. output.writeEndElement(); //text
  153. output.writeStartElement("text"); //minimum label
  154. output.writeAttribute("class", "whisker");
  155. output.writeAttribute("dy", ".3em");
  156. output.writeAttribute("dx", "6");
  157. output.writeAttribute("x", "54");
  158. output.writeAttribute("y", position(items[i].plots[j].min, plotMin, plotMax));
  159. output.writeAttribute("text-anchor", "start");
  160. output.writeCharacters(Number(items[i].plots[j].min * 100).toFixed(2) + "%");
  161. output.writeEndElement(); //text
  162. output.writeStartElement("text"); //maximum label
  163. output.writeAttribute("class", "whisker");
  164. output.writeAttribute("dy", ".3em");
  165. output.writeAttribute("dx", "6");
  166. output.writeAttribute("x", "54");
  167. output.writeAttribute("y", position(items[i].plots[j].max, plotMin, plotMax));
  168. output.writeAttribute("text-anchor", "start");
  169. output.writeCharacters(Number(items[i].plots[j].max * 100).toFixed(2) + "%");
  170. output.writeEndElement(); //text
  171. output.writeEndElement(); //g
  172. }
  173. output.writeStartElement("g"); //mean line and label
  174. output.writeAttribute("transform", "translate(0, 30)");
  175. output.writeStartElement("line");
  176. output.writeAttribute("class", "center");
  177. output.writeAttribute("style", "stroke: #000; stroke-width: 1px;");
  178. output.writeAttribute("x1", "0");
  179. output.writeAttribute("x2", (items[i].plots.length * 179) - 16);
  180. output.writeAttribute("y1", position(items[i].mean, plotMin, plotMax));
  181. output.writeAttribute("y2", position(items[i].mean, plotMin, plotMax));
  182. output.writeEndElement(); //line
  183. output.writeStartElement("text");
  184. output.writeAttribute("class", "box");
  185. output.writeAttribute("dy", ".3em");
  186. output.writeAttribute("dx", "-6");
  187. output.writeAttribute("x", "0");
  188. output.writeAttribute("y", position(items[i].mean, plotMin, plotMax));
  189. output.writeAttribute("text-anchor", "end");
  190. output.writeCharacters(Number(items[i].mean * 100).toFixed(2) + "%");
  191. output.writeEndElement(); //text
  192. output.writeEndElement(); //g
  193. output.writeStartElement("g") //x axis
  194. output.writeAttribute("class", "x axis");
  195. output.writeAttribute("transform", "translate(0,340)");
  196. for(var j = 0; j < items[i].plots.length; j++) {
  197. output.writeStartElement("g"); //name and population size
  198. output.writeAttribute("class", "tick");
  199. output.writeAttribute("transform", "translate(" + (82 + (j * 179)) + ",0)");
  200. output.writeStartElement("line"); //tick
  201. output.writeAttribute("y2", "6");
  202. output.writeAttribute("x2", "0");
  203. output.writeEndElement(); //line
  204. output.writeStartElement("text"); //label
  205. output.writeAttribute("style", "text-anchor: middle");
  206. output.writeAttribute("y", "9");
  207. output.writeAttribute("x", "0");
  208. output.writeStartElement("tspan");
  209. output.writeAttribute("x", "0");
  210. output.writeAttribute("dy", ".71em");
  211. output.writeCharacters(items[i].plots[j].name);
  212. output.writeEndElement(); //tspan
  213. output.writeStartElement("tspan");
  214. output.writeAttribute("x", "0");
  215. output.writeAttribute("dy", "1.42em");
  216. output.writeCharacters("(n=" + items[i].plots[j].count + ")");
  217. output.writeEndElement(); //tspan
  218. output.writeEndElement(); //text
  219. output.writeEndElement(); //g
  220. }
  221. output.writeStartElement("path");
  222. output.writeAttribute("class", "domain");
  223. output.writeAttribute("d", "M0,6V0H" + ((items[i].plots.length * 179) - 16) + "V6");
  224. output.writeEndElement(); //path
  225. output.writeEndElement(); //g
  226. output.writeStartElement("text") //chart title
  227. output.writeAttribute("x", (84 + (items[i].plots.length * 179))/2);
  228. output.writeAttribute("y", "15");
  229. output.writeAttribute("text-anchor", "middle");
  230. output.writeAttribute("style", "font-size: 18px;");
  231. output.writeCharacters(items[i].name);
  232. output.writeEndElement(); //text
  233. output.writeEndElement(); //g
  234. output.writeEndElement(); //svg
  235. }
  236. output.writeEndElement(); //body
  237. output.writeEndElement(); //html
  238. output.writeEndDocument();
  239. report.setContent(buffer);
  240. buffer.close();
  241. };
  242. refresh();
  243. var notifier = Application.subscribe("roastinglogchange");
  244. notifier.notify.connect(function() {
  245. refresh();
  246. });
  247. ]]>
  248. </program>
  249. </window>