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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 | class SliderResponseSpec(_SpecBaseModel):
"""General scalar rating response using an HTML slider."""
kind: Literal["slider"] = "slider"
min_value: float = Field(default=0.0, description="Minimum slider value.")
max_value: float = Field(default=100.0, description="Maximum slider value.")
start_value: float | None = Field(
default=None,
description=(
"Optional initial slider value. If omitted, uses midpoint "
"between min_value and max_value."
),
)
step: float | None = Field(
default=None,
description=(
"Optional step size. Null means continuous slider; positive values "
"produce discrete ticks."
),
)
tick_labels: tuple[str, ...] = Field(
default_factory=tuple,
description=(
"Optional labels shown along the slider (e.g. low/high anchors)."
),
)
button_label: str = Field(
default="Continue",
description="Button label used to submit the rating.",
json_schema_extra=_PROMPT_SILENT,
)
require_movement: bool = Field(
default=False,
description=(
"If true, user must move the slider before submitting."
),
json_schema_extra=_PROMPT_SILENT,
)
correct_values: tuple[float, ...] | None = Field(
default=None,
description=(
"Optional exact value(s) considered correct for feedback/scoring."
),
)
correct_min_value: float | None = Field(
default=None,
description=(
"Optional lower bound of a correct range (inclusive)."
),
)
correct_max_value: float | None = Field(
default=None,
description=(
"Optional upper bound of a correct range (inclusive)."
),
)
max_responses: int | None = Field(
default=1,
description=(
"Maximum number of responses to capture. Default 1. "
"Use null for no limit (as many responses as occur before the trial ends)."
),
)
response_ends_trial: bool = Field(
default=True,
description="Whether a submitted response ends the trial.",
json_schema_extra=_PROMPT_SILENT,
)
@field_validator("max_responses")
@classmethod
def _slider_max_responses(cls, v: int | None) -> int | None:
if v is None:
return None
if v < 1:
raise ValueError("max_responses must be >= 1 or null")
return v
@model_validator(mode="after")
def _slider_bounds(self) -> "SliderResponseSpec":
if self.max_value <= self.min_value:
raise ValueError("max_value must be greater than min_value")
if self.step is not None and self.step <= 0:
raise ValueError("step must be > 0 when provided")
if self.start_value is not None:
if not (self.min_value <= self.start_value <= self.max_value):
raise ValueError("start_value must be within [min_value, max_value]")
if (self.correct_min_value is None) ^ (self.correct_max_value is None):
raise ValueError(
"correct_min_value and correct_max_value must be both set or both null"
)
if (
self.correct_min_value is not None
and self.correct_max_value is not None
and self.correct_max_value < self.correct_min_value
):
raise ValueError("correct_max_value must be >= correct_min_value")
return self
|