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/khandaker_insight_medical.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, Tuple, Type 

30 

31import cardinal_pythonlib.rnc_web as ws 

32from sqlalchemy.ext.declarative import DeclarativeMeta 

33from sqlalchemy.sql.schema import Column 

34from sqlalchemy.sql.sqltypes import UnicodeText 

35 

36from camcops_server.cc_modules.cc_constants import CssClass 

37from camcops_server.cc_modules.cc_html import ( 

38 bold, 

39 get_yes_no_none, 

40 tr_span_col, 

41) 

42from camcops_server.cc_modules.cc_request import CamcopsRequest 

43from camcops_server.cc_modules.cc_sqla_coltypes import BoolColumn 

44from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin 

45 

46 

47class KQInfo(object): 

48 def __init__(self, stem: str, heading_xml: str = "") -> None: 

49 self.fieldname_yn = stem + "_yn" 

50 self.fieldname_comment = stem + "_comment" 

51 self.question_xmlstr = "q_" + stem 

52 self.heading_xmlstr = heading_xml 

53 

54 def has_heading(self) -> bool: 

55 return bool(self.heading_xmlstr) 

56 

57 

58QUESTIONS = [ 

59 KQInfo("cancer", "heading_cancer"), 

60 KQInfo("epilepsy", "heading_brain"), 

61 KQInfo("cva_headinjury_braintumour"), 

62 KQInfo("ms_pd_dementia"), 

63 KQInfo("cerebralpalsy_otherbrain"), 

64 KQInfo("visual_impairment"), 

65 KQInfo("heart_disorder", "heading_cardiovascular"), 

66 KQInfo("respiratory", "heading_respiratory"), 

67 KQInfo("gastrointestinal", "heading_gastrointestinal"), 

68 KQInfo("other_inflammatory", "heading_inflammatory"), 

69 KQInfo("musculoskeletal", "heading_musculoskeletal"), 

70 KQInfo("renal_urinary", "heading_renal_urinary"), 

71 KQInfo("dermatological", "heading_dermatological"), 

72 KQInfo("diabetes", "heading_endocrinological"), 

73 KQInfo("other_endocrinological"), 

74 KQInfo("haematological", "heading_haematological"), 

75 KQInfo("infections", "heading_infections"), 

76] 

77 

78X_TITLE = "title" 

79X_INSTRUCTION = "instruction" 

80X_HEADING_CONDITION = "heading_condition" 

81X_HEADING_YN = "heading_yn" 

82X_HEADING_COMMENT = "heading_comment" 

83X_COMMENT_HINT = "comment_hint" 

84 

85 

86# ============================================================================= 

87# Khandaker_1_MedicalHistory 

88# ============================================================================= 

89 

90class KhandakerInsightMedicalMetaclass(DeclarativeMeta): 

91 # noinspection PyInitNewSignature 

92 def __init__(cls: Type['KhandakerInsightMedical'], 

93 name: str, 

94 bases: Tuple[Type, ...], 

95 classdict: Dict[str, Any]) -> None: 

96 for qinfo in QUESTIONS: 

97 setattr(cls, qinfo.fieldname_yn, BoolColumn(qinfo.fieldname_yn)) 

98 setattr(cls, qinfo.fieldname_comment, 

99 Column(qinfo.fieldname_comment, UnicodeText)) 

100 super().__init__(name, bases, classdict) 

101 

102 

103class KhandakerInsightMedical(TaskHasPatientMixin, Task, 

104 metaclass=KhandakerInsightMedicalMetaclass): 

105 """ 

106 Server implementation of the Khandaker_1_MedicalHistory task. 

107 """ 

108 __tablename__ = "khandaker_1_medicalhistory" # NB historical name 

109 shortname = "Khandaker_Insight_Medical" 

110 

111 @staticmethod 

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

113 _ = req.gettext 

114 return _("Khandaker GM — Insight — Medical history") 

115 

116 def is_complete(self) -> bool: 

117 for qinfo in QUESTIONS: 

118 yn_value = getattr(self, qinfo.fieldname_yn) 

119 if yn_value is None: 

120 return False 

121 if yn_value: 

122 comment = getattr(self, qinfo.fieldname_comment) 

123 if not comment: 

124 return False 

125 return True 

126 

127 def get_task_html(self, req: CamcopsRequest) -> str: 

128 html = f""" 

129 <div class="{CssClass.SUMMARY}"> 

130 <table class="{CssClass.SUMMARY}"> 

131 {self.get_is_complete_tr(req)} 

132 </table> 

133 </div> 

134 <table class="{CssClass.TASKDETAIL}"> 

135 <tr> 

136 <th width="40%">{self.xstring(req, 

137 X_HEADING_CONDITION)}</th> 

138 <th width="20%">{self.xstring(req, X_HEADING_YN)}</th> 

139 <th width="40%">{self.xstring(req, X_HEADING_COMMENT)}</th> 

140 </tr> 

141 """ 

142 

143 for qinfo in QUESTIONS: 

144 if qinfo.has_heading(): 

145 html += tr_span_col( 

146 self.xstring(req, qinfo.heading_xmlstr), 

147 cols=3, 

148 tr_class=CssClass.SUBHEADING, 

149 ) 

150 yn_value = getattr(self, qinfo.fieldname_yn) 

151 yn_str = get_yes_no_none(req, yn_value) 

152 if yn_value: 

153 yn_str = bold(yn_str) 

154 comment_value = getattr(self, qinfo.fieldname_comment) 

155 html += f""" 

156 <tr> 

157 <td>{self.xstring(req, qinfo.question_xmlstr)}</td> 

158 <td>{yn_str}</td> 

159 <td>{bold(ws.webify(comment_value)) 

160 if comment_value else ""}</td> 

161 </tr> 

162 """ 

163 

164 html += "</table>" 

165 return html