-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.py
More file actions
174 lines (147 loc) · 5.11 KB
/
schema.py
File metadata and controls
174 lines (147 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
"""
Scene specification schema using Pydantic.
Defines the data models for scene specifications that drive the animation pipeline.
"""
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field
# Preset theme definitions
PRESET_THEMES = {
"dark": {
"background": "#1a1a2e",
"text": "#eee",
"title": "#e94560",
"target": "#16c79a",
"cell_bg": "#0f3460",
"cell_border": "#16c79a",
"cell_text": "#eee",
"pointer_left": "#e94560",
"pointer_right": "#00b4d8",
"highlight_found": "#16c79a",
"highlight_sum": "#f7d716",
"message": "#f7d716",
"index_label": "#888",
"step_indicator": "#666",
},
"light": {
"background": "#f5f5f5",
"text": "#333",
"title": "#d63384",
"target": "#198754",
"cell_bg": "#ffffff",
"cell_border": "#198754",
"cell_text": "#333",
"pointer_left": "#d63384",
"pointer_right": "#0d6efd",
"highlight_found": "#198754",
"highlight_sum": "#ffc107",
"message": "#fd7e14",
"index_label": "#6c757d",
"step_indicator": "#adb5bd",
},
"neetcode": {
"background": "#0a0a0f",
"text": "#e5e5e5",
"title": "#ff6b6b",
"target": "#51cf66",
"cell_bg": "#1a1a2e",
"cell_border": "#4dabf7",
"cell_text": "#e5e5e5",
"pointer_left": "#ff6b6b",
"pointer_right": "#4dabf7",
"highlight_found": "#51cf66",
"highlight_sum": "#ffd43b",
"message": "#ffd43b",
"index_label": "#868e96",
"step_indicator": "#495057",
},
}
class ThemeColors(BaseModel):
"""Custom color overrides for theming.
All colors are optional. Unspecified colors fall back to the base preset.
"""
background: Optional[str] = None
text: Optional[str] = None
title: Optional[str] = None
target: Optional[str] = None
cell_bg: Optional[str] = None
cell_border: Optional[str] = None
cell_text: Optional[str] = None
pointer_left: Optional[str] = None
pointer_right: Optional[str] = None
highlight_found: Optional[str] = None
highlight_sum: Optional[str] = None
message: Optional[str] = None
index_label: Optional[str] = None
step_indicator: Optional[str] = None
class ThemeConfig(BaseModel):
"""Theme configuration for visualization colors.
Attributes:
preset: Base preset theme ("dark", "light", "neetcode")
colors: Custom color overrides
"""
preset: Literal["dark", "light", "neetcode"] = "dark"
colors: Optional[ThemeColors] = None
def resolve_colors(self) -> Dict[str, str]:
"""Resolve final colors by merging preset with overrides."""
base = PRESET_THEMES[self.preset].copy()
if self.colors:
for key, value in self.colors.model_dump().items():
if value is not None:
base[key] = value
return base
class StepState(BaseModel):
"""Visualization state for a single step.
Attributes:
left: Left pointer index (for two-pointer visualizations)
right: Right pointer index (for two-pointer visualizations)
highlight: Current highlight mode (e.g., "sum", "left_move", "right_move")
message: Display message for this state
"""
left: Optional[int] = None
right: Optional[int] = None
highlight: Optional[str] = None
message: Optional[str] = None
class Step(BaseModel):
"""A single step in the animation sequence.
Attributes:
id: Unique identifier for this step
narration: Text to be spoken during this step
state: Visualization state for this step
"""
id: str
narration: str
state: StepState
class VisualizationConfig(BaseModel):
"""Configuration for the visualization type and parameters.
Attributes:
type: Type of visualization (e.g., "array_pointers")
config: Type-specific configuration dictionary
theme: Optional theme configuration
"""
type: str
config: Dict[str, Any] = Field(default_factory=dict)
theme: ThemeConfig = Field(default_factory=ThemeConfig)
def get_resolved_theme(self) -> Dict[str, str]:
"""Get fully resolved theme colors."""
return self.theme.resolve_colors()
class SceneSpec(BaseModel):
"""Full scene specification.
This is the primary data structure that drives the entire animation pipeline.
Attributes:
id: Unique identifier for this scene
title: Human-readable title
description: Description of what the scene demonstrates
visualization: Visualization configuration
steps: List of animation steps with narration
"""
id: str
title: str
description: Optional[str] = None
visualization: VisualizationConfig
steps: List[Step]
def get_narrations(self) -> List[str]:
"""Extract all narration texts from steps."""
return [step.narration for step in self.steps]
def get_step_ids(self) -> List[str]:
"""Extract all step IDs."""
return [step.id for step in self.steps]