Move assessment code to the corresponding files

This commit is contained in:
Marcus Kammer 2024-10-15 18:40:14 +02:00
parent 9ed1b52f51
commit f2e96cff21
Signed by: marcuskammer
GPG key ID: C374817BE285268F
4 changed files with 106 additions and 100 deletions

View file

@ -17,7 +17,9 @@
(:file "stats") (:file "stats")
(:module "assessment/" (:module "assessment/"
:components :components
((:file "assessment"))) ((:file "assessment")
(:file "sus")
(:file "visawi")))
(:file "survey") (:file "survey")
(:file "questionnaire") (:file "questionnaire")
(:file "surveys") (:file "surveys")

View file

@ -133,93 +133,6 @@ ENTRY: Entry from a response."
(defgeneric calculator-group-stats (calculator results)) (defgeneric calculator-group-stats (calculator results))
;;; sus specific code
(defun sus-response-entry-negative-p (key-str)
(let ((number (string-integer key-str)))
(if (evenp number)
t
nil)))
(defun sus-recode-values (values)
(let ((counter 0))
(mapcar (lambda (x)
(setq counter (1+ counter))
(if (evenp counter)
(- 5 x)
(1- x)))
values)))
(defun sus-score (values)
(let ((values (remove-if #'keywordp values)))
(list :SCORE (* (apply #'+ values) 2.5))))
(defun sus-recode-value (value negative-p)
(if negative-p
(- 5 value)
(1- value)))
(defun sus-response-entry-process (entry)
(response-entry-process #'sus-response-entry-negative-p #'sus-recode-value entry))
(defclass sus-calculator (calculator) ())
(defmethod calculator-calc-results ((calc sus-calculator) responses)
(loop :for response :in responses
:for timestamp = (first response)
:for values = (reverse-pairs (aggregate-values-per-category #'sus-response-entry-process
(rest response)))
:collect (cons :TIMESTAMP
(cons timestamp
(append values (sus-score values))))))
(defmethod calculator-group-stats ((calc sus-calculator) results)
nil)
(defun visawi-value-matching (value)
(case value
(1 7)
(2 6)
(3 5)
(4 4)
(5 3)
(6 2)
(7 1)))
(defun visawi-recode-value (value negative-p)
"Recode response score from negative question.
VALUE is a integer.
NEGATIVE-P is a Predicate.
Returns an integer."
(if negative-p
(visawi-value-matching value)
value))
(defun visawi-entry-process (entry)
(response-entry-process #'response-entry-negative-p #'visawi-recode-value entry))
(defclass visawi-calculator (calculator) ())
(defmethod calculator-calc-results ((calc visawi-calculator) responses)
(loop :for response :in responses
:for timestamp = (first response)
:collect (cons :timestamp
(cons timestamp (mean-score-per-category #'visawi-entry-process
(rest response))))))
(defmethod calculator-group-stats ((calc visawi-calculator) results)
(if (> (length results) 1)
(flet ((merge-entry (acc entry)
(loop :for (key value) :on entry :by #'cddr
:do (push value (getf acc key)))
acc))
(let ((merged-values (reduce #'merge-entry
(mapcar #'cddr results)
:initial-value '())))
(reverse (loop :for (key value) :on merged-values :by #'cddr
:collect (list key (calculate-statistics value))))))
nil))
;;; Displayer ;;; Displayer
(defclass displayer () (defclass displayer ()
@ -235,15 +148,3 @@ Returns an integer."
(when group-stats (when group-stats
(with-section (with-title-bar "Group Analysis") (with-section (with-title-bar "Group Analysis")
(render-nested-plist-tbl group-stats))))) (render-nested-plist-tbl group-stats)))))
(defclass sus-assessment (assessment) ())
(defmethod initialize-instance :after ((a sus-assessment) &key)
(setf (assessment-calculator a) (make-instance 'sus-calculator)
(assessment-displayer a) (make-instance 'displayer :name "SUS")))
(defclass visawi-assessment (assessment) ())
(defmethod initialize-instance :after ((a visawi-assessment) &key)
(setf (assessment-calculator a) (make-instance 'visawi-calculator)
(assessment-displayer a) (make-instance 'displayer :name "VISAWI")))

50
src/assessment/sus.lisp Normal file
View file

@ -0,0 +1,50 @@
;;;; -*- mode: common-lisp; coding: utf-8; -*-
(in-package :ml-survey/assessment)
(defun sus-response-entry-negative-p (key-str)
(let ((number (string-integer key-str)))
(if (evenp number)
t
nil)))
(defun sus-recode-values (values)
(let ((counter 0))
(mapcar (lambda (x)
(setq counter (1+ counter))
(if (evenp counter)
(- 5 x)
(1- x)))
values)))
(defun sus-score (values)
(let ((values (remove-if #'keywordp values)))
(list :SCORE (* (apply #'+ values) 2.5))))
(defun sus-recode-value (value negative-p)
(if negative-p
(- 5 value)
(1- value)))
(defun sus-response-entry-process (entry)
(response-entry-process #'sus-response-entry-negative-p #'sus-recode-value entry))
(defclass sus-calculator (calculator) ())
(defmethod calculator-calc-results ((calc sus-calculator) responses)
(loop :for response :in responses
:for timestamp = (first response)
:for values = (reverse-pairs (aggregate-values-per-category #'sus-response-entry-process
(rest response)))
:collect (cons :TIMESTAMP
(cons timestamp
(append values (sus-score values))))))
(defmethod calculator-group-stats ((calc sus-calculator) results)
nil)
(defclass sus-assessment (assessment) ())
(defmethod initialize-instance :after ((a sus-assessment) &key)
(setf (assessment-calculator a) (make-instance 'sus-calculator)
(assessment-displayer a) (make-instance 'displayer :name "SUS")))

View file

@ -0,0 +1,53 @@
;;;; -*- mode: common-lisp; coding: utf-8; -*-
(in-package :ml-survey/assessment)
(defun visawi-value-matching (value)
(case value
(1 7)
(2 6)
(3 5)
(4 4)
(5 3)
(6 2)
(7 1)))
(defun visawi-recode-value (value negative-p)
"Recode response score from negative question.
VALUE is a integer.
NEGATIVE-P is a Predicate.
Returns an integer."
(if negative-p
(visawi-value-matching value)
value))
(defun visawi-entry-process (entry)
(response-entry-process #'response-entry-negative-p #'visawi-recode-value entry))
(defclass visawi-calculator (calculator) ())
(defmethod calculator-calc-results ((calc visawi-calculator) responses)
(loop :for response :in responses
:for timestamp = (first response)
:collect (cons :timestamp
(cons timestamp (mean-score-per-category #'visawi-entry-process
(rest response))))))
(defmethod calculator-group-stats ((calc visawi-calculator) results)
(if (> (length results) 1)
(flet ((merge-entry (acc entry)
(loop :for (key value) :on entry :by #'cddr
:do (push value (getf acc key)))
acc))
(let ((merged-values (reduce #'merge-entry
(mapcar #'cddr results)
:initial-value '())))
(reverse (loop :for (key value) :on merged-values :by #'cddr
:collect (list key (calculate-statistics value))))))
nil))
(defclass visawi-assessment (assessment) ())
(defmethod initialize-instance :after ((a visawi-assessment) &key)
(setf (assessment-calculator a) (make-instance 'visawi-calculator)
(assessment-displayer a) (make-instance 'displayer :name "VISAWI")))