File size: 4,338 Bytes
653a3eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# 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)