From 35df30bce607c669a95d5f397074503aa618d5d6 Mon Sep 17 00:00:00 2001 From: Marcus Kammer Date: Wed, 1 Jan 2025 17:31:55 +0100 Subject: [PATCH] Calc NPS score --- dev.metalisp.qmetrics.asd | 3 ++- src/assessment/nps.lisp | 32 +++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/dev.metalisp.qmetrics.asd b/dev.metalisp.qmetrics.asd index c0e1932..74891dc 100644 --- a/dev.metalisp.qmetrics.asd +++ b/dev.metalisp.qmetrics.asd @@ -15,4 +15,5 @@ (:file "calculator") (:file "displayer") (:file "sus") - (:file "visawi"))))))) + (:file "visawi") + (:file "nps"))))))) diff --git a/src/assessment/nps.lisp b/src/assessment/nps.lisp index e2db5c8..8475f0c 100644 --- a/src/assessment/nps.lisp +++ b/src/assessment/nps.lisp @@ -1,28 +1,50 @@ -;;; -*- mode: lisp; coding: utf-8; comment-column 79; -*- +;;; -*- mode: lisp; coding: utf-8; -*- (in-package :ml-qmetrics/assessment) +(defun nps-calc-score (promoters detractors total) + "Calculate the Net Promoter Score (NPS)." + (* (/ (- promoters detractors) total) 100)) + +(defun nps-enumerate (data) + (check-type data list) + (if data + (let ((clean-data (remove-if (lambda (x) (or (> x 10) (< x 0))) data))) + (loop for score in clean-data + counting (>= score 9) into promoters + counting (<= score 6) into detractors + finally (return (list promoters detractors (length clean-data))))) + (error "Empty DATA list."))) + ;;; ;;; CALCULATOR ;;; (defclass nps-calculator (calculator) ()) -(defmethod calculator-calc-results ((calc nps-calculator) responses)) +(defmethod calculator-calc-results ((calc nps-calculator) responses) + (let ((values (mapcar #'parse-integer (mapcar #'cdadr responses)))) + (apply #'nps-calc-score (nps-enumerate values)))) + +(defmethod calculator-calc-group-stats ((calc nps-calculator) results) + nil) ;;; ;;; DISPLAYER ;;; -(defclass nps-displayer (displayer)) +(defclass nps-displayer (displayer) ()) -(defmethod displayer-generate-html ((disp nps-displayer) results &optional group-stats survey-id)) +(defmethod displayer-generate-html ((disp nps-displayer) results &optional group-stats survey-id) + (with-section + (with-title-bar (format nil "~A" (displayer-name disp))) + (format nil "~A" results))) ;;; ;;; ASSESSMENT ;;; -(defclass nps-assessment (assessment)) +(defclass nps-assessment (assessment) ()) (defmethod initialize-instance :after ((a nps-assessment) &key) (setf (assessment-calculator a) (make-instance 'nps-calculator)