Bryceeee's picture
Upload 34 files
6a11527 verified
Raw History Blame Contribute Delete
6.41 kB
"""
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)