Coverage for tasks/distressthermometer.py: 52%
56 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
1#!/usr/bin/env python
3"""
4camcops_server/tasks/distressthermometer.py
6===============================================================================
8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
11 This file is part of CamCOPS.
13 CamCOPS is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
18 CamCOPS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
26===============================================================================
28"""
30from typing import Any, Dict, List, Tuple, Type
32from cardinal_pythonlib.stringfunc import strseq
33from sqlalchemy.ext.declarative import DeclarativeMeta
34from sqlalchemy.sql.schema import Column
35from sqlalchemy.sql.sqltypes import Integer, UnicodeText
37from camcops_server.cc_modules.cc_constants import CssClass, PV
38from camcops_server.cc_modules.cc_ctvinfo import CTV_INCOMPLETE, CtvInfo
39from camcops_server.cc_modules.cc_db import add_multiple_columns
40from camcops_server.cc_modules.cc_html import (
41 get_yes_no_none,
42 subheading_spanning_two_columns,
43 tr_qa,
44)
45from camcops_server.cc_modules.cc_request import CamcopsRequest
46from camcops_server.cc_modules.cc_sqla_coltypes import (
47 CamcopsColumn,
48 PermittedValueChecker,
49)
50from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin
53# =============================================================================
54# Distress Thermometer
55# =============================================================================
58class DistressThermometerMetaclass(DeclarativeMeta):
59 # noinspection PyInitNewSignature
60 def __init__(
61 cls: Type["DistressThermometer"],
62 name: str,
63 bases: Tuple[Type, ...],
64 classdict: Dict[str, Any],
65 ) -> None:
66 add_multiple_columns(
67 cls,
68 "q",
69 1,
70 cls.NQUESTIONS,
71 pv=PV.BIT,
72 comment_fmt="{n}. {s} (0 no, 1 yes)",
73 comment_strings=[
74 "child care",
75 "housing",
76 "insurance/financial",
77 "transportation",
78 "work/school",
79 "children",
80 "partner",
81 "close friend/relative",
82 "depression",
83 "fears",
84 "nervousness",
85 "sadness",
86 "worry",
87 "loss of interest",
88 "spiritual/religious",
89 "appearance",
90 "bathing/dressing",
91 "breathing",
92 "urination",
93 "constipation",
94 "diarrhoea",
95 "eating",
96 "fatigue",
97 "feeling swollen",
98 "fevers",
99 "getting around",
100 "indigestion",
101 "memory/concentration",
102 "mouth sores",
103 "nausea",
104 "nose dry/congested",
105 "pain",
106 "sexual",
107 "skin dry/itchy",
108 "sleep",
109 "tingling in hands/feet",
110 ],
111 )
112 super().__init__(name, bases, classdict)
115class DistressThermometer(
116 TaskHasPatientMixin, Task, metaclass=DistressThermometerMetaclass
117):
118 """
119 Server implementation of the DistressThermometer task.
120 """
122 __tablename__ = "distressthermometer"
123 shortname = "Distress Thermometer"
125 distress = CamcopsColumn(
126 "distress",
127 Integer,
128 permitted_value_checker=PermittedValueChecker(minimum=0, maximum=10),
129 comment="Distress (0 none - 10 extreme)",
130 )
131 other = Column("other", UnicodeText, comment="Other problems")
133 NQUESTIONS = 36
134 COMPLETENESS_FIELDS = strseq("q", 1, NQUESTIONS) + ["distress"]
136 @staticmethod
137 def longname(req: "CamcopsRequest") -> str:
138 _ = req.gettext
139 return _("Distress Thermometer")
141 def get_clinical_text(self, req: CamcopsRequest) -> List[CtvInfo]:
142 if self.distress is None:
143 return CTV_INCOMPLETE
144 return [CtvInfo(content=f"Overall distress: {self.distress}/10")]
146 def is_complete(self) -> bool:
147 return (
148 self.all_fields_not_none(self.COMPLETENESS_FIELDS)
149 and self.field_contents_valid()
150 )
152 def get_task_html(self, req: CamcopsRequest) -> str:
153 h = f"""
154 <div class="{CssClass.SUMMARY}">
155 <table class="{CssClass.SUMMARY}">
156 {self.get_is_complete_tr(req)}
157 {tr_qa("Overall distress (0–10)", self.distress)}
158 </table>
159 </div>
160 <div class="{CssClass.EXPLANATION}">
161 All questions relate to distress/problems “in the past week,
162 including today” (yes = problem, no = no problem).
163 </div>
164 <table class="{CssClass.TASKDETAIL}">
165 <tr>
166 <th width="50%">Question</th>
167 <th width="50%">Answer</th>
168 </tr>
169 """
170 h += tr_qa(
171 "Distress (0 no distress – 10 extreme distress)", self.distress
172 )
173 h += subheading_spanning_two_columns("Practical problems")
174 for i in range(1, 5 + 1):
175 h += tr_qa(
176 f"{i}. {self.wxstring(req, 'q' + str(i))}",
177 get_yes_no_none(req, getattr(self, "q" + str(i))),
178 )
179 h += subheading_spanning_two_columns("Family problems")
180 for i in range(6, 8 + 1):
181 h += tr_qa(
182 f"{i}. {self.wxstring(req, 'q' + str(i))}",
183 get_yes_no_none(req, getattr(self, "q" + str(i))),
184 )
185 h += subheading_spanning_two_columns("Emotional problems")
186 for i in range(9, 14 + 1):
187 h += tr_qa(
188 f"{i}. {self.wxstring(req, 'q' + str(i))}",
189 get_yes_no_none(req, getattr(self, "q" + str(i))),
190 )
191 h += subheading_spanning_two_columns("Spiritual problems")
192 for i in range(15, 15 + 1):
193 h += tr_qa(
194 f"{i}. {self.wxstring(req, 'q' + str(i))}",
195 get_yes_no_none(req, getattr(self, "q" + str(i))),
196 )
197 h += subheading_spanning_two_columns("Physical problems")
198 for i in range(16, self.NQUESTIONS + 1):
199 h += tr_qa(
200 f"{i}. {self.wxstring(req, 'q' + str(i))}",
201 get_yes_no_none(req, getattr(self, "q" + str(i))),
202 )
203 h += subheading_spanning_two_columns("Other problems")
204 h += tr_qa(self.wxstring(req, "other_s"), self.other)
205 h += """
206 </table>
207 """
208 return h