Coverage for tasks/distressthermometer.py : 52%

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