"""
camcops_server/tasks/ceca.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/>.
===============================================================================
"""
from typing import Any, Dict, List, Optional, Sequence
import cardinal_pythonlib.rnc_web as ws
from sqlalchemy.sql.schema import Column
from sqlalchemy.sql.sqltypes import Boolean, Float, Integer, UnicodeText
from camcops_server.cc_modules.cc_constants import CssClass
from camcops_server.cc_modules.cc_html import (
answer,
get_yes_no,
get_yes_no_none,
subheading_spanning_two_columns,
tr,
tr_qa,
)
from camcops_server.cc_modules.cc_request import CamcopsRequest
from camcops_server.cc_modules.cc_sqla_coltypes import (
BIT_CHECKER,
CamcopsColumn,
MIN_ZERO_CHECKER,
ONE_TO_FOUR_CHECKER,
ONE_TO_FIVE_CHECKER,
PermittedValueChecker,
ZERO_TO_TWO_CHECKER,
ZERO_TO_THREE_CHECKER,
ZERO_TO_FOUR_CHECKER,
ZERO_TO_FIVE_CHECKER,
)
from camcops_server.cc_modules.cc_summaryelement import SummaryElement
from camcops_server.cc_modules.cc_task import (
get_from_dict,
Task,
TaskHasPatientMixin,
)
# =============================================================================
# CECA-Q3
# =============================================================================
FREQUENCY_COMMENT = "Frequency (0 never - 3 often)"
[docs]class CecaQ3(TaskHasPatientMixin, Task):
"""
Server implementation of the CECA-Q3 task.
"""
__tablename__ = "cecaq3"
shortname = "CECA-Q3"
# -------------------------------------------------------------------------
# Section 1(A)
# -------------------------------------------------------------------------
s1a_motherfigure_birthmother = CamcopsColumn(
"s1a_motherfigure_birthmother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, birth mother?",
)
s1a_motherfigure_stepmother = CamcopsColumn(
"s1a_motherfigure_stepmother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, stepmother?",
)
s1a_motherfigure_femalerelative = CamcopsColumn(
"s1a_motherfigure_femalerelative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, female relative?",
)
s1a_motherfigure_femalerelative_detail = Column(
"s1a_motherfigure_femalerelative_detail",
UnicodeText,
comment="Raised by, maternal, female relative, detail",
)
s1a_motherfigure_familyfriend = CamcopsColumn(
"s1a_motherfigure_familyfriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, family friend?",
)
s1a_motherfigure_fostermother = CamcopsColumn(
"s1a_motherfigure_fostermother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, foster mother?",
)
s1a_motherfigure_adoptivemother = CamcopsColumn(
"s1a_motherfigure_adoptivemother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, adoptive mother?",
)
s1a_motherfigure_other = CamcopsColumn(
"s1a_motherfigure_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, maternal, other?",
)
s1a_motherfigure_other_detail = Column(
"s1a_motherfigure_other_detail",
UnicodeText,
comment="Raised by, maternal, other, detail",
)
s1a_fatherfigure_birthfather = CamcopsColumn(
"s1a_fatherfigure_birthfather",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, birth father?",
)
s1a_fatherfigure_stepfather = CamcopsColumn(
"s1a_fatherfigure_stepfather",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, stepfather?",
)
s1a_fatherfigure_malerelative = CamcopsColumn(
"s1a_fatherfigure_malerelative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, male relative?",
)
s1a_fatherfigure_malerelative_detail = Column(
"s1a_fatherfigure_malerelative_detail",
UnicodeText,
comment="Raised by, paternal, male relative, detail",
)
s1a_fatherfigure_familyfriend = CamcopsColumn(
"s1a_fatherfigure_familyfriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, family friend?",
)
s1a_fatherfigure_fosterfather = CamcopsColumn(
"s1a_fatherfigure_fosterfather",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, foster father?",
)
s1a_fatherfigure_adoptivefather = CamcopsColumn(
"s1a_fatherfigure_adoptivefather",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, adoptive father?",
)
s1a_fatherfigure_other = CamcopsColumn(
"s1a_fatherfigure_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Raised by, paternal, other?",
)
s1a_fatherfigure_other_detail = Column(
"s1a_fatherfigure_other_detail",
UnicodeText,
comment="Raised by, paternal, other, detail",
)
# -------------------------------------------------------------------------
# Section 1(B)
# -------------------------------------------------------------------------
s1b_institution = CamcopsColumn(
"s1b_institution",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="In institution before 17?",
)
s1b_institution_time_years = CamcopsColumn(
"s1b_institution_time_years",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="In institution, time (years)",
)
# -------------------------------------------------------------------------
# Section 1(C)
# -------------------------------------------------------------------------
s1c_mother_died = CamcopsColumn(
"s1c_mother_died",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Mother died before 17?",
)
s1c_father_died = CamcopsColumn(
"s1c_father_died",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Father died before 17?",
)
s1c_mother_died_subject_aged = CamcopsColumn(
"s1c_mother_died_subject_aged",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Age when mother died (years)",
)
s1c_father_died_subject_aged = CamcopsColumn(
"s1c_father_died_subject_aged",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Age when father died (years)",
)
s1c_separated_from_mother = CamcopsColumn(
"s1c_separated_from_mother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Separated from mother for >=1y before 17?",
)
s1c_separated_from_father = CamcopsColumn(
"s1c_separated_from_father",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Separated from father for >=1y before 17?",
)
s1c_first_separated_from_mother_aged = CamcopsColumn(
"s1c_first_separated_from_mother_aged",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Maternal separation, age (years)",
)
s1c_first_separated_from_father_aged = CamcopsColumn(
"s1c_first_separated_from_father_aged",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Paternal separation, age (years)",
)
s1c_mother_how_long_first_separation_years = CamcopsColumn(
"s1c_mother_how_long_first_separation_years",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Maternal separation, how long first separation (y)",
)
s1c_father_how_long_first_separation_years = CamcopsColumn(
"s1c_father_how_long_first_separation_years",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Paternal separation, how long first separation (y)",
)
s1c_mother_separation_reason = CamcopsColumn(
"s1c_mother_separation_reason",
Integer,
permitted_value_checker=PermittedValueChecker(minimum=1, maximum=6),
comment="Maternal separation, reason "
"(1 illness, 2 work, 3 divorce/separation, 4 never knew, "
"5 abandoned, 6 other)",
)
s1c_father_separation_reason = CamcopsColumn(
"s1c_father_separation_reason",
Integer,
permitted_value_checker=PermittedValueChecker(minimum=1, maximum=6),
comment="Paternal separation, reason "
"(1 illness, 2 work, 3 divorce/separation, 4 never knew, "
"5 abandoned, 6 other)",
)
s1c_describe_experience = Column(
"s1c_describe_experience",
UnicodeText,
comment="Loss of/separation from parent, description",
)
# -------------------------------------------------------------------------
# Section 2(A)
# -------------------------------------------------------------------------
s2a_which_mother_figure = CamcopsColumn(
"s2a_which_mother_figure",
Integer,
permitted_value_checker=PermittedValueChecker(minimum=0, maximum=5),
comment="Mother figure, which one (0 none/skip, 1 birth mother, "
"2 stepmother, 3 other relative, 4 other non-relative, "
"5 other)",
)
s2a_which_mother_figure_other_detail = Column(
"s2a_which_mother_figure_other_detail",
UnicodeText,
comment="Mother figure, other, detail",
)
s2a_q1 = CamcopsColumn(
"s2a_q1",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, difficult to please (1 no - 5 yes)",
)
s2a_q2 = CamcopsColumn(
"s2a_q2",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, concerned re my worries (1 no - 5 yes)",
)
s2a_q3 = CamcopsColumn(
"s2a_q3",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, interested re school (1 no - 5 yes)",
)
s2a_q4 = CamcopsColumn(
"s2a_q4",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, made me feel unwanted (1 no - 5 yes)",
)
s2a_q5 = CamcopsColumn(
"s2a_q5",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, better when upset (1 no - 5 yes)",
)
s2a_q6 = CamcopsColumn(
"s2a_q6",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, critical (1 no - 5 yes)",
)
s2a_q7 = CamcopsColumn(
"s2a_q7",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, unsupervised <10y (1 no - 5 yes)",
)
s2a_q8 = CamcopsColumn(
"s2a_q8",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, time to talk (1 no - 5 yes)",
)
s2a_q9 = CamcopsColumn(
"s2a_q9",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, nuisance (1 no - 5 yes)",
)
s2a_q10 = CamcopsColumn(
"s2a_q10",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, picked on unfairly (1 no - 5 yes)",
)
s2a_q11 = CamcopsColumn(
"s2a_q11",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, there if needed (1 no - 5 yes)",
)
s2a_q12 = CamcopsColumn(
"s2a_q12",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, interested in friends (1 no - 5 yes)",
)
s2a_q13 = CamcopsColumn(
"s2a_q13",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, concerned re whereabouts (1 no - 5 yes)",
)
s2a_q14 = CamcopsColumn(
"s2a_q14",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, cared when ill (1 no - 5 yes)",
)
s2a_q15 = CamcopsColumn(
"s2a_q15",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, neglected basic needs (1 no - 5 yes)",
)
s2a_q16 = CamcopsColumn(
"s2a_q16",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Mother figure, preferred siblings (1 no - 5 yes)",
)
s2a_extra = Column(
"s2a_extra", UnicodeText, comment="Mother figure, extra detail"
)
# -------------------------------------------------------------------------
# Section 2(B)
# -------------------------------------------------------------------------
s2b_q1 = CamcopsColumn(
"s2b_q1",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, tease me (0 no - 2 yes)",
)
s2b_q2 = CamcopsColumn(
"s2b_q2",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, made me keep secrets (0 no - 2 yes)",
)
s2b_q3 = CamcopsColumn(
"s2b_q3",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, undermined confidence (0 no - 2 yes)",
)
s2b_q4 = CamcopsColumn(
"s2b_q4",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, contradictory (0 no - 2 yes)",
)
s2b_q5 = CamcopsColumn(
"s2b_q5",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, played on fears (0 no - 2 yes)",
)
s2b_q6 = CamcopsColumn(
"s2b_q6",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, liked to see me suffer (0 no - 2 yes)",
)
s2b_q7 = CamcopsColumn(
"s2b_q7",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, humiliated me (0 no - 2 yes)",
)
s2b_q8 = CamcopsColumn(
"s2b_q8",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, shamed me before others (0 no - 2 yes)",
)
s2b_q9 = CamcopsColumn(
"s2b_q9",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, rejecting (0 no - 2 yes)",
)
s2b_q10 = CamcopsColumn(
"s2b_q10",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, took things I cherished (0 no - 2 yes)",
)
s2b_q11 = CamcopsColumn(
"s2b_q11",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, eat disliked until sick (0 no - 2 yes)",
)
s2b_q12 = CamcopsColumn(
"s2b_q12",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, deprived light/food/company (0 no - 2 yes)",
)
s2b_q13 = CamcopsColumn(
"s2b_q13",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, wouldn't let me mix (0 no - 2 yes)",
)
s2b_q14 = CamcopsColumn(
"s2b_q14",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, obedience through guilt (0 no - 2 yes)",
)
s2b_q15 = CamcopsColumn(
"s2b_q15",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, threatened to hurt people dear to me "
"(0 no - 2 yes)",
)
s2b_q16 = CamcopsColumn(
"s2b_q16",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, forced to break law (0 no - 2 yes)",
)
s2b_q17 = CamcopsColumn(
"s2b_q17",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Mother figure, said wanted me dead (0 no - 2 yes)",
)
s2b_q1_frequency = CamcopsColumn(
"s2b_q1_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q2_frequency = CamcopsColumn(
"s2b_q2_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q3_frequency = CamcopsColumn(
"s2b_q3_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q4_frequency = CamcopsColumn(
"s2b_q4_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q5_frequency = CamcopsColumn(
"s2b_q5_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q6_frequency = CamcopsColumn(
"s2b_q6_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q7_frequency = CamcopsColumn(
"s2b_q7_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q8_frequency = CamcopsColumn(
"s2b_q8_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q9_frequency = CamcopsColumn(
"s2b_q9_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q10_frequency = CamcopsColumn(
"s2b_q10_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q11_frequency = CamcopsColumn(
"s2b_q11_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q12_frequency = CamcopsColumn(
"s2b_q12_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q13_frequency = CamcopsColumn(
"s2b_q13_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q14_frequency = CamcopsColumn(
"s2b_q14_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q15_frequency = CamcopsColumn(
"s2b_q15_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q16_frequency = CamcopsColumn(
"s2b_q16_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_q17_frequency = CamcopsColumn(
"s2b_q17_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s2b_age_began = CamcopsColumn(
"s2b_age_began",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Age these experienced began (years)",
)
s2b_extra = Column("s2b_extra", UnicodeText, comment="Extra detail")
# -------------------------------------------------------------------------
# Section 3(A)
# -------------------------------------------------------------------------
s3a_which_father_figure = CamcopsColumn(
"s3a_which_father_figure",
Integer,
permitted_value_checker=ZERO_TO_FIVE_CHECKER,
comment="Father figure, which one (0 none/skip, 1 birth father, "
"2 stepfather, 3 other relative, 4 other non-relative, "
"5 other)",
)
s3a_which_father_figure_other_detail = Column(
"s3a_which_father_figure_other_detail",
UnicodeText,
comment="Father figure, other, detail",
)
s3a_q1 = CamcopsColumn(
"s3a_q1",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, difficult to please (1 no - 5 yes)",
)
s3a_q2 = CamcopsColumn(
"s3a_q2",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, concerned re my worries (1 no - 5 yes)",
)
s3a_q3 = CamcopsColumn(
"s3a_q3",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, interested re school (1 no - 5 yes)",
)
s3a_q4 = CamcopsColumn(
"s3a_q4",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, made me feel unwanted (1 no - 5 yes)",
)
s3a_q5 = CamcopsColumn(
"s3a_q5",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, better when upset (1 no - 5 yes)",
)
s3a_q6 = CamcopsColumn(
"s3a_q6",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, critical (1 no - 5 yes)",
)
s3a_q7 = CamcopsColumn(
"s3a_q7",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, unsupervised <10y (1 no - 5 yes)",
)
s3a_q8 = CamcopsColumn(
"s3a_q8",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, time to talk (1 no - 5 yes)",
)
s3a_q9 = CamcopsColumn(
"s3a_q9",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, nuisance (1 no - 5 yes)",
)
s3a_q10 = CamcopsColumn(
"s3a_q10",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, picked on unfairly (1 no - 5 yes)",
)
s3a_q11 = CamcopsColumn(
"s3a_q11",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, there if needed (1 no - 5 yes)",
)
s3a_q12 = CamcopsColumn(
"s3a_q12",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, interested in friends (1 no - 5 yes)",
)
s3a_q13 = CamcopsColumn(
"s3a_q13",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, concerned re whereabouts (1 no - 5 yes)",
)
s3a_q14 = CamcopsColumn(
"s3a_q14",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, cared when ill (1 no - 5 yes)",
)
s3a_q15 = CamcopsColumn(
"s3a_q15",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, neglected basic needs (1 no - 5 yes)",
)
s3a_q16 = CamcopsColumn(
"s3a_q16",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Father figure, preferred siblings (1 no - 5 yes)",
)
s3a_extra = Column(
"s3a_extra", UnicodeText, comment="Father figure, extra detail"
)
# -------------------------------------------------------------------------
# Section 3(B)
# -------------------------------------------------------------------------
s3b_q1 = CamcopsColumn(
"s3b_q1",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, tease me (0 no - 2 yes)",
)
s3b_q2 = CamcopsColumn(
"s3b_q2",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, made me keep secrets (0 no - 2 yes)",
)
s3b_q3 = CamcopsColumn(
"s3b_q3",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, undermined confidence (0 no - 2 yes)",
)
s3b_q4 = CamcopsColumn(
"s3b_q4",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, contradictory (0 no - 2 yes)",
)
s3b_q5 = CamcopsColumn(
"s3b_q5",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, played on fears (0 no - 2 yes)",
)
s3b_q6 = CamcopsColumn(
"s3b_q6",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, liked to see me suffer (0 no - 2 yes)",
)
s3b_q7 = CamcopsColumn(
"s3b_q7",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, humiliated me (0 no - 2 yes)",
)
s3b_q8 = CamcopsColumn(
"s3b_q8",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, shamed me before others (0 no - 2 yes)",
)
s3b_q9 = CamcopsColumn(
"s3b_q9",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, rejecting (0 no - 2 yes)",
)
s3b_q10 = CamcopsColumn(
"s3b_q10",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, took things I cherished (0 no - 2 yes)",
)
s3b_q11 = CamcopsColumn(
"s3b_q11",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, eat disliked until sick (0 no - 2 yes)",
)
s3b_q12 = CamcopsColumn(
"s3b_q12",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, deprived light/food/company (0 no - 2 yes)",
)
s3b_q13 = CamcopsColumn(
"s3b_q13",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, wouldn't let me mix (0 no - 2 yes)",
)
s3b_q14 = CamcopsColumn(
"s3b_q14",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, obedience through guilt (0 no - 2 yes)",
)
s3b_q15 = CamcopsColumn(
"s3b_q15",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, threatened to hurt people dear to me "
"(0 no - 2 yes)",
)
s3b_q16 = CamcopsColumn(
"s3b_q16",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, forced to break law (0 no - 2 yes)",
)
s3b_q17 = CamcopsColumn(
"s3b_q17",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Father figure, said wanted me dead (0 no - 2 yes)",
)
s3b_q1_frequency = CamcopsColumn(
"s3b_q1_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q2_frequency = CamcopsColumn(
"s3b_q2_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q3_frequency = CamcopsColumn(
"s3b_q3_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q4_frequency = CamcopsColumn(
"s3b_q4_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q5_frequency = CamcopsColumn(
"s3b_q5_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q6_frequency = CamcopsColumn(
"s3b_q6_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q7_frequency = CamcopsColumn(
"s3b_q7_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q8_frequency = CamcopsColumn(
"s3b_q8_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q9_frequency = CamcopsColumn(
"s3b_q9_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q10_frequency = CamcopsColumn(
"s3b_q10_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q11_frequency = CamcopsColumn(
"s3b_q11_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q12_frequency = CamcopsColumn(
"s3b_q12_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q13_frequency = CamcopsColumn(
"s3b_q13_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q14_frequency = CamcopsColumn(
"s3b_q14_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q15_frequency = CamcopsColumn(
"s3b_q15_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q16_frequency = CamcopsColumn(
"s3b_q16_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_q17_frequency = CamcopsColumn(
"s3b_q17_frequency",
Integer,
permitted_value_checker=ZERO_TO_THREE_CHECKER,
comment=FREQUENCY_COMMENT,
)
s3b_age_began = CamcopsColumn(
"s3b_age_began",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Age these experienced began (years)",
)
s3b_extra = Column("s3b_extra", UnicodeText, comment="Extra detail")
# -------------------------------------------------------------------------
# Section 3(C)
# -------------------------------------------------------------------------
s3c_q1 = CamcopsColumn(
"s3c_q1",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Responsibility (1 no - 5 yes)",
)
s3c_q2 = CamcopsColumn(
"s3c_q2",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Housework (1 no - 5 yes)",
)
s3c_q3 = CamcopsColumn(
"s3c_q3",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Look after young siblings (1 no - 5 yes)",
)
s3c_q4 = CamcopsColumn(
"s3c_q4",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Cooking/cleaning (1 no - 5 yes)",
)
s3c_q5 = CamcopsColumn(
"s3c_q5",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Miss school for domestic responsibilities (1 no - 5 yes)",
)
s3c_q6 = CamcopsColumn(
"s3c_q6",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Miss seeing friends for domestic responsibilities "
"(1 no - 5 yes)",
)
s3c_q7 = CamcopsColumn(
"s3c_q7",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents said they couldn't cope (1 no - 5 yes)",
)
s3c_q8 = CamcopsColumn(
"s3c_q8",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents looked to you for help (1 no - 5 yes)",
)
s3c_q9 = CamcopsColumn(
"s3c_q9",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents coped if you were hurt/ill (1 no - 5 yes)",
)
s3c_q10 = CamcopsColumn(
"s3c_q10",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents confided their problems (1 no - 5 yes)",
)
s3c_q11 = CamcopsColumn(
"s3c_q11",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents relied on you for emotional support (1 no - 5 yes)",
)
s3c_q12 = CamcopsColumn(
"s3c_q12",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents cried in front of you (1 no - 5 yes)",
)
s3c_q13 = CamcopsColumn(
"s3c_q13",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Concerned/worried re parent (1 no - 5 yes)",
)
s3c_q14 = CamcopsColumn(
"s3c_q14",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Tried to support/care for parent (1 no - 5 yes)",
)
s3c_q15 = CamcopsColumn(
"s3c_q15",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Try to make parent smile when upset (1 no - 5 yes)",
)
s3c_q16 = CamcopsColumn(
"s3c_q16",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Parents made you feel guilty for their sacrifices "
"(1 no - 5 yes)",
)
s3c_q17 = CamcopsColumn(
"s3c_q17",
Integer,
permitted_value_checker=ONE_TO_FIVE_CHECKER,
comment="Had to keep secrets for parent (1 no - 5 yes)",
)
s3c_which_parent_cared_for = CamcopsColumn(
"s3c_which_parent_cared_for",
Integer,
permitted_value_checker=ZERO_TO_FOUR_CHECKER,
comment="Which parent did you have to provide care for (0 none, "
"1 mother, 2 father, 3 both, 4 other)",
)
s3c_parent_mental_problem = CamcopsColumn(
"s3c_parent_mental_problem",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Parent/s had emotional/mental health problems (0 no - 2 yes)",
)
s3c_parent_physical_problem = CamcopsColumn(
"s3c_parent_physical_problem",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Parent/s had disability/physical illness (0 no - 2 yes)",
)
# -------------------------------------------------------------------------
# Section 4(A)
# -------------------------------------------------------------------------
s4a_adultconfidant = CamcopsColumn(
"s4a_adultconfidant",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant?",
)
s4a_adultconfidant_mother = CamcopsColumn(
"s4a_adultconfidant_mother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant, mother?",
)
s4a_adultconfidant_father = CamcopsColumn(
"s4a_adultconfidant_father",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant, father?",
)
s4a_adultconfidant_otherrelative = CamcopsColumn(
"s4a_adultconfidant_otherrelative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant, other relative?",
)
s4a_adultconfidant_familyfriend = CamcopsColumn(
"s4a_adultconfidant_familyfriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant, family friend?",
)
s4a_adultconfidant_responsibleadult = CamcopsColumn(
"s4a_adultconfidant_responsibleadult",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant, teacher/vicar/etc.?",
)
s4a_adultconfidant_other = CamcopsColumn(
"s4a_adultconfidant_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Adult confidant, other?",
)
s4a_adultconfidant_other_detail = Column(
"s4a_adultconfidant_other_detail",
UnicodeText,
comment="Adult confidant, other, detail",
)
s4a_adultconfidant_additional = Column(
"s4a_adultconfidant_additional",
UnicodeText,
comment="Adult confidant, additional notes",
)
# -------------------------------------------------------------------------
# Section 4(B)
# -------------------------------------------------------------------------
s4b_childconfidant = CamcopsColumn(
"s4b_childconfidant",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant?",
)
s4b_childconfidant_sister = CamcopsColumn(
"s4b_childconfidant_sister",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant, sister?",
)
s4b_childconfidant_brother = CamcopsColumn(
"s4b_childconfidant_brother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant, brother?",
)
s4b_childconfidant_otherrelative = CamcopsColumn(
"s4b_childconfidant_otherrelative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant, other relative?",
)
s4b_childconfidant_closefriend = CamcopsColumn(
"s4b_childconfidant_closefriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant, close friend?",
)
s4b_childconfidant_otherfriend = CamcopsColumn(
"s4b_childconfidant_otherfriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant, other less close friend(s)?",
)
s4b_childconfidant_other = CamcopsColumn(
"s4b_childconfidant_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Child confidant, other person?",
)
s4b_childconfidant_other_detail = Column(
"s4b_childconfidant_other_detail",
UnicodeText,
comment="Child confidant, other person, detail",
)
s4b_childconfidant_additional = Column(
"s4b_childconfidant_additional",
UnicodeText,
comment="Child confidant, additional notes",
)
# -------------------------------------------------------------------------
# Section 4(C)
# -------------------------------------------------------------------------
s4c_closest_mother = CamcopsColumn(
"s4c_closest_mother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: mother?",
)
s4c_closest_father = CamcopsColumn(
"s4c_closest_father",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: father?",
)
s4c_closest_sibling = CamcopsColumn(
"s4c_closest_sibling",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: sibling?",
)
s4c_closest_otherrelative = CamcopsColumn(
"s4c_closest_otherrelative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: other relative?",
)
s4c_closest_adultfriend = CamcopsColumn(
"s4c_closest_adultfriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: adult family friend?",
)
s4c_closest_childfriend = CamcopsColumn(
"s4c_closest_childfriend",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: friend your age?",
)
s4c_closest_other = CamcopsColumn(
"s4c_closest_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Two closest people include: other?",
)
s4c_closest_other_detail = Column(
"s4c_closest_other_detail",
UnicodeText,
comment="Two closest people include: other, detail",
)
s4c_closest_additional = Column(
"s4c_closest_additional",
UnicodeText,
comment="Two closest people include: additional notes",
)
# -------------------------------------------------------------------------
# Section 5(C)
# -------------------------------------------------------------------------
s5c_physicalabuse = CamcopsColumn(
"s5c_physicalabuse",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse?",
)
s5c_abused_by_mother = CamcopsColumn(
"s5c_abused_by_mother",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by mother?",
)
s5c_abused_by_father = CamcopsColumn(
"s5c_abused_by_father",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by father?",
)
s5c_mother_abuse_age_began = CamcopsColumn(
"s5c_mother_abuse_age_began",
Float,
comment="Physical abuse, by mother, age began (y)",
)
s5c_father_abuse_age_began = CamcopsColumn(
"s5c_father_abuse_age_began",
Float,
comment="Physical abuse, by father, age began (y)",
)
s5c_mother_hit_more_than_once = CamcopsColumn(
"s5c_mother_hit_more_than_once",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by mother, hit on >1 occasion",
)
s5c_father_hit_more_than_once = CamcopsColumn(
"s5c_father_hit_more_than_once",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by father, hit on >1 occasion",
)
s5c_mother_hit_how = CamcopsColumn(
"s5c_mother_hit_how",
Integer,
permitted_value_checker=ONE_TO_FOUR_CHECKER,
comment="Physical abuse, by mother, hit how (1 belt/stick, "
"2 punched/kicked, 3 hit with hand, 4 other)",
)
s5c_father_hit_how = CamcopsColumn(
"s5c_father_hit_how",
Integer,
permitted_value_checker=ONE_TO_FOUR_CHECKER,
comment="Physical abuse, by father, hit how (1 belt/stick, "
"2 punched/kicked, 3 hit with hand, 4 other)",
)
s5c_mother_injured = CamcopsColumn(
"s5c_mother_injured",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by mother, injured?",
)
s5c_father_injured = CamcopsColumn(
"s5c_father_injured",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by father, injured?",
)
s5c_mother_out_of_control = CamcopsColumn(
"s5c_mother_out_of_control",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by mother, out of control?",
)
s5c_father_out_of_control = CamcopsColumn(
"s5c_father_out_of_control",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by father, out of control?",
)
s5c_parental_abuse_description = Column(
"s5c_parental_abuse_description",
UnicodeText,
comment="Physical abuse, description",
)
s5c_abuse_by_nonparent = CamcopsColumn(
"s5c_abuse_by_nonparent",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Physical abuse, by anyone else in household?",
)
s5c_nonparent_abuse_description = Column(
"s5c_nonparent_abuse_description",
UnicodeText,
comment="Physical abuse, nonparent, description",
)
# -------------------------------------------------------------------------
# Section 6
# -------------------------------------------------------------------------
s6_any_unwanted_sexual_experience = CamcopsColumn(
# Prior to 2.1.0: was cctype="BOOL" on the server, but this gave
# TINYINT(1), which can store -128 to 128. Corrected to Integer.
"s6_any_unwanted_sexual_experience",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Any unwanted sexual experiences (0 no - 2 yes)",
)
s6_unwanted_intercourse = CamcopsColumn(
# Prior to 2.1.0: was cctype="BOOL" on the server, but this gave
# TINYINT(1), which can store -128 to 128. Corrected to Integer.
"s6_unwanted_intercourse",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Unwanted intercourse before 17yo (0 no - 2 yes)",
)
s6_upsetting_sexual_adult_authority = CamcopsColumn(
# Prior to 2.1.0: was cctype="BOOL" on the server, but this gave
# TINYINT(1), which can store -128 to 128. Corrected to Integer.
"s6_upsetting_sexual_adult_authority",
Integer,
permitted_value_checker=ZERO_TO_TWO_CHECKER,
comment="Upsetting sexual experiences under 17yo with "
"related adult or someone in authority (0 no - 2 yes)",
)
s6_first_age = CamcopsColumn(
"s6_first_age",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Sexual abuse, first experience, age it began",
)
s6_other_age = CamcopsColumn(
"s6_other_age",
Float,
permitted_value_checker=MIN_ZERO_CHECKER,
comment="Sexual abuse, other experience, age it began",
)
s6_first_person_known = CamcopsColumn(
"s6_first_person_known",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, knew the person?",
)
s6_other_person_known = CamcopsColumn(
"s6_other_person_known",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, knew the person?",
)
s6_first_relative = CamcopsColumn(
"s6_first_relative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, person was a relative?",
)
s6_other_relative = CamcopsColumn(
"s6_other_relative",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, person was a relative?",
)
s6_first_in_household = CamcopsColumn(
"s6_first_in_household",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, person lived in household?",
)
s6_other_in_household = CamcopsColumn(
"s6_other_in_household",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, person lived in household?",
)
s6_first_more_than_once = CamcopsColumn(
"s6_first_more_than_once",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, happened more than once?",
)
s6_other_more_than_once = CamcopsColumn(
"s6_other_more_than_once",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, happened more than once?",
)
s6_first_touch_privates_subject = CamcopsColumn(
"s6_first_touch_privates_subject",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, touched your private parts?",
)
s6_other_touch_privates_subject = CamcopsColumn(
"s6_other_touch_privates_subject",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, touched your private parts?",
)
s6_first_touch_privates_other = CamcopsColumn(
"s6_first_touch_privates_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, touched their private parts?",
)
s6_other_touch_privates_other = CamcopsColumn(
"s6_other_touch_privates_other",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, touched their private parts?",
)
s6_first_intercourse = CamcopsColumn(
"s6_first_intercourse",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, first experience, sexual intercourse?",
)
s6_other_intercourse = CamcopsColumn(
"s6_other_intercourse",
Boolean,
permitted_value_checker=BIT_CHECKER,
comment="Sexual abuse, other experience, sexual intercourse?",
)
s6_unwanted_sexual_description = Column(
"s6_unwanted_sexual_description",
UnicodeText,
comment="Sexual abuse, description",
)
# -------------------------------------------------------------------------
# Final
# -------------------------------------------------------------------------
any_other_comments = CamcopsColumn(
"any_other_comments", UnicodeText, comment="Any other comments"
)
[docs] @staticmethod
def longname(req: "CamcopsRequest") -> str:
_ = req.gettext
return _("Childhood Experience of Care and Abuse Questionnaire")
[docs] def get_summaries(self, req: CamcopsRequest) -> List[SummaryElement]:
return self.standard_task_summary_fields() + [
SummaryElement(
name="parental_loss_risk",
coltype=Boolean(),
value=self.parental_loss_risk(),
comment="Parental loss risk factor?",
),
SummaryElement(
name="parental_loss_high_risk",
coltype=Boolean(),
value=self.parental_loss_high_risk(),
comment="Parental loss higher risk factor?",
),
SummaryElement(
name="mother_antipathy",
coltype=Integer(),
value=self.mother_antipathy(),
comment="Maternal antipathy score (8-40)",
),
SummaryElement(
name="mother_neglect",
coltype=Integer(),
value=self.mother_neglect(),
comment="Maternal neglect score (8-40)",
),
SummaryElement(
name="mother_psychological_abuse",
coltype=Integer(),
value=self.mother_psychological_abuse(),
comment="Maternal psychological abuse score (0-85)",
),
SummaryElement(
name="father_antipathy",
coltype=Integer(),
value=self.father_antipathy(),
comment="Paternal antipathy score (8-40)",
),
SummaryElement(
name="father_neglect",
coltype=Integer(),
value=self.father_neglect(),
comment="Paternal neglect score (8-40)",
),
SummaryElement(
name="father_psychological_abuse",
coltype=Integer(),
value=self.father_psychological_abuse(),
comment="Paternal psychological abuse score (0-85)",
),
SummaryElement(
name="role_reversal",
coltype=Integer(),
value=self.role_reversal(),
comment="Role reversal score (17-85)",
),
SummaryElement(
name="physical_abuse_screen",
coltype=Integer(),
value=self.physical_abuse_screen(),
comment="Physical abuse screen (0-1)",
),
SummaryElement(
name="physical_abuse_severity_mother",
coltype=Integer(),
value=self.physical_abuse_severity_mother(),
comment="Maternal physical abuse severity score (0-4)",
),
SummaryElement(
name="physical_abuse_severity_father",
coltype=Integer(),
value=self.physical_abuse_severity_father(),
comment="Paternal physical abuse severity score (0-4)",
),
SummaryElement(
name="sexual_abuse_screen",
coltype=Integer(),
value=self.sexual_abuse_screen(),
comment="Sexual abuse screen (0-3)",
),
SummaryElement(
name="sexual_abuse_score_first",
coltype=Integer(),
value=self.sexual_abuse_score_first(),
comment="First sexual abuse severity score (0-7)",
),
SummaryElement(
name="sexual_abuse_score_other",
coltype=Integer(),
value=self.sexual_abuse_score_other(),
comment="Other sexual abuse severity score (0-7)",
),
]
# -------------------------------------------------------------------------
# Complete?
# -------------------------------------------------------------------------
[docs] def is_complete(self) -> bool:
return (
self.complete_1a()
and self.complete_1b()
and self.complete_1c()
and self.complete_2a()
and self.complete_2b()
and self.complete_3a()
and self.complete_3b()
and self.complete_3c()
and self.complete_4a()
and self.complete_4b()
and self.complete_4c()
and self.complete_5()
and self.complete_6()
and self.field_contents_valid()
)
def is_at_least_one_field_true(self, fields: List[str]) -> bool:
for f in fields:
if getattr(self, f):
return True
return True
def complete_1a(self) -> bool:
if not self.is_at_least_one_field_true(
[
"s1a_motherfigure_birthmother",
"s1a_motherfigure_stepmother",
"s1a_motherfigure_femalerelative",
"s1a_motherfigure_familyfriend",
"s1a_motherfigure_fostermother",
"s1a_motherfigure_adoptivemother",
"s1a_motherfigure_other",
"s1a_fatherfigure_birthfather",
"s1a_fatherfigure_stepfather",
"s1a_fatherfigure_malerelative",
"s1a_fatherfigure_familyfriend",
"s1a_fatherfigure_fosterfather",
"s1a_fatherfigure_adoptivefather",
"s1a_fatherfigure_other",
]
):
return False
if (
self.s1a_motherfigure_other
and not self.s1a_motherfigure_other_detail
):
return False
if (
self.s1a_motherfigure_femalerelative
and not self.s1a_motherfigure_femalerelative_detail
):
return False
if (
self.s1a_fatherfigure_other
and not self.s1a_fatherfigure_other_detail
):
return False
if (
self.s1a_fatherfigure_malerelative
and not self.s1a_fatherfigure_malerelative_detail
):
return False
return True
def complete_1b(self) -> bool:
if self.s1b_institution is None:
return False
if self.s1b_institution and self.s1b_institution_time_years is None:
return False
return True
def complete_1c(self) -> bool:
if self.s1c_mother_died is None or self.s1c_father_died is None:
return False
if self.s1c_mother_died and self.s1c_mother_died_subject_aged is None:
return False
if self.s1c_father_died and self.s1c_father_died_subject_aged is None:
return False
if (
self.s1c_separated_from_mother is None
or self.s1c_separated_from_father is None
):
return False
if self.s1c_separated_from_mother:
if self.any_fields_none(
[
"s1c_first_separated_from_mother_aged",
"s1c_mother_how_long_first_separation_years",
"s1c_mother_separation_reason",
]
):
return False
if self.s1c_separated_from_father:
if self.any_fields_none(
[
"s1c_first_separated_from_father_aged",
"s1c_father_how_long_first_separation_years",
"s1c_father_separation_reason",
]
):
return False
return True
def complete_2a(self) -> bool:
if self.s2a_which_mother_figure is None:
return False
if self.s2a_which_mother_figure == 0:
return True
if (
self.s2a_which_mother_figure == 5
and self.s2a_which_mother_figure_other_detail is None
):
return False
for i in range(1, 16): # not q16 (siblings)
if getattr(self, "s2a_q" + str(i)) is None:
return False
return True
def complete_2b(self) -> bool:
abuse = False
if self.s2a_which_mother_figure == 0:
return True
for i in range(1, 18):
if getattr(self, "s2b_q" + str(i)) is None:
return False
if getattr(self, "s2b_q" + str(i)) != 0:
abuse = True
if getattr(self, "s2b_q" + str(i) + "_frequency") is None:
return False
if abuse and self.s2b_age_began is None:
return False
return True
def complete_3a(self):
if self.s3a_which_father_figure is None:
return False
if self.s3a_which_father_figure == 0:
return True
if (
self.s3a_which_father_figure == 5
and self.s3a_which_father_figure_other_detail is None
):
return False
for i in range(1, 16): # not q16 (siblings)
if getattr(self, "s3a_q" + str(i)) is None:
return False
return True
def complete_3b(self) -> bool:
abuse = False
if self.s3a_which_father_figure == 0:
return True
for i in range(1, 18):
if getattr(self, "s3b_q" + str(i)) is None:
return False
if getattr(self, "s3b_q" + str(i)) != 0:
abuse = True
if getattr(self, "s3b_q" + str(i) + "_frequency") is None:
return False
if abuse and self.s3b_age_began is None:
return False
return True
def complete_3c(self) -> bool:
return self.all_fields_not_none(
[
"s3c_q1",
"s3c_q2",
"s3c_q3",
"s3c_q4",
"s3c_q5",
"s3c_q6",
"s3c_q7",
"s3c_q8",
"s3c_q9",
"s3c_q10",
"s3c_q11",
"s3c_q12",
"s3c_q13",
"s3c_q14",
"s3c_q15",
"s3c_q16",
"s3c_q17",
"s3c_which_parent_cared_for",
"s3c_parent_mental_problem",
"s3c_parent_physical_problem",
]
)
def complete_4a(self) -> bool:
if self.s4a_adultconfidant is None:
return False
if not self.s4a_adultconfidant:
return True
if not self.is_at_least_one_field_true(
[
"s4a_adultconfidant_mother",
"s4a_adultconfidant_father",
"s4a_adultconfidant_otherrelative",
"s4a_adultconfidant_familyfriend",
"s4a_adultconfidant_responsibleadult",
"s4a_adultconfidant_other",
]
):
return False
if (
self.s4a_adultconfidant_other
and not self.s4a_adultconfidant_other_detail
):
return False
return True
def complete_4b(self) -> bool:
if self.s4b_childconfidant is None:
return False
if not self.s4b_childconfidant:
return True
if not self.is_at_least_one_field_true(
[
"s4b_childconfidant_sister",
"s4b_childconfidant_brother",
"s4b_childconfidant_otherrelative",
"s4b_childconfidant_closefriend",
"s4b_childconfidant_otherfriend",
"s4b_childconfidant_other",
]
):
return False
if (
self.s4b_childconfidant_other
and not self.s4b_childconfidant_other_detail
):
return False
return True
def complete_4c(self) -> bool:
n = 0
if self.s4c_closest_mother:
n += 1
if self.s4c_closest_father:
n += 1
if self.s4c_closest_sibling:
n += 1
if self.s4c_closest_otherrelative:
n += 1
if self.s4c_closest_adultfriend:
n += 1
if self.s4c_closest_childfriend:
n += 1
if self.s4c_closest_other:
n += 1
if n < 2:
return False
if self.s4c_closest_other and not self.s4c_closest_other_detail:
return False
return True
def complete_5(self) -> bool:
if self.s5c_physicalabuse is None:
return False
if self.s5c_physicalabuse == 0:
return True
if (
self.s5c_abused_by_mother is None
or self.s5c_abused_by_father is None
or self.s5c_abuse_by_nonparent is None
):
return False
if self.s5c_abused_by_mother:
if self.any_fields_none(
[
"s5c_mother_abuse_age_began",
"s5c_mother_hit_more_than_once",
"s5c_mother_hit_how",
"s5c_mother_injured",
"s5c_mother_out_of_control",
]
):
return False
if self.s5c_abused_by_father:
if self.any_fields_none(
[
"s5c_father_abuse_age_began",
"s5c_father_hit_more_than_once",
"s5c_father_hit_how",
"s5c_father_injured",
"s5c_father_out_of_control",
]
):
return False
if (
self.s5c_abuse_by_nonparent
and not self.s5c_nonparent_abuse_description
):
return False
return True
def complete_6(self) -> bool:
if (
self.s6_any_unwanted_sexual_experience is None
or self.s6_unwanted_intercourse is None
or self.s6_upsetting_sexual_adult_authority is None
):
return False
if (
self.s6_any_unwanted_sexual_experience == 0
and self.s6_unwanted_intercourse == 0
and self.s6_upsetting_sexual_adult_authority == 0
):
return True
if self.any_fields_none(
[
"s6_first_age",
"s6_first_person_known",
"s6_first_relative",
"s6_first_in_household",
"s6_first_more_than_once",
"s6_first_touch_privates_subject",
"s6_first_touch_privates_other",
"s6_first_intercourse",
]
):
return False
# no checks for "other experience"
return True
# -------------------------------------------------------------------------
# Scoring
# -------------------------------------------------------------------------
def total_sum_abort_if_none(self, fields: List[str]) -> Optional[int]:
total = 0
for field in fields:
value = getattr(self, field)
if value is None:
return None
total += value
return total
def total_nonzero_scores_1_abort_if_none(
self, fields: Sequence[str]
) -> Optional[int]:
total = 0
for field in fields:
value = getattr(self, field)
if value is None:
return None
if value:
total += 1
return total
def parental_loss_risk(self) -> bool:
return bool(
self.s1c_mother_died
or self.s1c_father_died
or self.s1c_separated_from_mother
or self.s1c_separated_from_father
)
def parental_loss_high_risk(self) -> bool:
return bool(
self.s1c_separated_from_mother
and (
self.s1c_mother_separation_reason == 5
or self.s1c_mother_separation_reason == 6
)
or self.s1c_separated_from_father
and (
self.s1c_father_separation_reason == 5
or self.s1c_father_separation_reason == 6
)
)
def mother_antipathy(self) -> Optional[int]:
if self.s2a_which_mother_figure == 0:
return None
total = 0
for i in (1, 4, 6, 8, 9, 10, 11, 16):
score = getattr(self, "s2a_q" + str(i))
if i == 16 and score is None:
# Q16 is allowed to be blank (if no siblings)
score = 0
if score is None:
return None
if i in (8, 11):
score = 6 - score # reverse
total += score
return total
def father_antipathy(self) -> Optional[int]:
if self.s3a_which_father_figure == 0:
return None
total = 0
for i in (1, 4, 6, 8, 9, 10, 11, 16):
score = getattr(self, "s3a_q" + str(i))
if i == 16 and score is None:
# Q16 is allowed to be blank (if no siblings)
score = 0
if score is None:
return None
if i in (8, 11):
score = 6 - score # reverse
total += score
return total
def mother_neglect(self) -> Optional[int]:
if self.s2a_which_mother_figure == 0:
return None
total = 0
for i in (2, 3, 5, 7, 12, 13, 14, 15):
score = getattr(self, "s2a_q" + str(i))
if score is None:
return None
if i in (2, 3, 5, 12, 13, 14):
score = 6 - score # reverse
total += score
return total
def father_neglect(self) -> Optional[int]:
if self.s3a_which_father_figure == 0:
return None
total = 0
for i in (2, 3, 5, 7, 12, 13, 14, 15):
score = getattr(self, "s3a_q" + str(i))
if score is None:
return None
if i in (2, 3, 5, 12, 13, 14):
score = 6 - score # reverse
total += score
return total
def mother_psychological_abuse(self) -> Optional[int]:
if self.s2a_which_mother_figure == 0:
return None
total = 0
for i in range(1, 18):
score = getattr(self, "s2b_q" + str(i))
if score is None:
return None
total += score
freqscore = getattr(self, "s2b_q" + str(i) + "_frequency")
if score != 0 and freqscore is None:
return None
if freqscore is not None:
total += freqscore
return total
def father_psychological_abuse(self) -> Optional[int]:
if self.s3a_which_father_figure == 0:
return None
total = 0
for i in range(1, 18):
score = getattr(self, "s3b_q" + str(i))
if score is None:
return None
total += score
freqscore = getattr(self, "s3b_q" + str(i) + "_frequency")
if score != 0 and freqscore is None:
return None
if freqscore is not None:
total += freqscore
return total
def role_reversal(self) -> Optional[int]:
total = 0
for i in range(1, 18):
score = getattr(self, "s3c_q" + str(i))
if score is None:
return None
total += score
return total
def physical_abuse_screen(self) -> Optional[int]:
fields = (
"s5c_physicalabuse",
) # tuple of length 1 -- requires the comma
return self.total_nonzero_scores_1_abort_if_none(fields)
def physical_abuse_severity_mother(self) -> Optional[int]:
if self.physical_abuse_screen() == 0:
return 0
if self.s5c_abused_by_mother == 0:
return 0
mainfields = (
"s5c_mother_hit_more_than_once",
"s5c_mother_injured",
"s5c_mother_out_of_control",
)
total = self.total_nonzero_scores_1_abort_if_none(mainfields)
if total is None:
return None
if self.s5c_mother_hit_how is None:
return None
if self.s5c_mother_hit_how == 1 or self.s5c_mother_hit_how == 2:
total += 1
return total
def physical_abuse_severity_father(self) -> Optional[int]:
if self.physical_abuse_screen() == 0:
return 0
if self.s5c_abused_by_father == 0:
return 0
mainfields = (
"s5c_father_hit_more_than_once",
"s5c_father_injured",
"s5c_father_out_of_control",
)
total = self.total_nonzero_scores_1_abort_if_none(mainfields)
if total is None:
return None
if self.s5c_father_hit_how is None:
return None
if self.s5c_father_hit_how == 1 or self.s5c_father_hit_how == 2:
total += 1
return total
def sexual_abuse_screen(self) -> Optional[int]:
fields = (
"s6_any_unwanted_sexual_experience",
"s6_unwanted_intercourse",
"s6_upsetting_sexual_adult_authority",
)
return self.total_nonzero_scores_1_abort_if_none(fields)
def sexual_abuse_score_first(self) -> Optional[int]:
if self.sexual_abuse_screen() == 0:
return 0
fields = (
"s6_first_person_known",
"s6_first_relative",
"s6_first_in_household",
"s6_first_more_than_once",
"s6_first_touch_privates_subject",
"s6_first_touch_privates_other",
"s6_first_intercourse",
)
return self.total_nonzero_scores_1_abort_if_none(fields)
def sexual_abuse_score_other(self) -> Optional[int]:
if self.sexual_abuse_screen() == 0:
return 0
fields = (
"s6_other_person_known",
"s6_other_relative",
"s6_other_in_household",
"s6_other_more_than_once",
"s6_other_touch_privates_subject",
"s6_other_touch_privates_other",
"s6_other_intercourse",
)
return self.total_nonzero_scores_1_abort_if_none(fields)
# -------------------------------------------------------------------------
# HTML
# -------------------------------------------------------------------------
[docs] def get_task_html(self, req: CamcopsRequest) -> str:
def wxstring(wstringname: str) -> str:
return self.wxstring(req, wstringname)
def subheading_from_wstring(wstringname: str) -> str:
return subheading_from_string(self.wxstring(req, wstringname))
def subsubheading_from_wstring(wstringname: str) -> str:
return subsubheading_from_string(self.wxstring(req, wstringname))
def wstring_boolean(wstring: str, value: Any) -> str:
return string_boolean_(req, self.wxstring(req, wstring), value)
def wstring_numeric(wstring: str, value: Any) -> str:
return string_numeric(self.wxstring(req, wstring), value)
def wstring_string(wstring: str, value: str) -> str:
return string_string(self.wxstring(req, wstring), value)
def wstring_dict(wstring: str, value: Any, d: Dict) -> str:
return string_dict(self.wxstring(req, wstring), value, d)
def string_boolean(string: str, value: Any) -> str:
return string_boolean_(req, string, value)
separation_map = {
None: None,
1: "1 — " + wxstring("1c_separation_reason1"),
2: "2 — " + wxstring("1c_separation_reason2"),
3: "3 — " + wxstring("1c_separation_reason3"),
4: "4 — " + wxstring("1c_separation_reason4"),
5: "5 — " + wxstring("1c_separation_reason5"),
6: "6 — " + wxstring("1c_separation_reason6"),
}
motherfigure_map = {
None: None,
0: "0 — " + wxstring("2a_which_option0"),
1: "1 — " + wxstring("2a_which_option1"),
2: "2 — " + wxstring("2a_which_option2"),
3: "3 — " + wxstring("2a_which_option3"),
4: "4 — " + wxstring("2a_which_option4"),
5: "5 — " + wxstring("2a_which_option5"),
}
fatherfigure_map = {
None: None,
0: "0 — " + wxstring("3a_which_option0"),
1: "1 — " + wxstring("3a_which_option1"),
2: "2 — " + wxstring("3a_which_option2"),
3: "3 — " + wxstring("3a_which_option3"),
4: "4 — " + wxstring("3a_which_option4"),
5: "5 — " + wxstring("3a_which_option5"),
}
no_yes_5way_map = {
None: None,
1: "1 — " + wxstring("options5way_notoyes_1"),
2: "2 — (between not-at-all and unsure)",
3: "3 — " + wxstring("options5way_notoyes_3"),
4: "4 — (between unsure and yes-definitely)",
5: "5 — " + wxstring("options5way_notoyes_5"),
}
no_yes_3way_map = {
None: None,
0: "0 — " + wxstring("options3way_noto_yes_0"),
1: "1 — " + wxstring("options3way_noto_yes_1"),
2: "2 — " + wxstring("options3way_noto_yes_2"),
}
frequency_map = {
None: None,
0: "0 — " + wxstring("optionsfrequency0"),
1: "1 — " + wxstring("optionsfrequency1"),
2: "2 — " + wxstring("optionsfrequency2"),
3: "3 — " + wxstring("optionsfrequency3"),
}
parent_cared_for_map = {
None: None,
0: "0 — " + wxstring("3c_whichparentcaredfor_option0"),
1: "1 — " + wxstring("3c_whichparentcaredfor_option1"),
2: "2 — " + wxstring("3c_whichparentcaredfor_option2"),
3: "3 — " + wxstring("3c_whichparentcaredfor_option3"),
4: "4 — " + wxstring("3c_whichparentcaredfor_option4"),
}
hitting_map = {
None: None,
1: "1 — " + wxstring("5_hit_option_1"),
2: "2 — " + wxstring("5_hit_option_2"),
3: "3 — " + wxstring("5_hit_option_3"),
4: "4 — " + wxstring("5_hit_option_4"),
}
html = (
f"""
<div class="{CssClass.SUMMARY}">
<table class="{CssClass.SUMMARY}">
"""
+ self.get_is_complete_tr(req)
+ tr_qa(
"Parental loss risk factor? <sup>[1]</sup>",
get_yes_no(req, self.parental_loss_risk()),
)
+ tr_qa(
"Parental loss higher risk factor? <sup>[2]</sup>",
get_yes_no(req, self.parental_loss_high_risk()),
)
+ tr_qa(
"Maternal antipathy score (8–40) <sup>[3]</sup>",
self.mother_antipathy(),
)
+ tr_qa(
"Maternal neglect score (8–40) <sup>[3]</sup>",
self.mother_neglect(),
)
+ tr_qa(
"Maternal psychological abuse score (0–85) <sup>[4]</sup>",
self.mother_psychological_abuse(),
)
+ tr_qa(
"Paternal antipathy score (8–40) <sup>[3]</sup>",
self.father_antipathy(),
)
+ tr_qa(
"Paternal neglect score (8–40) <sup>[3]</sup>",
self.father_neglect(),
)
+ tr_qa(
"Paternal psychological abuse score (0–85) <sup>[4]</sup>",
self.father_psychological_abuse(),
)
+ tr_qa(
"Role reversal score (17–85) <sup>[5]</sup>",
self.role_reversal(),
)
+ tr_qa(
"Physical abuse screen (0–1) <sup>[6]</sup>",
self.physical_abuse_screen(),
)
+ tr_qa(
"Maternal physical abuse severity score (0–4) "
"<sup>[6]</sup>",
self.physical_abuse_severity_mother(),
)
+ tr_qa(
"Paternal physical abuse severity score (0–4) "
"<sup>[6]</sup>",
self.physical_abuse_severity_father(),
)
+ tr_qa(
"Sexual abuse screen (0–3) <sup>[7]</sup>",
self.sexual_abuse_screen(),
)
+ tr_qa(
"First sexual abuse severity score (0–7) <sup>[7]</sup>",
self.sexual_abuse_score_first(),
)
+ tr_qa(
"Other sexual abuse severity score (0–7) <sup>[7]</sup>",
self.sexual_abuse_score_other(),
)
+ f"""
</table>
</div>
<table class="{CssClass.TASKDETAIL}">
"""
+ subheading_spanning_two_columns("1A: " + wxstring("1a_q"))
+ subsubheading_from_wstring("1a_motherfigures")
+ wstring_boolean(
"1a_mf_birthmother", self.s1a_motherfigure_birthmother
)
+ wstring_boolean(
"1a_mf_stepmother", self.s1a_motherfigure_stepmother
)
+ wstring_boolean(
"1a_mf_femalerelative", self.s1a_motherfigure_femalerelative
)
+ string_string(
"(Female relative details)",
self.s1a_motherfigure_femalerelative_detail,
)
+ wstring_boolean(
"1a_mf_familyfriend", self.s1a_motherfigure_familyfriend
)
+ wstring_boolean(
"1a_mf_fostermother", self.s1a_motherfigure_fostermother
)
+ wstring_boolean(
"1a_mf_adoptivemother", self.s1a_motherfigure_adoptivemother
)
+ wstring_boolean("other", self.s1a_motherfigure_other)
+ string_string(
"(Other, details)", self.s1a_motherfigure_other_detail
)
+ subsubheading_from_wstring("1a_fatherfigures")
+ wstring_boolean(
"1a_ff_birthfather", self.s1a_fatherfigure_birthfather
)
+ wstring_boolean(
"1a_ff_stepfather", self.s1a_fatherfigure_stepfather
)
+ wstring_boolean(
"1a_ff_malerelative", self.s1a_fatherfigure_malerelative
)
+ string_string(
"(Male relative details)",
self.s1a_fatherfigure_malerelative_detail,
)
+ wstring_boolean(
"1a_ff_familyfriend", self.s1a_fatherfigure_familyfriend
)
+ wstring_boolean(
"1a_ff_fosterfather", self.s1a_fatherfigure_fosterfather
)
+ wstring_boolean(
"1a_ff_adoptivefather", self.s1a_fatherfigure_adoptivefather
)
+ wstring_boolean("other", self.s1a_fatherfigure_other)
+ string_string(
"(Other, details)", self.s1a_fatherfigure_other_detail
)
+ subheading_from_string("1B: " + wxstring("1b_q"))
+ wstring_boolean("1b_q", self.s1b_institution)
+ wstring_numeric("1b_q_how_long", self.s1b_institution_time_years)
+ subheading_from_string("1C: " + wxstring("1c_heading"))
+ subsubheading_from_wstring("mother")
+ string_boolean("Mother died before age 17", self.s1c_mother_died)
+ wstring_numeric(
"1c_parentdiedage", self.s1c_mother_died_subject_aged
)
+ string_boolean(
"Separated from mother for >1y", self.s1c_separated_from_mother
)
+ wstring_numeric(
"1c_age_first_separated",
self.s1c_first_separated_from_mother_aged,
)
+ wstring_numeric(
"1c_how_long_separation",
self.s1c_mother_how_long_first_separation_years,
)
+ wstring_dict(
"1c_separation_reason",
self.s1c_mother_separation_reason,
separation_map,
)
+ subsubheading_from_wstring("father")
+ string_boolean("Father died before age 17", self.s1c_father_died)
+ wstring_numeric(
"1c_parentdiedage", self.s1c_father_died_subject_aged
)
+ string_boolean(
"Separated from father for >1y", self.s1c_separated_from_father
)
+ wstring_numeric(
"1c_age_first_separated",
self.s1c_first_separated_from_father_aged,
)
+ wstring_numeric(
"1c_how_long_separation",
self.s1c_father_how_long_first_separation_years,
)
+ wstring_dict(
"1c_separation_reason",
self.s1c_father_separation_reason,
separation_map,
)
+ wstring_string(
"please_describe_experience", self.s1c_describe_experience
)
+ subheading_from_string("2A: " + wxstring("2a_heading"))
+ wstring_dict(
"2a_which", self.s2a_which_mother_figure, motherfigure_map
)
+ wstring_string(
"rnc_if_other_describe",
self.s2a_which_mother_figure_other_detail,
)
)
for i in range(1, 17):
html += string_dict(
str(i) + ". " + wxstring("2a_q" + str(i)),
getattr(self, "s2a_q" + str(i)),
no_yes_5way_map,
)
html += wstring_string(
"2a_add_anything", self.s2a_extra
) + subheading_from_string("2B: " + wxstring("2b_heading"))
for i in range(1, 18):
html += tr(
str(i) + ". " + wxstring("2b_q" + str(i)),
answer(
get_from_dict(
no_yes_3way_map, getattr(self, "s2b_q" + str(i))
)
)
+ " ("
+ answer(
get_from_dict(
frequency_map,
getattr(self, "s2b_q" + str(i) + "_frequency"),
)
)
+ ")",
)
html += (
wstring_boolean("if_any_what_age", self.s2b_age_began)
+ wstring_string("is_there_more_you_want_to_say", self.s2b_extra)
+ subheading_from_string("3A: " + wxstring("3a_heading"))
+ wstring_dict(
"2a_which", self.s3a_which_father_figure, fatherfigure_map
)
+ wstring_string(
"rnc_if_other_describe",
self.s3a_which_father_figure_other_detail,
)
)
for i in range(1, 17):
html += string_dict(
str(i) + ". " + wxstring("3a_q" + str(i)),
getattr(self, "s3a_q" + str(i)),
no_yes_5way_map,
)
html += wstring_string(
"3a_add_anything", self.s3a_extra
) + subheading_from_string("3B: " + wxstring("3b_heading"))
for i in range(1, 18):
html += tr(
str(i) + ". " + wxstring("3b_q" + str(i)),
answer(
get_from_dict(
no_yes_3way_map, getattr(self, "s3b_q" + str(i))
)
)
+ " ("
+ answer(
get_from_dict(
frequency_map,
getattr(self, "s3b_q" + str(i) + "_frequency"),
)
)
+ ")",
)
html += (
wstring_boolean("if_any_what_age", self.s3b_age_began)
+ wstring_string("is_there_more_you_want_to_say", self.s3b_extra)
+ subheading_from_string("3C: " + wxstring("3c_heading"))
)
for i in range(1, 18):
html += string_dict(
str(i) + ". " + wxstring("3c_q" + str(i)),
getattr(self, "s3c_q" + str(i)),
no_yes_5way_map,
)
html += (
wstring_dict(
"3c_which_parent_cared_for",
self.s3c_which_parent_cared_for,
parent_cared_for_map,
)
+ wstring_boolean(
"3c_parent_mental_problem", self.s3c_parent_mental_problem
)
+ wstring_boolean(
"3c_parent_physical_problem", self.s3c_parent_physical_problem
)
+ subheading_from_string("4: " + wxstring("4_heading"))
+ subsubheading_from_string("(Adult confidant)")
+ wstring_boolean("4a_q", self.s4a_adultconfidant)
+ subsubheading_from_wstring("4_if_so_who")
+ wstring_boolean(
"4a_option_mother", self.s4a_adultconfidant_mother
)
+ wstring_boolean(
"4a_option_father", self.s4a_adultconfidant_father
)
+ wstring_boolean(
"4a_option_relative", self.s4a_adultconfidant_otherrelative
)
+ wstring_boolean(
"4a_option_friend", self.s4a_adultconfidant_familyfriend
)
+ wstring_boolean(
"4a_option_responsibleadult",
self.s4a_adultconfidant_responsibleadult,
)
+ wstring_boolean("4a_option_other", self.s4a_adultconfidant_other)
+ string_string(
"(Other, details)", self.s4a_adultconfidant_other_detail
)
+ wstring_string(
"4_note_anything", self.s4a_adultconfidant_additional
)
+ subsubheading_from_string("(Child confidant)")
+ wstring_boolean("4b_q", self.s4b_childconfidant)
+ subsubheading_from_wstring("4_if_so_who")
+ wstring_boolean(
"4b_option_sister", self.s4b_childconfidant_sister
)
+ wstring_boolean(
"4b_option_brother", self.s4b_childconfidant_brother
)
+ wstring_boolean(
"4b_option_relative", self.s4b_childconfidant_otherrelative
)
+ wstring_boolean(
"4b_option_closefriend", self.s4b_childconfidant_closefriend
)
+ wstring_boolean(
"4b_option_otherfriend", self.s4b_childconfidant_otherfriend
)
+ wstring_boolean("4b_option_other", self.s4b_childconfidant_other)
+ string_string(
"(Other, details)", self.s4b_childconfidant_other_detail
)
+ wstring_string(
"4_note_anything", self.s4b_childconfidant_additional
)
+ subsubheading_from_wstring("4c_q")
+ wstring_boolean("4c_option_mother", self.s4c_closest_mother)
+ wstring_boolean("4c_option_father", self.s4c_closest_father)
+ string_boolean("4c_option_sibling", self.s4c_closest_sibling)
+ wstring_boolean(
"4c_option_relative", self.s4c_closest_otherrelative
)
+ wstring_boolean(
"4c_option_adultfriend", self.s4c_closest_adultfriend
)
+ wstring_boolean(
"4c_option_youngfriend", self.s4c_closest_childfriend
)
+ wstring_boolean("4c_option_other", self.s4c_closest_other)
+ string_string("(Other, details)", self.s4c_closest_other_detail)
+ wstring_string("4_note_anything", self.s4c_closest_additional)
+ subheading_from_string("4: " + wxstring("5_heading"))
+ wstring_boolean("5_mainq", self.s5c_physicalabuse)
+ subsubheading_from_wstring("5_motherfigure")
+ wstring_boolean(
"5_did_this_person_hurt_you", self.s5c_abused_by_mother
)
+ wstring_numeric("5_how_old", self.s5c_mother_abuse_age_began)
+ wstring_boolean(
"5_hit_more_than_once", self.s5c_mother_hit_more_than_once
)
+ wstring_dict("5_how_hit", self.s5c_mother_hit_how, hitting_map)
+ wstring_boolean("5_injured", self.s5c_mother_injured)
+ wstring_boolean("5_outofcontrol", self.s5c_mother_out_of_control)
+ subsubheading_from_wstring("5_fatherfigure")
+ wstring_boolean(
"5_did_this_person_hurt_you", self.s5c_abused_by_father
)
+ wstring_numeric("5_how_old", self.s5c_father_abuse_age_began)
+ wstring_boolean(
"5_hit_more_than_once", self.s5c_father_hit_more_than_once
)
+ wstring_dict("5_how_hit", self.s5c_father_hit_how, hitting_map)
+ wstring_boolean("5_injured", self.s5c_father_injured)
+ wstring_boolean("5_outofcontrol", self.s5c_father_out_of_control)
+ wstring_string(
"5_can_you_describe_1", self.s5c_parental_abuse_description
)
+ subsubheading_from_string("(Other in household)")
+ wstring_boolean("5_anyone_else", self.s5c_abuse_by_nonparent)
+ wstring_string(
"5_can_you_describe_2", self.s5c_nonparent_abuse_description
)
+ subheading_from_string("6: " + wxstring("6_heading"))
+ wstring_dict(
"6_any_unwanted",
self.s6_any_unwanted_sexual_experience,
no_yes_3way_map,
)
+ wstring_dict(
"6_intercourse", self.s6_unwanted_intercourse, no_yes_3way_map
)
+ wstring_dict(
"6_upset_adult_authority",
self.s6_upsetting_sexual_adult_authority,
no_yes_3way_map,
)
+ subsubheading_from_wstring("6_first_experience")
+ wstring_numeric("6_q1", self.s6_first_age)
+ wstring_boolean("6_q2", self.s6_first_person_known)
+ wstring_boolean("6_q3", self.s6_first_relative)
+ wstring_boolean("6_q4", self.s6_first_in_household)
+ wstring_boolean("6_q5", self.s6_first_more_than_once)
+ wstring_boolean("6_q6", self.s6_first_touch_privates_subject)
+ wstring_boolean("6_q7", self.s6_first_touch_privates_other)
+ wstring_boolean("6_q8", self.s6_first_intercourse)
+ subsubheading_from_wstring("6_other_experience")
+ wstring_numeric("6_q1", self.s6_other_age)
+ wstring_boolean("6_q2", self.s6_other_person_known)
+ wstring_boolean("6_q3", self.s6_other_relative)
+ wstring_boolean("6_q4", self.s6_other_in_household)
+ wstring_boolean("6_q5", self.s6_other_more_than_once)
+ wstring_boolean("6_q6", self.s6_other_touch_privates_subject)
+ wstring_boolean("6_q7", self.s6_other_touch_privates_other)
+ wstring_boolean("6_q8", self.s6_other_intercourse)
+ wstring_string(
"5_can_you_describe_1", self.s6_unwanted_sexual_description
)
+ subheading_from_wstring("any_other_comments")
+ wstring_string("any_other_comments", self.any_other_comments)
+ f"""
</table>
<div class="{CssClass.FOOTNOTES}">
[1] Death of mother/father before age 17 or continuous
separation of ≥1 year.
[2] Reason for loss ‘abandonment’ or ‘other’.
[3] Section 2A and 3A contain antipathy and neglect scales.
Antipathy scales: reverse items 8, 11;
then sum 1, 4, 6, 8–11, 16.
Neglect scales: reverse items 2, 3, 5, 12–14;
then sum 2, 3, 5, 7, 12–15.
[4] Psychological abuse scores (sections 2B, 3B):
sum of items 1–17 (yes=2, unsure=1, no=0) with
frequencies (never=0, once=1, rarely=2, often=3).
Any score >1 is a risk indicator.
[5] Role reversal: sum of scores from section 3C.
[6] Physical abuse (section 4): first question (screen
item) is scored 0/1. For each parent, score 1 for
{{>1 occasion, {{belt/stick/punch/kick}}, injured,
out-of-control}}.
[7] Sexual abuse (section 6): no=0, unsure=1, yes=1.
First three questions are the screen.
</div>
"""
)
return html
# =============================================================================
# More helper functions
# =============================================================================
def subheading_from_string(s: str) -> str:
return subheading_spanning_two_columns(s)
def subsubheading_from_string(s: str) -> str:
return f'<tr><td></td><td class="{CssClass.SUBHEADING}">{s}</td></tr>'
def row(label: str, value: Any, default: str = "") -> str:
return tr_qa(label, value, default=default)
def string_boolean_(req: CamcopsRequest, string: str, value: Any) -> str:
return row(string, get_yes_no_none(req, value))
def string_numeric(string: str, value: Any) -> str:
return row(string, value)
def string_string(string: str, value: str) -> str:
return row(string, ws.webify(value))
def string_dict(string: str, value: Any, d: Dict) -> str:
return row(string, get_from_dict(d, value))