diff --git a/src/sweetbean/stimulus/InformedConsent.py b/src/sweetbean/stimulus/InformedConsent.py new file mode 100644 index 00000000..97e5dd9d --- /dev/null +++ b/src/sweetbean/stimulus/InformedConsent.py @@ -0,0 +1,165 @@ +from __future__ import annotations + +from html import escape +from typing import Any + +from sweetbean.stimulus.HtmlKeyboardResponse import HtmlKeyboardResponse + + +def _sn(d: dict[str, Any], key: str) -> str | None: + if key not in d: + return None + v = d[key] + if v is None: + return None + s = str(v).strip() + return s if s else None + + +class InformedConsent(HtmlKeyboardResponse): + """ + SweetBean-compatible informed-consent page. + Participants continue with space. + """ + + def __init__(self, text: str, duration=None, side_effects=None): + super().__init__( + duration=duration, + stimulus=text, + choices=[" "], + correct_key="", + side_effects=side_effects, + ) + + @classmethod + def from_sections( + cls, + *, + research_config: dict[str, Any], + consent_config: dict[str, Any], + ) -> "InformedConsent": + title = _sn(research_config, "study_title") or _sn(consent_config, "title") + text = cls._build_html( + institution=_sn(research_config, "institution"), + title=title, + version=_sn(consent_config, "version"), + researcher_name=_sn(research_config, "researcher_name"), + researcher_email=_sn(research_config, "researcher_email"), + researcher_phone=_sn(research_config, "researcher_phone"), + duration_minutes=_sn(consent_config, "duration_minutes"), + compensation_amount=_sn(consent_config, "compensation_amount"), + age_range=_sn(consent_config, "age_range"), + compensation_rate=_sn(consent_config, "compensation_rate"), + purpose=_sn(consent_config, "purpose"), + procedures=_sn(consent_config, "procedures"), + risks=_sn(consent_config, "risks"), + benefits=_sn(consent_config, "benefits"), + confidentiality=_sn(consent_config, "confidentiality"), + continue_text=_sn(consent_config, "continue_text"), + ) + return cls(text=text) + + @staticmethod + def _build_html( + *, + institution: str | None, + title: str | None, + version: str | None, + researcher_name: str | None, + researcher_email: str | None, + researcher_phone: str | None, + duration_minutes: str | None, + compensation_amount: str | None, + age_range: str | None, + compensation_rate: str | None, + purpose: str | None, + procedures: str | None, + risks: str | None, + benefits: str | None, + confidentiality: str | None, + continue_text: str | None, + ) -> str: + parts: list[str] = [ + "
{escape(version)}
") + + parts.append("CONSENT TO PARTICIPATE: Continuing confirms that you have read and " + "understood this information and agree to participate.
" + ) + if continue_text: + parts.append(f"{escape(continue_text)}
") + parts.append("