Skip to content

Commit daa5701

Browse files
committed
fix
1 parent 84345c9 commit daa5701

File tree

13 files changed

+162
-55
lines changed

13 files changed

+162
-55
lines changed

fab_management/utils.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def get_timestamp(row_values, field_name, default_time="00:00:00"):
8989

9090
def get_type(row_values):
9191
value_str = row_values["type"]
92-
if value_str not in ["binary", "numeric", "multiple_choice"]:
92+
if value_str not in ["binary", "numeric", "discrete", "multiple_choice"]:
9393
raise ValueError("Unknown value for the question type")
9494
return value_str
9595

@@ -252,7 +252,7 @@ def get_values_dict(row):
252252
question_fields = list(common_fields)
253253
author = get_author(row_values)
254254

255-
if question_type == "numeric":
255+
if question_type == "numeric" or question_type == "discrete":
256256
question_fields += numeric_q_fields
257257

258258
if question_type == "multiple_choice":
@@ -267,7 +267,10 @@ def get_values_dict(row):
267267
f"Error on row {row_idx}, col '{field_name}': question has no parent, but '.p' was used for field"
268268
)
269269
continue
270-
val = getattr(parent_post.question or parent_post.group_of_questions, field_name)
270+
val = getattr(
271+
parent_post.question or parent_post.group_of_questions,
272+
field_name,
273+
)
271274
elif callable(field_get_value_fn):
272275
val = field_get_value_fn(row_values)
273276

front_end/src/app/(main)/questions/[id]/components/forecast_maker/helpers.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { isNil } from "lodash";
22
import { MessageKeys, useTranslations } from "next-intl";
33

