POST /exercises/evaluate
Evalua la respuesta de un usuario a un ejercicio. Devuelve score 0-10, resultado y feedback.
Campos del body
| Campo | Tipo | Requerido | Descripcion |
|---|---|---|---|
exerciseId | string | Si | Identificador del ejercicio (max 128 chars) |
area | string | Si | listening, reading, writing, vocabulary, grammar |
type | string | Si | Ver tabla de tipos |
answer | string | Si | Respuesta del usuario (max 2000 chars) |
correctAnswer | string o string[] | Condicional | Requerido para multiple_choice y fill_blank. Opcional para open_answer. |
content | object | Condicional | Requerido para drag_and_drop, match, word_search, crossword. Sin el retorna 400. |
difficulty | number | No | Nivel de dificultad 1-5 |
Tipos soportados
| type | Estrategia | Score |
|---|---|---|
multiple_choice | Case-insensitive + trim | 0 o 10 |
fill_blank | Case-insensitive + trim, multiples alternativas | 0 o 10 |
complete | Igual que fill_blank — el usuario escribe la palabra | 0 o 10 |
open_answer | Levenshtein >= 0.8 o longitud minima | 0-10 |
drag_and_drop | Items en zona correcta / total | 0-10 |
match | Pares correctos / total | 0-10 |
word_search | Palabras encontradas / total | 0-10 |
crossword | Respuestas por pista / total, case-insensitive | 0-10 |
Estructura de respuesta
{ "correct": true, "score": 10, "feedback": "Correct!", "metadata": { "area": "vocabulary", "type": "multiple_choice" }}Ejemplos por tipo
multiple_choice
{ "exerciseId": "ex_001", "area": "vocabulary", "type": "multiple_choice", "answer": "B", "correctAnswer": "b"}“B” y “b” son equivalentes (case-insensitive).
fill_blank - multiples alternativas
{ "exerciseId": "ex_002", "area": "grammar", "type": "fill_blank", "answer": "goes", "correctAnswer": ["went", "go", "goes"]}complete
Identico a fill_blank. Usar cuando el ejercicio pide al usuario que escriba la palabra en un espacio en blanco dentro de un texto.
{ "exerciseId": "ex_002b", "area": "vocabulary", "type": "complete", "answer": "She", "correctAnswer": "She"}Acepta correctAnswer como string o array de alternativas.
open_answer
{ "exerciseId": "ex_003", "area": "writing", "type": "open_answer", "answer": "The cat is sleeping on the couch", "correctAnswer": "The cat sleeps on the sofa"}Feedback segun score: "Good answer!" (>= 0.8), "Your answer is partially correct." (0.5-0.8), "Incorrect. Review the topic and try again." (< 0.5).
drag_and_drop
answer = JSON.stringify({ item_id: zone_id })
{ "exerciseId": "ex_004", "area": "vocabulary", "type": "drag_and_drop", "answer": "{\"1\":\"fruit\",\"2\":\"vegetable\"}", "content": { "items": [ { "id": "1", "text": "Apple", "correctZoneId": "fruit" }, { "id": "2", "text": "Carrot", "correctZoneId": "vegetable" } ], "zones": [ { "id": "fruit", "label": "Fruits" }, { "id": "vegetable", "label": "Vegetables" } ] }}match
answer = JSON.stringify({ left: right })
{ "exerciseId": "ex_005", "area": "vocabulary", "type": "match", "answer": "{\"Dog\":\"A loyal pet\",\"Cat\":\"A small animal\"}", "content": { "pairs": [ { "left": "Dog", "right": "A loyal pet" }, { "left": "Cat", "right": "A small animal" } ] }}word_search
answer = JSON.stringify({ found: string[] })
{ "exerciseId": "ex_006", "area": "vocabulary", "type": "word_search", "answer": "{\"found\":[\"CAT\",\"DOG\"]}", "content": { "words": ["CAT", "DOG", "BIRD"] }}content.words acepta string[] o { word, clue }[].
crossword
answer = JSON.stringify({ "1": "WORD", "2": "WORD" }) - claves son el numero de pista (1-based).
{ "exerciseId": "ex_007", "area": "vocabulary", "type": "crossword", "answer": "{\"1\":\"cat\",\"2\":\"dog\",\"3\":\"act\"}", "content": { "words": [ { "answer": "CAT", "clue": { "type": "TEXT", "value": "A small animal" } }, { "answer": "DOG", "clue": { "type": "TEXT", "value": "A loyal pet" } }, { "answer": "ACT", "clue": { "type": "TEXT", "value": "To do something" } } ] }}La comparacion es case-insensitive: “cat” === “CAT”.