Bryceeee's picture
Upload 34 files
6a11527 verified
"""
Constructive Scenario Formatter
Formats scenarios in an educational, constructive way
"""
from typing import List
from ..database.scenario_models import ADASScenario, RankedScenario
class FormattedScenario:
"""Formatted scenario"""
def __init__(
self,
title: str,
adas_feature: str,
boundary_conditions: List[str],
appropriate_responses: List[str],
educational_principle: str,
relevance_hint: str = "",
full_scenario_link: str = ""
):
self.title = title
self.adas_feature = adas_feature
self.boundary_conditions = boundary_conditions
self.appropriate_responses = appropriate_responses
self.educational_principle = educational_principle
self.relevance_hint = relevance_hint
self.full_scenario_link = full_scenario_link
class ConstructiveFormatter:
"""Constructive scenario formatter"""
def format_scenario(self, ranked_scenario: RankedScenario) -> FormattedScenario:
"""
Format a single scenario
Principles:
- Avoid detailed incident descriptions
- Emphasize boundary conditions and appropriate responses
- Provide educational principles
- Use positive, constructive language
"""
scenario = ranked_scenario.scenario
# Format boundary conditions
boundary_conditions = self._format_boundary_conditions(scenario)
# Format appropriate responses
appropriate_responses = self._format_responses(scenario)
# Extract educational principle
educational_principle = self._format_principle(scenario)
# Generate relevance hint
relevance_hint = self._generate_relevance_hint(ranked_scenario)
return FormattedScenario(
title=scenario.title,
adas_feature=scenario.adas_feature,
boundary_conditions=boundary_conditions,
appropriate_responses=appropriate_responses,
educational_principle=educational_principle,
relevance_hint=relevance_hint,
full_scenario_link=f"/scenario/{scenario.scenario_id}"
)
def _format_boundary_conditions(self, scenario: ADASScenario) -> List[str]:
"""Format boundary conditions using constructive language"""
formatted = []
for bc in scenario.boundary_conditions:
# Use constructive language: emphasize "may" rather than "failed"
condition_text = f"β€’ {bc.condition}: {bc.impact}"
if bc.details:
condition_text += f" ({bc.details})"
formatted.append(condition_text)
return formatted
def _format_responses(self, scenario: ADASScenario) -> List[str]:
"""Format appropriate responses, emphasizing correct actions"""
formatted = []
for ar in scenario.appropriate_responses:
response_text = f"β€’ {ar.response}: {ar.rationale}"
if ar.details:
response_text += f" ({ar.details})"
formatted.append(response_text)
return formatted
def _format_principle(self, scenario: ADASScenario) -> str:
"""Format educational principle"""
if scenario.educational_principles:
# Use first principle, or combine multiple principles
if len(scenario.educational_principles) == 1:
return scenario.educational_principles[0]
else:
return " ".join(scenario.educational_principles[:2]) # Max two principles
elif scenario.generalization:
return scenario.generalization
else:
return "Understanding system limitations helps ensure safe operation."
def _generate_relevance_hint(self, ranked_scenario: RankedScenario) -> str:
"""Generate relevance hint"""
if ranked_scenario.match_reasons:
reasons = ", ".join(ranked_scenario.match_reasons[:2]) # Max two reasons
return f"Relevant because: {reasons}"
return ""
def format_scenarios_for_ui(self, ranked_scenarios: List[RankedScenario]) -> str:
"""
Format multiple scenarios as HTML for UI display
Returns:
str: HTML formatted scenario cards
"""
if not ranked_scenarios:
return ""
formatted_scenarios = [self.format_scenario(rs) for rs in ranked_scenarios]
html_parts = []
for i, fs in enumerate(formatted_scenarios, 1):
scenario_html = f"""
<div style="margin-bottom: 20px; padding: 15px; border: 1px solid #ddd; border-radius: 8px; background-color: #f9f9f9;">
<h4 style="margin-top: 0; color: #333;">{fs.title}</h4>
<p style="margin: 5px 0; color: #666; font-size: 0.9em;">Related to: <strong>{fs.adas_feature}</strong></p>
<div style="margin: 15px 0;">
<strong style="color: #d9534f;">⚠️ Boundary Conditions:</strong>
<ul style="margin: 5px 0; padding-left: 20px;">
{''.join(f'<li style="margin: 5px 0;">{bc}</li>' for bc in fs.boundary_conditions)}
</ul>
</div>
<div style="margin: 15px 0;">
<strong style="color: #5cb85c;">βœ… Appropriate Responses:</strong>
<ul style="margin: 5px 0; padding-left: 20px;">
{''.join(f'<li style="margin: 5px 0;">{ar}</li>' for ar in fs.appropriate_responses)}
</ul>
</div>
<div style="margin: 15px 0;">
<strong style="color: #337ab7;">πŸ“– Educational Principle:</strong>
<p style="margin: 5px 0; font-style: italic;">{fs.educational_principle}</p>
</div>
{f'<p style="margin: 5px 0; font-size: 0.85em; color: #999;">{fs.relevance_hint}</p>' if fs.relevance_hint else ''}
</div>
"""
html_parts.append(scenario_html)
return "".join(html_parts)