44
import {
5+
DefaultInboundOutcomeCount,
56
DistributionQuantileComponent,
67
Quantile,
78
QuestionWithNumericForecasts,
@@ -243,7 +244,10 @@ export function validateUserQuantileData({
243244
}
244245

245246
// Check CDF length
246-
if (cdf.length !== 201) {
247+
if (
248+
cdf.length !==
249+
(question.inbound_outcome_count || DefaultInboundOutcomeCount) + 1
250+
) {
247251
validationErrors.push(t("invalidCdfLengthError"));
248252
return validationErrors;
249253
}

front_end/src/app/(main)/questions/[id]/components/forecast_maker/resolution/resolution_modal.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,18 @@ const QuestionResolutionModal: FC<Props> = ({ isOpen, onClose, question }) => {
6060
{ value: ANNULED_RESOLUTION, label: "Annulled" },
6161
];
6262

63-
if (["date", "numeric"].includes(question.type)) {
63+
if (
64+
[QuestionType.Numeric, QuestionType.Date, QuestionType.Discrete].includes(
65+
question.type
66+
)
67+
) {
6468
return [
6569
...baseQuestionOptions,
6670
{ value: "unambiguous", label: "Unambiguous" },
6771
];
6872
}
6973

70-
if (question.type === "binary") {
74+
if (question.type === QuestionType.Binary) {
7175
return [
7276
...baseQuestionOptions,
7377
{ value: "yes", label: "Yes" },

front_end/src/app/(main)/questions/components/group_form.tsx

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ import {
4646
TournamentPreview,
4747
TournamentType,
4848
} from "@/types/projects";
49-
import { QuestionType, QuestionWithNumericForecasts } from "@/types/question";
49+
import {
50+
DefaultInboundOutcomeCount,
51+
QuestionType,
52+
QuestionWithNumericForecasts,
53+
} from "@/types/question";
5054
import { logErrorWithScope } from "@/utils/errors";
5155
import { getPostLink } from "@/utils/navigation";
5256
import { sortGroupPredictionOptions } from "@/utils/questions";
@@ -201,6 +205,22 @@ const GroupForm: React.FC<Props> = ({
201205
open_lower_bound: x.open_lower_bound,
202206
open_upper_bound: x.open_upper_bound,
203207
};
208+
} else if (subtype === QuestionType.Discrete) {
209+
if (x.scaling.range_max == null || x.scaling.range_min == null) {
210+
setError(
211+
"Please enter a range_max and range_min value for discrete questions"
212+
);
213+
break_out = true;
214+
return;
215+
}
216+
return {
217+
...subquestionData,
218+
unit: x.unit,
219+
scaling: x.scaling,
220+
open_lower_bound: x.open_lower_bound,
221+
open_upper_bound: x.open_upper_bound,
222+
inbound_outcome_count: x.inbound_outcome_count,
223+
};
204224
} else if (subtype === QuestionType.Date) {
205225
if (x.scaling.range_max === null || x.scaling.range_min === null) {
206226
setError(
@@ -326,6 +346,10 @@ const GroupForm: React.FC<Props> = ({
326346
title: t("dateQuestionGroup"),
327347
description: t("dateQuestionGroupDescription"),
328348
},
349+
discrete: {
350+
title: t("discreteQuestionGroup"),
351+
description: t("discreteQuestionGroupDescription"),
352+
},
329353
};
330354

331355
const { title: formattedQuestionType, description: questionDescription } =
@@ -852,11 +876,30 @@ const GroupForm: React.FC<Props> = ({
852876
},
853877
]);
854878
} else {
855-
if (subtype === "numeric") {
879+
if (subtype === QuestionType.Numeric) {
880+
setSubQuestions([
881+
...subQuestions,
882+
{
883+
type: QuestionType.Numeric,
884+
label: "",
885+
scheduled_close_time:
886+
form.getValues().scheduled_close_time,
887+
scheduled_resolve_time:
888+
form.getValues().scheduled_resolve_time,
889+
scaling: {
890+
range_min: null,
891+
range_max: null,
892+
zero_point: null,
893+
},
894+
open_lower_bound: null,
895+
open_upper_bound: null,
896+
},
897+
]);
898+
} else if (subtype === QuestionType.Discrete) {
856899
setSubQuestions([
857900
...subQuestions,
858901
{
859-
type: "numeric",
902+
type: QuestionType.Discrete,
860903
label: "",
861904
scheduled_close_time:
862905
form.getValues().scheduled_close_time,
@@ -869,13 +912,14 @@ const GroupForm: React.FC<Props> = ({
869912
},
870913
open_lower_bound: null,
871914
open_upper_bound: null,
915+
inbound_outcome_count: DefaultInboundOutcomeCount,
872916
},
873917
]);
874-
} else if (subtype === "date") {
918+
} else if (subtype === QuestionType.Date) {
875919
setSubQuestions([
876920
...subQuestions,
877921
{
878-
type: "date",
922+
type: QuestionType.Date,
879923
label: "",
880924
scheduled_close_time:
881925
form.getValues().scheduled_close_time,

front_end/src/app/(main)/questions/components/question_form.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,13 @@ const createQuestionSchemas = (
5757
post: PostWithForecasts | null
5858
) => {
5959
const baseQuestionSchema = z.object({
60-
type: z.enum(["binary", "multiple_choice", "date", "numeric", "discrete"]),
60+
type: z.enum([
61+
QuestionType.Binary,
62+
QuestionType.MultipleChoice,
63+
QuestionType.Date,
64+
QuestionType.Numeric,
65+
QuestionType.Discrete,
66+
]),
6167
title: z
6268
.string()
6369
.min(4, {
@@ -370,15 +376,15 @@ const QuestionForm: FC<Props> = ({
370376
const schemas = createQuestionSchemas(t, post);
371377
const getFormSchema = (type: string) => {
372378
switch (type) {
373-
case "binary":
379+
case QuestionType.Binary:
374380
return schemas.binaryQuestionSchema;
375-
case "multiple_choice":
381+
case QuestionType.MultipleChoice:
376382
return schemas.multipleChoiceQuestionSchema;
377-
case "numeric":
383+
case QuestionType.Numeric:
378384
return schemas.numericQuestionSchema;
379-
case "date":
385+
case QuestionType.Date:
380386
return schemas.dateQuestionSchema;
381-
case "discrete":
387+
case QuestionType.Discrete:
382388
return schemas.discreteQuestionSchema;
383389
default:
384390
throw new Error("Invalid question type");
@@ -458,7 +464,8 @@ const QuestionForm: FC<Props> = ({
458464
className="w-full rounded border border-gray-500 px-3 py-2 text-base dark:border-gray-500-dark dark:bg-blue-50-dark"
459465
/>
460466
</InputContainer>
461-
{(questionType === "numeric" || questionType === "discrete") && (
467+
{(questionType === QuestionType.Numeric ||
468+
questionType === QuestionType.Discrete) && (
462469
<InputContainer
463470
labelText={t("questionUnit")}
464471
explanation={t("questionUnitDescription")}

front_end/src/app/(main)/questions/create/page.tsx

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import QuestionRepost from "@/app/(main)/questions/components/question_repost";
99
import ProjectsApi from "@/services/projects";
1010
import { SearchParams } from "@/types/navigation";
1111
import { ProjectPermissions } from "@/types/post";
12+
import { QuestionType } from "@/types/question";
1213
import { getPublicSettings } from "@/utils/public_settings.server";
1314

1415
import QuestionTypePicker from "../components/question_type_picker";
@@ -107,29 +108,37 @@ const Creator: React.FC<{ searchParams: Promise<SearchParams> }> = async (
107108
</h2>
108109
<div className="grid w-full grid-cols-1 gap-3 md:grid-cols-2 md:gap-4">
109110
<QuestionTypePicker
110-
url={createHref("/questions/create/question", { type: "binary" })}
111+
url={createHref("/questions/create/question", {
112+
type: QuestionType.Binary,
113+
})}
111114
questionType={t("binaryQuestion")}
112115
questionExample={`"${t("binaryQuestionExample")}"`}
113116
/>
114117
<QuestionTypePicker
115118
url={createHref("/questions/create/question", {
116-
type: "multiple_choice",
119+
type: QuestionType.MultipleChoice,
117120
})}
118121
questionType={t("multipleChoice")}
119122
questionExample={`"${t("multipleChoiceExample")}"`}
120123
/>
121124
<QuestionTypePicker
122-
url={createHref("/questions/create/question", { type: "numeric" })}
125+
url={createHref("/questions/create/question", {
126+
type: QuestionType.Numeric,
127+
})}
123128
questionType={t("numericRange")}
124129
questionExample={`"${t("numericRangeExample")}"`}
125130
/>
126131
<QuestionTypePicker
127-
url={createHref("/questions/create/question", { type: "date" })}
132+
url={createHref("/questions/create/question", {
133+
type: QuestionType.Date,
134+
})}
128135
questionType={t("dateRange")}
129136
questionExample={`"${t("dateRangeExample")}"`}
130137
/>
131138
<QuestionTypePicker
132-
url={createHref("/questions/create/question", { type: "discrete" })}
139+
url={createHref("/questions/create/question", {
140+
type: QuestionType.Discrete,
141+
})}
133142
questionType={t("discrete")}
134143
questionExample={`"${t("discreteExample")}"`}
135144
/>
@@ -138,25 +147,33 @@ const Creator: React.FC<{ searchParams: Promise<SearchParams> }> = async (
138147
<h2 className="text-lg font-light capitalize">{t("questionGroup")}</h2>
139148
<div className="grid w-full grid-cols-1 gap-3 md:grid-cols-2 md:gap-4">
140149
<QuestionTypePicker
141-
url={createHref("/questions/create/group", { subtype: "binary" })}
150+
url={createHref("/questions/create/group", {
151+
subtype: QuestionType.Binary,
152+
})}
142153
questionType={t("binaryGroup")}
143154
questionExample={`"${t("binaryGroupExample")}"`}
144155
/>
145156
<QuestionTypePicker
146-
url={createHref("/questions/create/group", { subtype: "numeric" })}
157+
url={createHref("/questions/create/group", {
158+
subtype: QuestionType.Numeric,
159+
})}
147160
questionType={t("numericGroup")}
148161
questionExample={`"${t("numericGroupExample")}"`}
149162
/>
150163
<QuestionTypePicker
151-
url={createHref("/questions/create/group", { subtype: "date" })}
164+
url={createHref("/questions/create/group", {
165+
subtype: QuestionType.Date,
166+
})}
152167
questionType={t("dateGroup")}
153168
questionExample={`"${t("dateGroupExample")}"`}
154169
/>
155-
{/* <QuestionTypePicker
156-
url={createHref("/questions/create/group", { subtype: "discrete" })}
170+
<QuestionTypePicker
171+
url={createHref("/questions/create/group", {
172+
subtype: QuestionType.Discrete,
173+
})}
157174
questionType={t("discreteGroup")}
158175
questionExample={`"${t("discreteGroupExample")}"`}
159-
/> */}
176+
/>
160177
<QuestionTypePicker
161178
url={createHref("/questions/create/conditional")}
162179
questionType={t("conditionalPair")}

0 commit comments

Comments
 (0)