summaryrefslogtreecommitdiff
path: root/models/nutrient-value.rkt
diff options
context:
space:
mode:
Diffstat (limited to 'models/nutrient-value.rkt')
-rw-r--r--models/nutrient-value.rkt150
1 files changed, 150 insertions, 0 deletions
diff --git a/models/nutrient-value.rkt b/models/nutrient-value.rkt
index 9653c7f..4514d84 100644
--- a/models/nutrient-value.rkt
+++ b/models/nutrient-value.rkt
@@ -51,3 +51,153 @@
(for/hash ([r (in-list residuals)])
(match-define (vector n-id n-canonical-name n-french-name n-formula value-ppm) r)
(values (nutrient n-id n-canonical-name n-french-name n-formula) value-ppm)))
+
+(module+ test
+ (require rackunit
+ rackunit/text-ui
+ db
+ sql
+ "../db/conn.rkt"
+ "../db/migrations.rkt"
+ "../models/nutrient.rkt")
+
+ (run-tests (test-suite "Nutrient value model"
+ #:before (λ ()
+ (connect! #:path 'memory)
+ (migrate-all!)
+ (create-nutrient! "Examplium" "Examplium" "Ex")
+ (create-nutrient! "Ignorium" "Ignorium" "Ig")
+ (create-nutrient! "Testium" "Testium" "Ts")
+ (create-nutrient! "Zeroium" "Zeroium" "Zr"))
+ #:after (λ () (disconnect!))
+
+ #;(test-case "Insert nutrient values"
+ (define ex (get-nutrient #:name "Examplium"))
+ (define ig (get-nutrient #:name "Ignorium"))
+
+ ;; Create a nutrient_value_set for testing
+ (define nvs-id
+ (insert-id (query (current-conn)
+ (insert #:into nutrient_value_sets
+ #:set [nutrient_measurement_id ,sql-null]
+ [crop_requirement_id ,sql-null]
+ [fertilizer_product_id ,sql-null]))))
+
+ (define nv-hash (hash ex 100.5 ig 50.25))
+ (define result (insert-nutrient-values (current-conn) nvs-id nv-hash))
+
+ (check-true (list? result))
+ (check-true (assoc 'insert-id result))
+
+ ;; Verify values were inserted
+ (define ex-value
+ (query-value (current-conn)
+ (select value_ppm
+ #:from nutrient_values
+ #:where (and (= value_set_id ,nvs-id)
+ (= nutrient_id ,(nutrient-id ex))))))
+ (check-= ex-value 100.5 0.001))
+
+ (test-case "Get sorted nutrient values filters positive and sorts descending"
+ (define ex (get-nutrient #:name "Examplium"))
+ (define ig (get-nutrient #:name "Ignorium"))
+ (define ts (get-nutrient #:name "Testium"))
+ (define zr (get-nutrient #:name "Zeroium"))
+
+ (define nv-hash (hash ex 100 ig 50 ts 150 zr 0))
+ (define sorted (get-sorted-nutrient-values nv-hash))
+
+ ;; Should exclude zero values
+ (check-equal? (length sorted) 3)
+ ;; Should be sorted descending by value
+ (check-equal? (cdr (first sorted)) 150) ; Testium
+ (check-equal? (cdr (second sorted)) 100) ; Examplium
+ (check-equal? (cdr (third sorted)) 50) ; Ignorium
+ ;; Zeroium should not be in the list
+ (check-false (member zr (map car sorted))))
+
+ (test-case "Get sorted nutrient values with all zeros returns empty"
+ (define ex (get-nutrient #:name "Examplium"))
+ (define ig (get-nutrient #:name "Ignorium"))
+
+ (define nv-hash (hash ex 0 ig 0))
+ (define sorted (get-sorted-nutrient-values nv-hash))
+
+ (check-equal? (length sorted) 0))
+
+ (test-case "Get sorted nutrient values with negatives excluded"
+ (define ex (get-nutrient #:name "Examplium"))
+ (define ig (get-nutrient #:name "Ignorium"))
+
+ ;; Note: nutrient-value? contract should prevent this, but testing the function
+ (define nv-hash (hash ex 100 ig -50))
+ (define sorted (get-sorted-nutrient-values nv-hash))
+
+ (check-equal? (length sorted) 1)
+ (check-equal? (cdr (first sorted)) 100))
+
+ #;(test-case "Update nutrient values"
+ (define ex (get-nutrient #:name "Examplium"))
+ (define ig (get-nutrient #:name "Ignorium"))
+
+ ;; Create initial values
+ (define nvs-id
+ (insert-id (query (current-conn)
+ (insert #:into nutrient_value_sets
+ #:set [nutrient_measurement_id ,sql-null]
+ [crop_requirement_id ,sql-null]
+ [fertilizer_product_id ,sql-null]))))
+
+ (define initial-hash (hash ex 100 ig 50))
+ (insert-nutrient-values (current-conn) nvs-id initial-hash)
+
+ ;; Update values
+ (define updated-hash (hash ex 200 ig 75))
+ (update-nutrient-values! (current-conn) nvs-id updated-hash)
+
+ ;; Verify updates
+ (define ex-value
+ (query-value (current-conn)
+ (select value_ppm
+ #:from nutrient_values
+ #:where (and (= value_set_id ,nvs-id)
+ (= nutrient_id ,(nutrient-id ex))))))
+ (check-= ex-value 200 0.001)
+
+ (define ig-value
+ (query-value (current-conn)
+ (select value_ppm
+ #:from nutrient_values
+ #:where (and (= value_set_id ,nvs-id)
+ (= nutrient_id ,(nutrient-id ig))))))
+ (check-= ig-value 75 0.001))
+
+ (test-case "Residuals to nutrient value hash conversion"
+ (define ex (get-nutrient #:name "Examplium"))
+ (define ig (get-nutrient #:name "Ignorium"))
+
+ (define residuals
+ (list (vector (nutrient-id ex) "Examplium" "Examplium" "Ex" 123.45)
+ (vector (nutrient-id ig) "Ignorium" "Ignorium" "Ig" 67.89)))
+
+ (define nv-hash (residuals->nutrient-value-hash residuals))
+
+ (check-equal? (hash-count nv-hash) 2)
+ (check-= (hash-ref nv-hash ex) 123.45 0.001)
+ (check-= (hash-ref nv-hash ig) 67.89 0.001))
+
+ (test-case "Residuals to nutrient value hash with empty list"
+ (define nv-hash (residuals->nutrient-value-hash '()))
+ (check-true (hash-empty? nv-hash)))
+
+ (test-case "Residuals to nutrient value hash preserves all fields"
+ (define residuals (list (vector 1 "Examplium" "Examplium-FR" "Ex" 100.0)))
+
+ (define nv-hash (residuals->nutrient-value-hash residuals))
+ (define nutrient-key (car (hash-keys nv-hash)))
+
+ (check-equal? (nutrient-id nutrient-key) 1)
+ (check-equal? (nutrient-canonical-name nutrient-key) "Examplium")
+ (check-equal? (nutrient-french-name nutrient-key) "Examplium-FR")
+ (check-equal? (nutrient-formula nutrient-key) "Ex")
+ (check-= (hash-ref nv-hash nutrient-key) 100.0 0.001)))))
Copyright 2019--2026 Marius PETER