Typica is a free program for professional coffee roasters. https://typica.us
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

roastspec.xml 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <window id="roastspec">
  2. <layout type="horizontal">
  3. <layout type="vertical">
  4. <layout type="horizontal">
  5. <label>Coffee:</label>
  6. <sqldrop data="0" display="1" showdata="false" id="currentitems">
  7. <query>SELECT id, name FROM items WHERE id IN (SELECT item FROM current_items) ORDER BY name</query>
  8. </sqldrop>
  9. </layout>
  10. <layout type="horizontal">
  11. <label>Expected % weight loss:</label>
  12. <line validator="numeric" id="expectedloss" />
  13. </layout>
  14. <layout type="horizontal">
  15. <label>Tolerance</label>
  16. <line validator="numeric" id="tolerance" />
  17. </layout>
  18. <label>Specification Notes:</label>
  19. <textarea id="notes" />
  20. <layout type="horizontal">
  21. <stretch />
  22. <button id="save" type="push" name="Save" />
  23. </layout>
  24. </layout>
  25. <svgwidget id="boxplot" />
  26. </layout>
  27. <program>
  28. <![CDATA[
  29. var window = this;
  30. this.windowTitle = TTR("roastspec", "Typica - Edit Roasting Specification");
  31. var selector = findChildObject(this, 'currentitems');
  32. var expected = findChildObject(this, 'expectedloss');
  33. var tolerance = findChildObject(this, 'tolerance');
  34. var notes = findChildObject(this, 'notes');
  35. var savebutton = findChildObject(this, 'save');
  36. var boxplot = findChildObject(this, 'boxplot');
  37. var updateDisplay = function() {
  38. var query = new QSqlQuery();
  39. query.prepare("SELECT loss, tolerance, notes FROM roasting_specification WHERE item = :id1 AND time = (SELECT max(time) FROM roasting_specification WHERE item = :id2)");
  40. query.bind(":id1", selector.currentData());
  41. query.bind(":id2", selector.currentData());
  42. query.exec();
  43. if(query.next()) {
  44. if(query.value(0).length > 0) {
  45. expected.text = Number(query.value(0)) * 100;
  46. } else {
  47. expected.text = "";
  48. }
  49. if(query.value(1).length > 0) {
  50. tolerance.text = Number(query.value(1)) * 100;
  51. } else {
  52. tolerance.text = "";
  53. }
  54. notes.plainText = query.value(2);
  55. } else {
  56. expected.text = "";
  57. tolerance.text = "";
  58. notes.plainText = "";
  59. }
  60. query.prepare("SELECT (unroasted_total_quantity - roasted_quantity)/unroasted_total_quantity AS loss FROM roasting_log WHERE roasted_id = :id1 AND unroasted_id = (SELECT unroasted_id FROM roasting_log WHERE time = (SELECT max(time) FROM roasting_log WHERE roasted_id = :id2) AND roasted_id = :id3) AND approval = true ORDER BY loss ASC");
  61. query.bind(":id1", selector.currentData());
  62. query.bind(":id2", selector.currentData());
  63. query.bind(":id3", selector.currentData());
  64. query.exec();
  65. var buffer = new QBuffer;
  66. buffer.open(3);
  67. var output = new XmlWriter(buffer);
  68. output.writeStartDocument("1.0");
  69. output.writeDTD('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">');
  70. output.writeStartElement("svg");
  71. output.writeAttribute("width", "40");
  72. output.writeAttribute("height", "320");
  73. output.writeStartElement("g");
  74. output.writeAttribute("stroke", "black");
  75. output.writeAttribute("stroke-width", "2");
  76. output.writeStartElement("line");
  77. output.writeAttribute("x1", "15");
  78. output.writeAttribute("x2", "25");
  79. output.writeAttribute("y1", "278.25");
  80. output.writeAttribute("y2", "278.26");
  81. output.writeTextElement("title", "17.71");
  82. output.writeEndElement();
  83. output.writeStartElement("line");
  84. output.writeAttribute("x1", "20");
  85. output.writeAttribute("x2", "20");
  86. output.writeAttribute("y1", "278.25");
  87. output.writeAttribute("y2", "247.5");
  88. output.writeEndElement();
  89. output.writeStartElement("line");
  90. output.writeAttribute("x1", "10");
  91. output.writeAttribute("x2", "30");
  92. output.writeAttribute("y1", "247.5");
  93. output.writeAttribute("y2", "247.5");
  94. output.writeEndElement();
  95. output.writeEndElement();
  96. output.writeEndElement();
  97. output.writeEndDocument();
  98. boxplot.loadDevice(buffer);
  99. buffer.close();
  100. query = query.invalidate();
  101. };
  102. updateDisplay();
  103. selector['currentIndexChanged(int)'].connect(function() {
  104. updateDisplay();
  105. });
  106. savebutton.clicked.connect(function() {
  107. var query = new QSqlQuery();
  108. var columnspec = "time, item, ";
  109. var valuespec = "'now', :id, ";
  110. if(expected.text.length > 0) {
  111. columnspec += "loss, ";
  112. valuespec += ":loss, ";
  113. }
  114. if(tolerance.text.length > 0) {
  115. columnspec += "tolerance, ";
  116. valuespec += ":tolerance, ";
  117. }
  118. columnspec += "notes";
  119. valuespec += ":notes";
  120. query.prepare("INSERT INTO roasting_specification (" + columnspec + ") VALUES (" + valuespec + ")");
  121. query.bind(":id", selector.currentData());
  122. if(expected.text.length > 0) {
  123. query.bind(":loss", Number(expected.text) / 100);
  124. }
  125. if(tolerance.text.length > 0) {
  126. query.bind(":tolerance", Number(tolerance.text) / 100);
  127. }
  128. query.bind(":notes", notes.plainText);
  129. query.exec();
  130. window.close();
  131. });
  132. ]]>
  133. </program>
  134. </window>