@@ -622,20 +622,54 @@ def _ok() -> Result:
622622 def _err (msg : str ) -> Result :
623623 return Result (is_correct = False , feedback_items = [("error" , msg )])
624624
625- # ── parse params FIRST — directed/weighted/multigraph live here ─────
625+ # ── parse answer FIRST — evaluation_type and graph flags now live here ─────
626+
627+ answer_dict = _to_dictish (answer ) or {}
628+
629+ if is_frontend_format (answer_dict ):
630+ parsed_graph = parse_frontend_graph (answer_dict )
631+ answer_dict = {"graph" : parsed_graph .model_dump ()}
626632
627- raw_params = _to_dictish (params ) or {}
628633 try :
629- p = EvaluationParams .model_validate (raw_params )
634+ ans = Answer .model_validate (answer_dict )
630635 except ValidationError as e :
631- return _err (
632- "Invalid params schema. Expected e.g. "
633- "{'evaluation_type': 'connectivity'|'bipartite'|'graph_coloring'|...}. "
634- f"Error: { e } "
635- f"response: { response } "
636- f"answer: { answer } "
637- f"params: { params } "
638- )
636+ return _err (f"Invalid answer schema: { e } " )
637+
638+ # ── extract evaluation params from answer ─────────────────────────────
639+ # All evaluation configuration now comes from the answer object
640+
641+ eval_params_dict = {}
642+
643+ # Get evaluation_type from answer (required)
644+ if ans .evaluation_type :
645+ eval_params_dict ['evaluation_type' ] = ans .evaluation_type
646+ elif 'evaluation_type' in answer_dict :
647+ eval_params_dict ['evaluation_type' ] = answer_dict ['evaluation_type' ]
648+ else :
649+ return _err ("evaluation_type is required in answer object" )
650+
651+ # Get graph structure flags from answer (with defaults)
652+ eval_params_dict ['directed' ] = ans .directed if ans .directed is not None else False
653+ eval_params_dict ['weighted' ] = ans .weighted if ans .weighted is not None else False
654+ eval_params_dict ['multigraph' ] = ans .multigraph if ans .multigraph is not None else False
655+
656+ # Get optional evaluation sub-params from answer
657+ for key in ['connectivity' , 'bipartite' , 'graph_coloring' , 'cycle_detection' ,
658+ 'isomorphism' , 'feedback_level' , 'tolerance' ]:
659+ value = getattr (ans , key , None )
660+ if value is not None :
661+ eval_params_dict [key ] = value
662+
663+ # Set defaults for feedback_level and tolerance if not provided
664+ if 'feedback_level' not in eval_params_dict :
665+ eval_params_dict ['feedback_level' ] = 'standard'
666+ if 'tolerance' not in eval_params_dict :
667+ eval_params_dict ['tolerance' ] = 1e-9
668+
669+ try :
670+ p = EvaluationParams .model_validate (eval_params_dict )
671+ except ValidationError as e :
672+ return _err (f"Invalid evaluation parameters in answer: { e } " )
639673
640674 # ── parse response (student's graph) ─────────────────────────────────
641675
@@ -650,22 +684,9 @@ def _err(msg: str) -> Result:
650684 except ValidationError as e :
651685 return _err (f"Invalid response schema: { e } " )
652686
653- # ── parse answer (teacher's reference) ───────────────────────────────
654-
655- answer_dict = _to_dictish (answer ) or {}
656-
657- if is_frontend_format (answer_dict ):
658- parsed_graph = parse_frontend_graph (answer_dict )
659- answer_dict = {"graph" : parsed_graph .model_dump ()}
660-
661- try :
662- ans = Answer .model_validate (answer_dict )
663- except ValidationError as e :
664- return _err (f"Invalid answer schema: { e } " )
665-
666687 # ── resolve graphs and stamp params flags ─────────────────────────────
667- # directed/weighted/multigraph come exclusively from params — never from
668- # the student or teacher payload.
688+ # directed/weighted/multigraph come exclusively from answer object — never from
689+ # the student response payload.
669690
670691 student_graph : Graph = resp .graph
671692 if student_graph is None :
0 commit comments