File size: 3,341 Bytes
339a529
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import json
import bisect

# Load questions and answers from JSON files
with open('numeric/questions.json', 'r') as q_file:
    questions = json.load(q_file)

with open('numeric/answers.json', 'r') as a_file:
    answers = json.load(a_file)

with open('numeric/distribution.json', 'r') as file:
    distribution_data = json.load(file)

def calculate_percentile(correct_answers, distribution):
    # Sort the distribution by the number of correct answers
    distribution.sort(key=lambda x: x[0])
    
    # Separate the correct answers and percentiles into two lists
    scores = [item[0] for item in distribution]
    percentiles = [item[1] for item in distribution]
    
    # Find the index where the given correct_answers should be inserted
    index = bisect.bisect_left(scores, correct_answers)
    
    # If the exact score is found in the distribution
    if index < len(scores) and scores[index] == correct_answers:
        return percentiles[index]
    
    # If the score is beyond the highest score in the distribution
    if index == len(scores):
        return 100.0
    
    # If the score is between two values in the distribution, interpolate
    if index > 0:
        lower_score, lower_percentile = scores[index-1], percentiles[index-1]
        upper_score, upper_percentile = scores[index], percentiles[index]
        
        # Linear interpolation
        slope = (upper_percentile - lower_percentile) / (upper_score - lower_score)
        interpolated_percentile = lower_percentile + slope * (correct_answers - lower_score)
        
        return round(interpolated_percentile, 2)
    
    # If the score is below the lowest score in the distribution
    return 0.0


def grade_test(*responses):
    score = 0
    distribution = [(item['correct_answers'], item['percentile']) for item in distribution_data]

    if any(response is None for response in responses):
        indices = [index for index, value in enumerate(responses) if value is None]
        indices = [value + 1  for value in indices]
        raise gr.Error(f"No se puede quedar ningun valor en 0. Preguntas sin respuesta:{indices}")
    
    for i, response in enumerate(responses):
        response_parsed = response.split('.')[0]
        if response_parsed == answers[str(i)]:
            score += 1
    percentile = calculate_percentile(score, distribution)
    return f"Your score: {percentile}: correct answers: {score}"

# Create Gradio interface
demo = gr.Blocks(title="Numerical Test")

with demo:
    inputs = []
    for i, question in enumerate(questions):
        inputs.append(gr.Radio(choices=question['options'], label=question['question']))
    

    gr.Image(value="numeric/questions39.png", show_label=False, height=700, width=350)

    inputs.append(gr.Radio(choices=["A. 8", "B. 4", "C. 2", "D. 1", "E. Ninguna de ellas"], 
                           label="39. Si introduce el número 8, ¿cuántas veces pasará por elpaso 4 para llegar al final?"))
    inputs.append(gr.Radio(choices=["A. 6", "B. 5", "C. 3", "D. 2", "E. Ninguna de ellas"], 
                           label="40. Si introduce el número 3, ¿Cuál será el número cuando llegue al final?"))
    
    output = gr.Textbox()
    gr.Button("Submit").click(grade_test, inputs=inputs, outputs=output)

if __name__ == "__main__":
    demo.launch()