[Racket] Ferti hydroponic nutrient solver, redux.
Refactor 'effective-on' to 'target-date'.
Changed files
db/migrations.rkt
@@ -119,9 +119,9 @@
119
119
(list (create-table #:if-not-exists nutrient_targets
120
120
#:columns [id integer #:not-null]
121
121
;; ISO8601 date
122
Removed:
[effective_on text #:not-null]
122
Added:
[target_date text #:not-null]
123
123
#:constraints (primary-key id)
124
Removed:
(unique effective_on))))
124
Added:
(unique target_date))))
125
125
126
126
;;;;;;;;
127
127
;; CROPS
formlets.rkt
@@ -23,16 +23,16 @@
23
23
(values measurement-date nutrient-values))))
24
24
25
25
(define (targets-formlet)
26
Removed:
(formlet* (#%# `(div ((class "mb-3")) (h5 "Date ciblée") ,{=>* date-formlet effective-on*})
26
Added:
(formlet* (#%# `(div ((class "mb-3")) (h5 "Date ciblée") ,{=>* date-formlet target-date*})
27
27
`(div ((class "mb-3"))
28
28
(h5 "Valeurs cibles (%)")
29
29
,@(for/list ([requirement (get-crop-requirements)])
30
30
{=>* (crop-requirement-formlet requirement) requirements*}))
31
31
{=>* (submit "Enregistrer la cible" #:attributes '((class "btn btn-primary"))) _})
32
Removed:
(let ([effective-on (first effective-on*)]
32
Added:
(let ([target-date (first target-date*)]
33
33
[nutrient-values (average-crop-requirement-nutrient-values (filter pair?
34
34
requirements*))])
35
Removed:
(values effective-on nutrient-values))))
35
Added:
(values target-date nutrient-values))))
36
36
37
37
(define (fertilizer-formlet)
38
38
(formlet*
handlers.rkt
@@ -129,8 +129,8 @@
129
129
(render-page (new-target-page)))
130
130
131
131
(define (create-target req)
132
Removed:
(define-values (effective-on nutrient-values) (formlet-process (targets-formlet) req))
133
Removed:
(create-nutrient-target! effective-on nutrient-values)
132
Added:
(define-values (target-date nutrient-values) (formlet-process (targets-formlet) req))
133
Added:
(create-nutrient-target! target-date nutrient-values)
134
134
(redirect-to "/ferti/targets"))
135
135
136
136
(define (show-target _ id)
models/nutrient-target.rkt
@@ -3,14 +3,14 @@
3
3
(provide nutrient-target
4
4
nutrient-target?
5
5
nutrient-target-id
6
Removed:
(rename-out [nutrient-target-effective-on nutrient-target-date]
6
Added:
(rename-out [nutrient-target-target-date nutrient-target-date]
7
7
[nutrient-target-nutrient-values nutrient-target-values])
8
8
(contract-out
9
9
[create-nutrient-target! (-> string? nutrient-value-hash/c nutrient-target?)]
10
10
[get-nutrient-targets (-> (listof nutrient-target?))]
11
11
[get-nutrient-target
12
12
(->* ()
13
Removed:
(#:id (or/c #f exact-nonnegative-integer?) #:effective-on (or/c #f string?))
13
Added:
(#:id (or/c #f exact-nonnegative-integer?) #:date (or/c #f string?))
14
14
(or/c nutrient-target? #f))]
15
15
[get-nutrient-target-values (-> nutrient-target-or-id/c nutrient-value-hash/c)]
16
16
[get-nutrient-target-value (-> nutrient-target-or-id/c nutrient? maybe-nutrient-value?)]
@@ -24,11 +24,11 @@
24
24
"../db/conn.rkt"
25
25
"nutrient.rkt")
26
26
27
Removed:
(struct nutrient-target (id effective-on nutrient-values)
27
Added:
(struct nutrient-target (id target-date nutrient-values)
28
28
#:transparent
29
29
#:property prop:custom-write
30
30
(λ (v out _)
31
Removed:
(fprintf out "Target #~a on ~a\n" (nutrient-target-id v) (nutrient-target-effective-on v))
31
Added:
(fprintf out "Target #~a on ~a\n" (nutrient-target-id v) (nutrient-target-target-date v))
32
32
(for ([(n v) (in-hash (nutrient-target-nutrient-values v))])
33
33
(fprintf out
34
34
"~a ~a\n"
@@ -46,13 +46,13 @@
46
46
47
47
;; CREATE
48
48
49
Removed:
(define (create-nutrient-target! effective-on nutrient-values)
50
Removed:
(or (get-nutrient-target #:effective-on effective-on)
49
Added:
(define (create-nutrient-target! target-date nutrient-values)
50
Added:
(or (get-nutrient-target #:date target-date)
51
51
(with-tx
52
Removed:
(query-exec (current-conn) (insert #:into nutrient_targets #:set [effective_on ,effective-on]))
52
Added:
(query-exec (current-conn) (insert #:into nutrient_targets #:set [target_date ,target-date]))
53
53
(define nt-id
54
54
(query-value (current-conn)
55
Removed:
(select id #:from nutrient_targets #:where (= effective_on ,effective-on))))
55
Added:
(select id #:from nutrient_targets #:where (= target_date ,target-date))))
56
56
(query-exec (current-conn)
57
57
(insert #:into nutrient_value_sets #:set [nutrient_target_id ,nt-id]))
58
58
(define nvs-id
@@ -64,7 +64,7 @@
64
64
#:set [value_set_id ,nvs-id]
65
65
[nutrient_id ,(nutrient-id n)]
66
66
[value_ppm ,v])))
67
Removed:
(get-nutrient-target #:effective-on effective-on))))
67
Added:
(get-nutrient-target #:date target-date))))
68
68
69
69
;; READ
70
70
@@ -78,38 +78,38 @@
78
78
#:on (= n.id nv.nutrient_id))))
79
79
80
80
(define (grouped-row->nutrient-target row)
81
Removed:
(match-define (vector nt-id effective-on residuals) row)
82
Removed:
(nutrient-target nt-id effective-on (residuals->nutrient-value-hash residuals)))
81
Added:
(match-define (vector nt-id target-date residuals) row)
82
Added:
(nutrient-target nt-id target-date (residuals->nutrient-value-hash residuals)))
83
83
84
84
(define (get-nutrient-targets)
85
85
(define grouped-rows
86
86
(query-rows (current-conn)
87
87
(select nt.id
88
Removed:
nt.effective_on
88
Added:
nt.target_date
89
89
n.id
90
90
n.canonical_name
91
91
n.french_name
92
92
n.formula
93
93
nv.value_ppm
94
94
#:from (TableExpr:AST ,joined)
95
Removed:
#:order-by nt.effective_on
95
Added:
#:order-by nt.target_date
96
96
#:desc)
97
97
#:group '#(0 1)))
98
98
(for/list ([row grouped-rows])
99
99
(grouped-row->nutrient-target row)))
100
100
101
Removed:
(define (get-nutrient-target #:id [nt-id #f] #:effective-on [effective-on #f])
101
Added:
(define (get-nutrient-target #:id [nt-id #f] #:date [target-date #f])
102
102
(define where
103
103
(cond
104
Removed:
[(and nt-id effective-on)
105
Removed:
(scalar-expr-qq (and (= nt.id ,nt-id) (= nt.effective_on ,effective-on)))]
104
Added:
[(and nt-id target-date)
105
Added:
(scalar-expr-qq (and (= nt.id ,nt-id) (= nt.target_date ,target-date)))]
106
106
[nt-id (scalar-expr-qq (= nt.id ,nt-id))]
107
Removed:
[effective-on (scalar-expr-qq (= nt.effective_on ,effective-on))]
108
Removed:
[else (error 'get-nutrient-target "either #:id or #:effective-on must be provided")]))
107
Added:
[target-date (scalar-expr-qq (= nt.target_date ,target-date))]
108
Added:
[else (error 'get-nutrient-target "either #:id or #:date must be provided")]))
109
109
(define grouped-rows
110
110
(query-rows (current-conn)
111
111
(select nt.id
112
Removed:
nt.effective_on
112
Added:
nt.target_date
113
113
n.id
114
114
n.canonical_name
115
115
n.french_name
@@ -117,7 +117,7 @@
117
117
nv.value_ppm
118
118
#:from (TableExpr:AST ,joined)
119
119
#:where (ScalarExpr:AST ,where)
120
Removed:
#:order-by nt.effective_on
120
Added:
#:order-by nt.target_date
121
121
#:desc)
122
122
#:group '#(0 1)))
123
123
(match grouped-rows
@@ -149,7 +149,7 @@
149
149
(select value_ppm
150
150
#:from (TableExpr:AST ,joined)
151
151
#:where (= nv.nutrient_id ,(nutrient-id nutrient))
152
Removed:
#:order-by nt.effective_on
152
Added:
#:order-by nt.target_date
153
153
#:desc
154
154
#:limit 1)))
155
155
@@ -160,16 +160,16 @@
160
160
n.canonical_name
161
161
n.french_name
162
162
n.formula
163
Removed:
nt.effective_on
163
Added:
nt.target_date
164
164
nv.value_ppm
165
165
#:from (TableExpr:AST ,joined)
166
Removed:
#:order-by nt.effective_on
166
Added:
#:order-by nt.target_date
167
167
#:desc)
168
168
#:group '(#(0 1 2 3))))
169
169
(for/hash ([row grouped-rows])
170
170
(match-define (vector n-id n-canonical-name n-french-name n-formula residual-rows) row)
171
Removed:
;; residual-rows is a non-empty list of vectors: #(effective_on value_ppm)
172
Removed:
(match-define (vector _effective-on value-ppm) (first residual-rows))
171
Added:
;; residual-rows is a non-empty list of vectors: #(target_date value_ppm)
172
Added:
(match-define (vector _ value-ppm) (first residual-rows))
173
173
(values (nutrient n-id n-canonical-name n-french-name n-formula) value-ppm)))
174
174
175
175
;; UPDATE
@@ -203,15 +203,15 @@
203
203
(define phosphorus (get-nutrient #:name "Phosphorus"))
204
204
(create-nutrient-target! target-date (hash nitrogen 12.3 phosphorus 4.5))
205
205
(check-equal? (length (get-nutrient-targets)) 1)
206
Removed:
(define nt (get-nutrient-target #:effective-on target-date))
206
Added:
(define nt (get-nutrient-target #:date target-date))
207
207
(check-true (nutrient-target? nt))
208
Removed:
(check-equal? (nutrient-target-effective-on nt) target-date))
208
Added:
(check-equal? (nutrient-target-target-date nt) target-date))
209
209
210
210
(test-case "Check all target values"
211
211
(define nitrogen (get-nutrient #:name "Nitrogen"))
212
212
(define phosphorus (get-nutrient #:name "Phosphorus"))
213
213
214
Removed:
(define nt (get-nutrient-target #:effective-on target-date))
214
Added:
(define nt (get-nutrient-target #:date target-date))
215
215
(check-equal? (get-nutrient-target-value nt nitrogen) 12.3)
216
216
(check-equal? (get-nutrient-target-value nt phosphorus) 4.5)
217
217
@@ -234,7 +234,7 @@
234
234
(check-equal? (get-latest-nutrient-target-value phosphorus) 8.9))
235
235
236
236
(test-case "Delete target and cascade to target values"
237
Removed:
(define nt (get-nutrient-target #:effective-on target-date))
237
Added:
(define nt (get-nutrient-target #:date target-date))
238
238
(delete-nutrient-target! nt)
239
239
(check-false (get-nutrient-target #:id (nutrient-target-id nt)))
240
240
(check-equal? (length (get-nutrient-targets))