# frontend/validation.py """ Validation logic for MOS evaluation form data. """ import json import gradio as gr from typing import Dict, Any, Tuple def validate_mos_completion(mos_data_json: str, expected_clips: int) -> Tuple[bool, str]: """ Validate that all MOS clips have been rated. Returns: (is_valid, error_message) """ if not mos_data_json or mos_data_json == "None": return False, "⚠️ Please rate at least one dimension for each clip before continuing!" try: ratings_data = json.loads(mos_data_json) # Check that each clip is completed # Clip is complete if: all 5 ratings are filled OR gender_mismatch is checked clips_with_ratings = 0 for clip_id, ratings in ratings_data.items(): rating_dims = ["clarity", "pronunciation", "prosody", "naturalness", "overall"] filled_ratings = [dim for dim in rating_dims if ratings.get(dim)] all_ratings_filled = len(filled_ratings) == 5 has_gender_mismatch = ratings.get("gender_mismatch", False) if all_ratings_filled or has_gender_mismatch: clips_with_ratings += 1 if clips_with_ratings < expected_clips: return False, f"⚠️ Please complete all clips before continuing! Each clip needs either all 5 ratings, or a gender flag. ({clips_with_ratings}/{expected_clips} completed)" return True, "" except json.JSONDecodeError: return False, "⚠️ Error reading ratings. Please try again!" def validate_ab_completion(ab_data_json: str, expected_comparisons: int, comparison_type: str = "comparisons") -> Tuple[bool, str]: """ Validate that all A/B comparisons have been completed. A comparison is considered complete if either: - A choice is selected (A, B, or tie), OR - At least one gender mismatch checkbox is checked Args: ab_data_json: JSON string containing comparison data expected_comparisons: Number of comparisons expected comparison_type: Type of comparison for error message (e.g., "model comparisons", "gender comparisons") Returns: (is_valid, error_message) """ if not ab_data_json or ab_data_json == "None": return False, f"⚠️ Please make a choice for each {comparison_type} before continuing!" try: comparisons_data = json.loads(ab_data_json) # Check that each comparison is completed # Complete if: has a choice OR has gender mismatch checked completed_comparisons = 0 for comp_id, comparison in comparisons_data.items(): has_choice = bool(comparison.get("choice")) has_gender_mismatch = ( comparison.get("gender_mismatch_a", False) or comparison.get("gender_mismatch_b", False) or comparison.get("gender_mismatch_male", False) or comparison.get("gender_mismatch_female", False) ) if has_choice or has_gender_mismatch: completed_comparisons += 1 if completed_comparisons < expected_comparisons: return False, f"⚠️ Please complete all {comparison_type} before continuing! Each needs either a choice or gender flag. ({completed_comparisons}/{expected_comparisons} completed)" return True, "" except json.JSONDecodeError: return False, f"⚠️ Error reading {comparison_type}. Please try again!" def validate_overall_feedback(overall_preference: str) -> Tuple[bool, str]: """ Validate that overall feedback has been selected. Returns: (is_valid, error_message) """ if not overall_preference or overall_preference == "None" or overall_preference == "": return False, "⚠️ Please select an overall preference before submitting!" return True, "" def validate_final_submission(overall_preference: str) -> Tuple[bool, str]: """ Validate final submission - only checks that overall preference is selected. Returns: (is_valid, error_message) """ # Only check that overall feedback is selected return validate_overall_feedback(overall_preference)