Qt Quick based coffee brewing control chart.
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.

main.qml 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. import CustomComponents 1.0
  2. import QtQuick 1.0
  3. Rectangle {
  4. id: root
  5. property real sumy : 0
  6. property real sumxsq : 0
  7. property real sumx : 0
  8. property real sumxy : 0
  9. property int n : 0
  10. width: 720
  11. height: 680
  12. BrewingControlChart {
  13. id: graph
  14. width: 450; height: 600
  15. anchors {right: parent.right; rightMargin: 20; top: parent.top; topMargin: 20}
  16. }
  17. Item {
  18. anchors {left: parent.left; leftMargin: 10; top: parent.top; topMargin: 10}
  19. Column {
  20. spacing: 8
  21. Row {
  22. spacing: 5
  23. Text {
  24. text: "Mass of ground coffee: "
  25. }
  26. TextInput {
  27. id: groundMass
  28. width: 30
  29. validator: DoubleValidator {
  30. bottom: 0
  31. decimals: 2
  32. notation: DoubleValidator.StandardNotation
  33. }
  34. Line {
  35. x1: -3; y1: groundMass.height
  36. x2: 33; y2: y1
  37. penWidth: 1
  38. color: "black"
  39. }
  40. }
  41. }
  42. Row {
  43. spacing: 5
  44. Text {
  45. text: "Mass of brewed coffee:"
  46. }
  47. TextInput {
  48. id: brewedMass
  49. width: 30
  50. validator: DoubleValidator {
  51. bottom: 0
  52. decimals: 2
  53. notation: DoubleValidator.StandardNotation
  54. }
  55. Line {
  56. x1: -3; y1: brewedMass.height
  57. x2: 33; y2: y1
  58. penWidth: 1
  59. color: "black"
  60. }
  61. }
  62. }
  63. Row {
  64. spacing: 56
  65. Text {
  66. text: "Percent TDS:"
  67. }
  68. TextInput {
  69. id: ptds
  70. width: 30
  71. validator: DoubleValidator {
  72. bottom: 0
  73. top: 100
  74. decimals: 2
  75. notation: DoubleValidator.StandardNotation
  76. }
  77. Line {
  78. x1: -3; y1: ptds.height
  79. x2: 33; y2: y1
  80. penWidth: 1
  81. color: "black"
  82. }
  83. }
  84. }
  85. Row {
  86. spacing: 87
  87. Text {
  88. id: colorlabel
  89. text: "Color:"
  90. }
  91. ColorPicker {
  92. id: colorpicker
  93. width: 37; height: colorlabel.height
  94. }
  95. }
  96. Row {
  97. id: lsfrow
  98. visible: false
  99. spacing: 1
  100. Text {
  101. id: fitcolorlabel
  102. text: "Least Squares Fit Color:"
  103. }
  104. ColorPicker {
  105. id: fitcolorpicker
  106. width: 37; height: colorlabel.height
  107. onColorChanged: {
  108. graph.setFitColor(color)
  109. }
  110. }
  111. }
  112. Rectangle {
  113. z: 0
  114. anchors.horizontalCenter: parent.horizontalCenter
  115. height: buttonText.height + 20; width: buttonText.width + 40
  116. border.color: "black"
  117. radius: 10
  118. Text {
  119. id: buttonText
  120. text: "Plot This Brew"
  121. anchors {horizontalCenter: parent.horizontalCenter; verticalCenter: parent.verticalCenter}
  122. }
  123. MouseArea {
  124. anchors.fill: parent
  125. onClicked: {
  126. var extraction = (brewedMass.text * (ptds.text / 100)) / groundMass.text
  127. graph.plotPoint(extraction, (ptds.text / 100), colorpicker.color)
  128. dataViewModel.append({"color": colorpicker.color, "ptds": ptds.text, "extraction": extraction})
  129. root.n += 1
  130. root.sumy += (ptds.text / 100)
  131. root.sumx += extraction
  132. root.sumxy += ((ptds.text / 100) * extraction)
  133. root.sumxsq += Math.pow(extraction, 2)
  134. if(root.n > 1) {
  135. var a = ((root.sumy * root.sumxsq)-(root.sumx * root.sumxy))/((root.n * root.sumxsq)-Math.pow(root.sumx, 2))
  136. var b = ((root.n * root.sumxy)-(root.sumx * root.sumy))/((root.n * root.sumxsq) - Math.pow(root.sumx, 2))
  137. var x1 = 0.14
  138. var x2 = 0.26
  139. var y1 = a + (b * x1)
  140. var y2 = a + (b * x2)
  141. if(y1 < 0.008) {
  142. x1 = (0.008 - a) / b
  143. y1 = 0.008
  144. }
  145. if(y2 < 0.008) {
  146. x2 = (0.008 - a) / b
  147. y2 = 0.008
  148. }
  149. if(y1 > 0.016) {
  150. x1 = (0.016 - a) / b
  151. y1 = 0.016
  152. }
  153. if(y2 > 0.016) {
  154. x2 = (0.016 - a) / b
  155. y2 = 0.016
  156. }
  157. graph.setFit(x1, y1, x2, y2);
  158. }
  159. }
  160. }
  161. }
  162. Repeater {
  163. id: dataView
  164. model: ListModel {
  165. id: dataViewModel
  166. }
  167. delegate: Row {
  168. spacing: 3
  169. Rectangle {
  170. width: 30; height: 30
  171. color: dataViewModel.get(index).color
  172. }
  173. Column {
  174. Text {
  175. text: "Strength: "+dataViewModel.get(index).ptds+"% TDS"
  176. }
  177. Text {
  178. text: "Extraction: "+Number(dataViewModel.get(index).extraction*100).toFixed(2)+"%"
  179. }
  180. }
  181. }
  182. }
  183. }
  184. }
  185. Component.onCompleted: {
  186. var quitItem = window.addMenuItem("File", "Quit");
  187. quitItem.shortcut = "Ctrl+Q";
  188. quitItem.triggered.connect(function() {
  189. Qt.quit();
  190. });
  191. var clearItem = window.addMenuItem("Plotting", "Clear Data");
  192. clearItem.triggered.connect(function() {
  193. graph.clear();
  194. dataViewModel.clear();
  195. root.sumy = 0;
  196. root.sumxsq = 0;
  197. root.sumx = 0;
  198. root.sumxy = 0;
  199. root.n = 0;
  200. graph.setFit(0, 0, 0, 0);
  201. });
  202. var showLeastSquares = window.addMenuItem("Plotting", "Least Squares Fit");
  203. showLeastSquares.checkable = true;
  204. showLeastSquares.triggered.connect(function() {
  205. graph.setFitVisible(showLeastSquares.checked);
  206. lsfrow.visible = showLeastSquares.checked;
  207. });
  208. }
  209. }