from __future__ import annotations import html import json from pathlib import Path from .language_support import ui_text def _escape(value: object) -> str: return html.escape(str(value)) def build_accessible_session_text(session: dict) -> str: language = str(session.get("output_language", "en")) lines = [ ui_text("didactopus_learner_session", language), "", f"{ui_text('learner_goal', language)}: {session.get('goal', '')}", f"{ui_text('source_language', language)}: {session.get('source_language', 'en')}", f"{ui_text('output_language', language)}: {session.get('output_language', 'en')}", "", f"{ui_text('study_plan', language)}:", ] for index, step in enumerate(session.get("study_plan", {}).get("steps", []), start=1): lines.extend( [ f"{index}. {step.get('title', '')}", f" {ui_text('status', language)}: {step.get('status', '')}", f" {ui_text('prerequisites', language)}: {', '.join(step.get('prerequisite_titles', []) or ['none explicit'])}", f" {ui_text('supporting_lessons', language)}: {', '.join(step.get('supporting_lessons', []) or ['none listed'])}", ] ) for fragment in step.get("source_fragments", [])[:2]: lines.append(f" {ui_text('source_fragment', language)} ({fragment.get('kind', 'fragment')}): {fragment.get('text', '')}") lines.extend( [ "", f"{ui_text('conversation', language)}:", ] ) for turn in session.get("turns", []): lines.extend( [ f"{turn.get('label', turn.get('role', 'Turn'))}:", str(turn.get("content", "")), "", ] ) evaluation = session.get("evaluation", {}) lines.extend( [ f"{ui_text('evaluation_summary', language)}:", f"{ui_text('verdict', language)}: {evaluation.get('verdict', '')}", f"{ui_text('aggregated_dimensions', language)}: {json.dumps(evaluation.get('aggregated', {}), sort_keys=True)}", f"{ui_text('follow_up', language)}: {evaluation.get('follow_up', '')}", ] ) return "\n".join(lines).strip() + "\n" def build_accessible_session_html(session: dict) -> str: language = str(session.get("output_language", "en")) steps = session.get("study_plan", {}).get("steps", []) turns = session.get("turns", []) evaluation = session.get("evaluation", {}) body = [ "", f'', "", '', '', f"{_escape(ui_text('didactopus_learner_session', language))}", "", "", "", f'', '
', '
', f'

{_escape(ui_text("didactopus_learner_session", language))}

', f'

{_escape(ui_text("screen_reader_note", language))}

', f"

{_escape(ui_text('learner_goal', language))}: {_escape(session.get('goal', ''))}

", f"

{_escape(ui_text('source_language', language))}: {_escape(session.get('source_language', 'en'))}

", f"

{_escape(ui_text('output_language', language))}: {_escape(session.get('output_language', 'en'))}

", "
", '
', f'

{_escape(ui_text("study_plan", language))}

', '
    ', ] for step in steps: body.append("
  1. ") body.append(f"

    {_escape(step.get('title', ''))}

    ") body.append(f"

    {_escape(ui_text('status', language))}: {_escape(step.get('status', ''))}

    ") body.append( f"

    {_escape(ui_text('prerequisites', language))}: {_escape(', '.join(step.get('prerequisite_titles', []) or ['none explicit']))}

    " ) body.append( f"

    {_escape(ui_text('supporting_lessons', language))}: {_escape(', '.join(step.get('supporting_lessons', []) or ['none listed']))}

    " ) fragments = step.get("source_fragments", [])[:2] if fragments: body.append(f"

    {_escape(ui_text('grounding_fragments', language))}:

    ") body.append("
      ") for fragment in fragments: body.append( f'
    • {_escape(fragment.get("lesson_title", ""))} ' f'({_escape(fragment.get("kind", "fragment"))})
      {_escape(fragment.get("text", ""))}
    • ' ) body.append("
    ") body.append("
  2. ") body.extend( [ "
", "
", '
', f'

{_escape(ui_text("conversation", language))}

', ] ) for turn in turns: body.append('
') body.append(f"

{_escape(turn.get('label', turn.get('role', 'Turn')))}

") body.append(f"

Role: {_escape(turn.get('role', ''))}

") body.append(f"

{_escape(turn.get('content', ''))}

") body.append("
") body.extend( [ "
", '
', f'

{_escape(ui_text("evaluation_summary", language))}

', f"

{_escape(ui_text('verdict', language))}: {_escape(evaluation.get('verdict', ''))}

", f"

{_escape(ui_text('aggregated_dimensions', language))}: {_escape(json.dumps(evaluation.get('aggregated', {}), sort_keys=True))}

", f"

{_escape(ui_text('follow_up', language))}: {_escape(evaluation.get('follow_up', ''))}

", "
", "
", "", "", ] ) return "\n".join(body) def render_accessible_session_outputs( session: dict, *, out_html: str | Path, out_text: str | Path, ) -> dict[str, str]: out_html = Path(out_html) out_text = Path(out_text) out_html.write_text(build_accessible_session_html(session), encoding="utf-8") out_text.write_text(build_accessible_session_text(session), encoding="utf-8") return {"html": str(out_html), "text": str(out_text)}