"""
camcops_server/tasks/khandaker_insight_medical.py
===============================================================================
Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
This file is part of CamCOPS.
CamCOPS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CamCOPS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
===============================================================================
"""
# =============================================================================
# Imports
# =============================================================================
from typing import Any, Dict, Tuple, Type
import cardinal_pythonlib.rnc_web as ws
from sqlalchemy.ext.declarative import DeclarativeMeta
from sqlalchemy.sql.schema import Column
from sqlalchemy.sql.sqltypes import UnicodeText
from camcops_server.cc_modules.cc_constants import CssClass
from camcops_server.cc_modules.cc_html import (
bold,
get_yes_no_none,
tr_span_col,
)
from camcops_server.cc_modules.cc_request import CamcopsRequest
from camcops_server.cc_modules.cc_sqla_coltypes import BoolColumn
from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin
# =============================================================================
# Constants
# =============================================================================
class KQInfo(object):
def __init__(self, stem: str, heading_xml: str = "") -> None:
self.fieldname_yn = stem + "_yn"
self.fieldname_comment = stem + "_comment"
self.question_xmlstr = "q_" + stem
self.heading_xmlstr = heading_xml
def has_heading(self) -> bool:
return bool(self.heading_xmlstr)
QUESTIONS = [
KQInfo("cancer", "heading_cancer"),
KQInfo("epilepsy", "heading_brain"),
KQInfo("cva_headinjury_braintumour"),
KQInfo("ms_pd_dementia"),
KQInfo("cerebralpalsy_otherbrain"),
KQInfo("visual_impairment"),
KQInfo("heart_disorder", "heading_cardiovascular"),
KQInfo("respiratory", "heading_respiratory"),
KQInfo("gastrointestinal", "heading_gastrointestinal"),
KQInfo("other_inflammatory", "heading_inflammatory"),
KQInfo("musculoskeletal", "heading_musculoskeletal"),
KQInfo("renal_urinary", "heading_renal_urinary"),
KQInfo("dermatological", "heading_dermatological"),
KQInfo("diabetes", "heading_endocrinological"),
KQInfo("other_endocrinological"),
KQInfo("haematological", "heading_haematological"),
KQInfo("infections", "heading_infections"),
]
X_TITLE = "title"
X_INSTRUCTION = "instruction"
X_HEADING_CONDITION = "heading_condition"
X_HEADING_YN = "heading_yn"
X_HEADING_COMMENT = "heading_comment"
X_COMMENT_HINT = "comment_hint"
# =============================================================================
# Khandaker_1_MedicalHistory
# =============================================================================
class KhandakerInsightMedicalMetaclass(DeclarativeMeta):
# noinspection PyInitNewSignature
def __init__(
cls: Type["KhandakerInsightMedical"],
name: str,
bases: Tuple[Type, ...],
classdict: Dict[str, Any],
) -> None:
for qinfo in QUESTIONS:
setattr(cls, qinfo.fieldname_yn, BoolColumn(qinfo.fieldname_yn))
setattr(
cls,
qinfo.fieldname_comment,
Column(qinfo.fieldname_comment, UnicodeText),
)
super().__init__(name, bases, classdict)
[docs]class KhandakerInsightMedical(
TaskHasPatientMixin, Task, metaclass=KhandakerInsightMedicalMetaclass
):
"""
Server implementation of the Khandaker_1_MedicalHistory task.
"""
__tablename__ = "khandaker_1_medicalhistory" # NB historical name
shortname = "Khandaker_Insight_Medical"
info_filename_stem = "khandaker_insight_medical"
[docs] @staticmethod
def longname(req: "CamcopsRequest") -> str:
_ = req.gettext
return _("Khandaker GM — Insight — Medical history")
[docs] def is_complete(self) -> bool:
for qinfo in QUESTIONS:
yn_value = getattr(self, qinfo.fieldname_yn)
if yn_value is None:
return False
if yn_value:
comment = getattr(self, qinfo.fieldname_comment)
if not comment:
return False
return True
[docs] def get_task_html(self, req: CamcopsRequest) -> str:
html = f"""
<div class="{CssClass.SUMMARY}">
<table class="{CssClass.SUMMARY}">
{self.get_is_complete_tr(req)}
</table>
</div>
<table class="{CssClass.TASKDETAIL}">
<tr>
<th width="40%">{self.xstring(req,
X_HEADING_CONDITION)}</th>
<th width="20%">{self.xstring(req, X_HEADING_YN)}</th>
<th width="40%">{self.xstring(req, X_HEADING_COMMENT)}</th>
</tr>
"""
for qinfo in QUESTIONS:
if qinfo.has_heading():
html += tr_span_col(
self.xstring(req, qinfo.heading_xmlstr),
cols=3,
tr_class=CssClass.SUBHEADING,
)
yn_value = getattr(self, qinfo.fieldname_yn)
yn_str = get_yes_no_none(req, yn_value)
if yn_value:
yn_str = bold(yn_str)
comment_value = getattr(self, qinfo.fieldname_comment)
html += f"""
<tr>
<td>{self.xstring(req, qinfo.question_xmlstr)}</td>
<td>{yn_str}</td>
<td>{bold(ws.webify(comment_value))
if comment_value else ""}</td>
</tr>
"""
html += "</table>"
return html