Hide keyboard shortcuts

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 

2 

3""" 

4camcops_server/tasks/distressthermometer.py 

5 

6=============================================================================== 

7 

8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com). 

9 

10 This file is part of CamCOPS. 

11 

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. 

16 

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. 

21 

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/>. 

24 

25=============================================================================== 

26 

27""" 

28 

29from typing import Any, Dict, List, Tuple, Type 

30 

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 

35 

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 

50 

51 

52# ============================================================================= 

53# Distress Thermometer 

54# ============================================================================= 

55 

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) 

106 

107 

108class DistressThermometer(TaskHasPatientMixin, Task, 

109 metaclass=DistressThermometerMetaclass): 

110 """ 

111 Server implementation of the DistressThermometer task. 

112 """ 

113 __tablename__ = "distressthermometer" 

114 shortname = "Distress Thermometer" 

115 

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") 

122 

123 NQUESTIONS = 36 

124 COMPLETENESS_FIELDS = strseq("q", 1, NQUESTIONS) + ["distress"] 

125 

126 @staticmethod 

127 def longname(req: "CamcopsRequest") -> str: 

128 _ = req.gettext 

129 return _("Distress Thermometer") 

130 

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 )] 

137 

138 def is_complete(self) -> bool: 

139 return ( 

140 self.all_fields_not_none(self.COMPLETENESS_FIELDS) and 

141 self.field_contents_valid() 

142 ) 

143 

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