Spaces:
Sleeping
Sleeping
| """ | |
| 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) | |