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.

cuppingform.xml 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. <window id="cuppingform">
  2. <layout type="vertical">
  3. <layout type="horizontal">
  4. <label>Grader:</label>
  5. <line id="grader" />
  6. <label>Session:</label>
  7. <line id="session" writable="false" />
  8. <label>Event:</label>
  9. <line id="event" writable="false" />
  10. </layout>
  11. <formarray id="form">
  12. <layout type="grid">
  13. <row>
  14. <column><label>Sample ID</label></column>
  15. <column><label>Notes</label></column>
  16. <column rowspan="5">
  17. <layout type="stack" id="attributes">
  18. <page>
  19. <layout type="grid">
  20. <row>
  21. <column>
  22. <layout type="vertical">
  23. <label>Aroma</label>
  24. <layout type="horizontal">
  25. <hscale id="aroma" />
  26. <spinbox min="0" max="10" decimals="2" step="0.01" id="aromabox" />
  27. </layout>
  28. <layout type="horizontal">
  29. <layout type="vertical">
  30. <label>Dry</label>
  31. <vscale id="dry" />
  32. </layout>
  33. <layout type="vertical">
  34. <label>Break</label>
  35. <vscale id="break" />
  36. </layout>
  37. <layout type="vertical">
  38. <label>Aroma Notes</label>
  39. <textarea id="aromanotes" />
  40. </layout>
  41. </layout>
  42. </layout>
  43. </column>
  44. <column stretch="100">
  45. <label></label>
  46. </column>
  47. </row>
  48. </layout>
  49. </page>
  50. <page>
  51. <layout type="grid">
  52. <row>
  53. <column><label>Flavor</label></column>
  54. <column><label>Acidity</label></column>
  55. <column><label>Body</label></column>
  56. </row>
  57. <row>
  58. <column>
  59. <layout type="horizontal">
  60. <hscale id="flavor" />
  61. <spinbox min="0" max="10" decimals="2" step="0.01" id="flavorbox" />
  62. </layout>
  63. </column>
  64. <column>
  65. <layout type="horizontal">
  66. <hscale id="acidity" />
  67. <spinbox min="0" max="10" decimals="2" step="0.01" id="aciditybox" />
  68. </layout>
  69. </column>
  70. <column>
  71. <layout type="horizontal">
  72. <hscale id="body" />
  73. <spinbox min="0" max="10" decimals="2" step="0.01" id="bodybox" />
  74. </layout>
  75. </column>
  76. </row>
  77. <row>
  78. <column column="1">
  79. <layout type="vertical">
  80. <label>Intensity</label>
  81. <layout type="horizontal">
  82. <vscale id="acidityintensity" />
  83. <layout type="vertical">
  84. <label>Acidity Notes</label>
  85. <textarea id="aciditynotes" />
  86. </layout>
  87. </layout>
  88. </layout>
  89. </column>
  90. <column>
  91. <layout type="vertical">
  92. <label>Level</label>
  93. <layout type="horizontal">
  94. <vscale id="bodylevel" />
  95. <layout type="vertical">
  96. <label>Body Notes</label>
  97. <textarea id="bodynotes" />
  98. </layout>
  99. </layout>
  100. </layout>
  101. </column>
  102. </row>
  103. </layout>
  104. </page>
  105. <page>
  106. <layout type="grid">
  107. <row>
  108. <column><label>Balance</label></column>
  109. <column><label>Aftertaste</label></column>
  110. <column><label>Overall</label></column>
  111. </row>
  112. <row>
  113. <column>
  114. <layout type="horizontal">
  115. <hscale id="balance" />
  116. <spinbox min="0" max="10" decimals="2" step="0.01" id="balancebox" />
  117. </layout>
  118. </column>
  119. <column>
  120. <layout type="horizontal">
  121. <hscale id="aftertaste" />
  122. <spinbox min="0" max="10" decimals="2" step="0.01" id="aftertastebox" />
  123. </layout>
  124. </column>
  125. <column>
  126. <layout type="horizontal">
  127. <hscale id="overall" />
  128. <spinbox min="0" max="10" decimals="2" step = "0.01" id="overallbox" />
  129. </layout>
  130. </column>
  131. </row>
  132. <row>
  133. <column>
  134. <textarea id="balancenotes" />
  135. </column>
  136. <column>
  137. <textarea id="aftertastenotes" />
  138. </column>
  139. </row>
  140. </layout>
  141. </page>
  142. <page>
  143. <layout type="grid">
  144. <row>
  145. <column><label>Uniformity</label></column>
  146. <column><label>Clean Cup</label></column>
  147. <column><label>Sweetness</label></column>
  148. </row>
  149. <row>
  150. <column>
  151. <layout type="horizontal">
  152. <button type="check" id="u1" name="" />
  153. <button type="check" id="u2" name="" />
  154. <button type="check" id="u3" name="" />
  155. <button type="check" id="u4" name="" />
  156. <button type="check" id="u5" name="" />
  157. <spinbox min="0" max="10" decimals="2" step="0.1" id="uniformity" />
  158. </layout>
  159. </column>
  160. <column>
  161. <layout type="horizontal">
  162. <button type="check" id="c1" name="" />
  163. <button type="check" id="c2" name="" />
  164. <button type="check" id="c3" name="" />
  165. <button type="check" id="c4" name="" />
  166. <button type="check" id="c5" name="" />
  167. <spinbox min="0" max="10" decimals="2" step="0.1" id="cleancup" />
  168. </layout>
  169. </column>
  170. <column>
  171. <layout type="horizontal">
  172. <button type="check" id="s1" name="" />
  173. <button type="check" id="s2" name="" />
  174. <button type="check" id="s3" name="" />
  175. <button type="check" id="s4" name="" />
  176. <button type="check" id="s5" name="" />
  177. <spinbox min="0" max="10" decimals="2" step="0.1" id="sweetness" />
  178. </layout>
  179. </column>
  180. </row>
  181. <row>
  182. <column>
  183. <textarea id="uniformityNotes" />
  184. </column>
  185. </row>
  186. </layout>
  187. </page>
  188. </layout>
  189. </column>
  190. <column><label>Total Score</label></column>
  191. <column>
  192. <spinbox decimals="2" step="0.01" min="0" max="100" id="totalscore" />
  193. </column>
  194. </row>
  195. <row>
  196. <column><line id="sampleID" writable="false" /></column>
  197. <column rowspan="4"><textarea id="notes" /></column>
  198. <column column="3"><label>Taints</label></column>
  199. <column>
  200. <spinbox decimals="0" step="1" id="taints" />
  201. </column>
  202. </row>
  203. <row>
  204. <column column="3"><label>Faults</label></column>
  205. <column>
  206. <spinbox decimals="0" step="1" id="faults" />
  207. </column>
  208. </row>
  209. <row>
  210. <column column="3"><label>Final Score</label></column>
  211. <column>
  212. <spinbox decimals="2" step="0.01" min="-20" max="100" id="finalscore" />
  213. </column>
  214. </row>
  215. </layout>
  216. </formarray>
  217. <button type="push" id="submit" name="Submit" />
  218. </layout>
  219. <menu name="File">
  220. <item id="quit" shortcut="Ctrl+Q">Quit</item>
  221. </menu>
  222. <menu name="Sections">
  223. <item id="p1" shortcut="Ctrl+1">Aroma</item>
  224. <item id="p2" shortcut="Ctrl+2">Flavor, Acidity, Body</item>
  225. <item id="p3" shortcut="Ctrl+3">Balance, Aftertaste, Overall</item>
  226. <item id="p4" shortcut="Ctrl+4">Uniformity, Clean Cup, Sweetness</item>
  227. <item id="next" shortcut="Ctrl+=">Next Section</item>
  228. <item id="prev" shortcut="Ctrl+-">Previous Section</item>
  229. </menu>
  230. <program>
  231. <![CDATA[
  232. var window = this;
  233. var form = findChildObject(this, 'form')
  234. var m1 = findChildObject(this, 'p1');
  235. var m2 = findChildObject(this, 'p2');
  236. var m3 = findChildObject(this, 'p3');
  237. var m4 = findChildObject(this, 'p4');
  238. var mnext = findChildObject(this, 'next');
  239. var mprev = findChildObject(this, 'prev');
  240. m1.triggered.connect(function() {
  241. for(var i = 0; i < form.elements(); i++)
  242. {
  243. var section = findChildObject(form.elementAt(i), 'attributes');
  244. section.setCurrentIndex(0);
  245. }
  246. });
  247. m2.triggered.connect(function() {
  248. for(var i = 0; i < form.elements(); i++)
  249. {
  250. var section = findChildObject(form.elementAt(i), 'attributes');
  251. section.setCurrentIndex(1);
  252. }
  253. });
  254. m3.triggered.connect(function() {
  255. for(var i = 0; i < form.elements(); i++)
  256. {
  257. var section = findChildObject(form.elementAt(i), 'attributes');
  258. section.setCurrentIndex(2);
  259. }
  260. });
  261. m4.triggered.connect(function() {
  262. for(var i = 0; i < form.elements(); i++)
  263. {
  264. var section = findChildObject(form.elementAt(i), 'attributes');
  265. section.setCurrentIndex(3);
  266. }
  267. });
  268. mnext.triggered.connect(function() {
  269. for(var i = 0; i < form.elements(); i++)
  270. {
  271. var section = findChildObject(form.elementAt(i), 'attributes');
  272. section.setCurrentIndex((section.currentIndex + 1) % 4);
  273. }
  274. });
  275. mprev.triggered.connect(function() {
  276. for(var i = 0; i < form.elements(); i++)
  277. {
  278. var section = findChildObject(form.elementAt(i), 'attributes');
  279. section.setCurrentIndex((section.currentIndex + 3) % 4);
  280. }
  281. });
  282. var quitMenu = findChildObject(this, 'quit');
  283. quitMenu.triggered.connect(function() {
  284. window.close();
  285. Application.quit();
  286. });
  287. var submit = findChildObject(this, 'submit');
  288. var grader = findChildObject(this, 'grader');
  289. var session = findChildObject(this, 'session');
  290. submit.clicked.connect(function() {
  291. for(var i = 0; i < form.elements(); i++)
  292. {
  293. var sampleBox = findChildObject(form.elementAt(i), 'sampleID');
  294. var outfile = new QBuffer("");
  295. outfile.open(3);
  296. var output = new XmlWriter(outfile);
  297. output.writeStartDocument("1.0");
  298. output.writeDTD("<!DOCTYPE cuppingsession>");
  299. output.writeStartElement("session");
  300. output.writeAttribute("samples", "1");
  301. output.writeAttribute("formtype", "T1");
  302. output.writeStartElement("grader");
  303. output.writeCDATA(grader.text);
  304. output.writeEndElement();
  305. output.writeStartElement("form");
  306. var aromaScale = findChildObject(form.elementAt(i), 'aroma');
  307. output.writeStartElement("attribute");
  308. output.writeAttribute("name", "aroma");
  309. output.writeAttribute("initial", aromaScale.initialValue);
  310. var aromaBox = findChildObject(form.elementAt(i), 'aromabox');
  311. output.writeAttribute("value", aromaBox.cleanText);
  312. output.writeEmptyElement("qualifier");
  313. output.writeAttribute("name", "dry");
  314. var dryScale = findChildObject(form.elementAt(i), 'dry');
  315. output.writeAttribute("value", dryScale.value);
  316. output.writeEmptyElement("qualifier");
  317. var breakScale = findChildObject(form.elementAt(i), 'break');
  318. output.writeAttribute("name", "break");
  319. output.writeAttribute("value", breakScale.value);
  320. output.writeStartElement("notes");
  321. var aromaNotes = findChildObject(form.elementAt(i), 'aromanotes');
  322. output.writeCDATA(aromaNotes.plainText);
  323. output.writeEndElement();
  324. output.writeEndElement();
  325. output.writeStartElement("attribute");
  326. output.writeAttribute("name", "flavor");
  327. var flavorScale = findChildObject(form.elementAt(i), 'flavor');
  328. output.writeAttribute("initial", flavorScale.initialValue);
  329. var flavorBox = findChildObject(form.elementAt(i), 'flavorbox');
  330. output.writeAttribute("value", flavorBox.cleanText);
  331. output.writeEndElement();
  332. output.writeStartElement("attribute");
  333. output.writeAttribute("name", "acidity");
  334. var acidityScale = findChildObject(form.elementAt(i), 'acidity');
  335. output.writeAttribute("initial", acidityScale.initialValue);
  336. var acidityBox = findChildObject(form.elementAt(i), 'aciditybox');
  337. output.writeAttribute("value", acidityBox.cleanText);
  338. output.writeStartElement("qualifier");
  339. output.writeAttribute("name", "intensity");
  340. var intensityScale = findChildObject(form.elementAt(i), 'acidityintensity');
  341. output.writeAttribute("value", intensityScale.value);
  342. output.writeEndElement();
  343. output.writeStartElement("notes");
  344. var acidityNotes = findChildObject(form.elementAt(i), 'aciditynotes');
  345. output.writeCDATA(acidityNotes.plainText);
  346. output.writeEndElement();
  347. output.writeEndElement();
  348. output.writeStartElement("attribute");
  349. output.writeAttribute("name", "body");
  350. var bodyScale = findChildObject(form.elementAt(i), 'body');
  351. output.writeAttribute("initial", bodyScale.initialValue);
  352. var bodyBox = findChildObject(form.elementAt(i), 'bodybox');
  353. output.writeAttribute("value", bodyBox.cleanText);
  354. output.writeStartElement("qualifier");
  355. output.writeAttribute("name", "level");
  356. var levelScale = findChildObject(form.elementAt(i), 'bodylevel');
  357. output.writeAttribute("value", levelScale.value);
  358. output.writeEndElement();
  359. output.writeStartElement("notes");
  360. var bodyNotes = findChildObject(form.elementAt(i), 'bodynotes');
  361. output.writeCDATA(bodyNotes.plainText);
  362. output.writeEndElement();
  363. output.writeEndElement();
  364. output.writeStartElement("attribute");
  365. output.writeAttribute("name", "balance");
  366. var balanceScale = findChildObject(form.elementAt(i), 'balance');
  367. output.writeAttribute("initial", balanceScale.initialValue);
  368. var balanceBox = findChildObject(form.elementAt(i), 'balancebox');
  369. output.writeAttribute("value", balanceBox.cleanText);
  370. output.writeStartElement("notes")
  371. var balanceNotes = findChildObject(form.elementAt(i), 'balancenotes');
  372. output.writeCDATA(balanceNotes.plainText);
  373. output.writeEndElement();
  374. output.writeEndElement();
  375. output.writeStartElement("attribute");
  376. output.writeAttribute("name", "aftertaste");
  377. var aftertasteScale = findChildObject(form.elementAt(i), 'aftertaste');
  378. output.writeAttribute("initial", aftertasteScale.initialValue);
  379. var aftertasteBox = findChildObject(form.elementAt(i), 'aftertastebox');
  380. output.writeAttribute("value", aftertasteBox.cleanText);
  381. output.writeStartElement("notes");
  382. var aftertasteNotes = findChildObject(form.elementAt(i), 'aftertastenotes');
  383. output.writeCDATA(aftertasteNotes.plainText);
  384. output.writeEndElement();
  385. output.writeEndElement();
  386. output.writeStartElement("attribute");
  387. output.writeAttribute("name", "overall");
  388. var overallScale = findChildObject(form.elementAt(i), 'overall');
  389. output.writeAttribute("initial", overallScale.initialValue);
  390. var overallBox = findChildObject(form.elementAt(i), 'overallbox');
  391. output.writeAttribute("value", overallBox.cleanText);
  392. output.writeEndElement();
  393. output.writeStartElement("attribute");
  394. output.writeAttribute("name", "uniformity");
  395. var uniformityBox = findChildObject(form.elementAt(i), 'uniformity');
  396. output.writeAttribute("value", uniformityBox.cleanText);
  397. output.writeStartElement("notes");
  398. var uniformityNotes = findChildObject(form.elementAt(i), 'uniformityNotes');
  399. output.writeCDATA(uniformityNotes.plainText);
  400. output.writeEndElement();
  401. output.writeEndElement();
  402. output.writeStartElement("attribute");
  403. output.writeAttribute("name", "cleancup");
  404. var cleancupBox = findChildObject(form.elementAt(i), 'cleancup');
  405. output.writeAttribute("value", cleancupBox.cleanText);
  406. output.writeEndElement();
  407. output.writeStartElement("attribute");
  408. output.writeAttribute("name", "sweetness");
  409. var sweetnessBox = findChildObject(form.elementAt(i), 'sweetness');
  410. output.writeAttribute("value", sweetnessBox.cleanText);
  411. output.writeEndElement();
  412. output.writeStartElement("attribute");
  413. output.writeAttribute("name", "total");
  414. var totalBox = findChildObject(form.elementAt(i), 'totalscore');
  415. output.writeAttribute("value", totalBox.cleanText);
  416. output.writeEndElement();
  417. output.writeStartElement("attribute");
  418. output.writeAttribute("name", "taints");
  419. var taintBox = findChildObject(form.elementAt(i), 'taints');
  420. output.writeAttribute("value", taintBox.cleanText);
  421. output.writeEndElement();
  422. output.writeStartElement("attribute");
  423. output.writeAttribute("name", "faults");
  424. var faultBox = findChildObject(form.elementAt(i), 'faults');
  425. output.writeAttribute("value", faultBox.cleanText);
  426. output.writeEndElement();
  427. output.writeStartElement("attribute");
  428. output.writeAttribute("name", "final");
  429. var finalBox = findChildObject(form.elementAt(i), 'finalscore');
  430. output.writeAttribute("value", finalBox.cleanText);
  431. output.writeEndElement();
  432. output.writeStartElement("attribute");
  433. output.writeAttribute("name", "sample");
  434. output.writeAttribute("value", sampleBox.text);
  435. output.writeEndElement();
  436. output.writeStartElement("notes");
  437. var sampleNotes = findChildObject(form.elementAt(i), 'notes');
  438. output.writeCDATA(sampleNotes.plainText);
  439. output.writeEndElement();
  440. output.writeEndElement();
  441. output.writeEndElement();
  442. output.writeEndDocument();
  443. var q = "INSERT INTO cuppingform_t1 VALUES(:session, :sample, :position, :grader, :finalscore, :notes, :serialization, :aroma, :flavor, :aftertaste, :acidity, :body, :uniformity, :balance, :cleancup, :sweetness, :overall, :total)";
  444. var query = new QSqlQuery;
  445. query.prepare(q);
  446. query.bind(":session", Number(session.text));
  447. query.bind(":sample", sampleBox.text);
  448. query.bind(":position", i + 1);
  449. query.bind(":grader", grader.text);
  450. query.bind(":finalscore", Number(finalBox.cleanText));
  451. query.bind(":notes", sampleNotes.plainText);
  452. query.bindDeviceData(":serialization", outfile);
  453. query.bind(":aroma", Number(aromaBox.cleanText));
  454. query.bind(":flavor", Number(flavorBox.cleanText));
  455. query.bind(":aftertaste", Number(aftertasteBox.cleanText));
  456. query.bind(":acidity", Number(acidityBox.cleanText));
  457. query.bind(":body", Number(bodyBox.cleanText));
  458. query.bind(":uniformity", Number(uniformityBox.cleanText));
  459. query.bind(":balance", Number(balanceBox.cleanText));
  460. query.bind(":cleancup", Number(cleancupBox.cleanText));
  461. query.bind(":sweetness", Number(sweetnessBox.cleanText));
  462. query.bind(":overall", Number(overallBox.cleanText));
  463. query.bind(":total", Number(totalBox.cleanText));
  464. query.exec();
  465. }
  466. window.close();
  467. });
  468. ]]>
  469. </program>
  470. </window>