feat: add substract with image reference
This commit is contained in:
@@ -4,6 +4,24 @@ Test quick examples for each endpoint:
|
||||
|
||||
## Grade 1
|
||||
|
||||
### Subtract with image reference
|
||||
|
||||
```bash
|
||||
curl -X POST "http://127.0.0.1:8000/math/grade_1/subtract_with_image_reference" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"object_name": "peces",
|
||||
"initial_quantity": 5,
|
||||
"removed_quantity": 2,
|
||||
"actor_name": "Diego",
|
||||
"figure": {
|
||||
"id": "fish",
|
||||
"name": "Fish",
|
||||
"image_path": "/images/fish.png"
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Join corresponding sums
|
||||
|
||||
```bash
|
||||
|
||||
@@ -5,6 +5,9 @@ from app.problems.grade_1.join_corresponding_sums import join_corresponding_sums
|
||||
from app.problems.grade_1.join_pictures_with_quantity import (
|
||||
join_pictures_with_quantity,
|
||||
)
|
||||
from app.problems.grade_1.subtract_with_image_reference import (
|
||||
subtract_with_image_reference,
|
||||
)
|
||||
from app.problems.grade_1.sum_with_image_reference import sum_with_image_reference
|
||||
from app.problems.grade_1.where_are_more_items import where_are_more_items
|
||||
|
||||
@@ -12,6 +15,7 @@ __all__ = [
|
||||
"compose_and_decompose_numbers",
|
||||
"join_corresponding_sums",
|
||||
"join_pictures_with_quantity",
|
||||
"subtract_with_image_reference",
|
||||
"sum_with_image_reference",
|
||||
"where_are_more_items",
|
||||
]
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 328 KiB |
49
app/problems/grade_1/subtract_with_image_reference.py
Normal file
49
app/problems/grade_1/subtract_with_image_reference.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from app.schemas.grade_1.subtract_with_image_reference import (
|
||||
FigureGroup,
|
||||
PictureAsset,
|
||||
SubtractWithImageReferenceProblem,
|
||||
SubtractionEquation,
|
||||
)
|
||||
|
||||
|
||||
def subtract_with_image_reference(
|
||||
object_name: str,
|
||||
initial_quantity: int,
|
||||
removed_quantity: int,
|
||||
figure: dict,
|
||||
actor_name: str = "Diego",
|
||||
) -> dict:
|
||||
"""Generate a subtraction story problem with remaining and removed groups."""
|
||||
if removed_quantity > initial_quantity:
|
||||
raise ValueError("removed_quantity must be less than or equal to initial_quantity")
|
||||
|
||||
selected_figure = PictureAsset.model_validate(figure)
|
||||
remaining_quantity = initial_quantity - removed_quantity
|
||||
question = (
|
||||
f"Hay {initial_quantity} {object_name}. "
|
||||
f"{actor_name} sacó {removed_quantity} {object_name}. "
|
||||
f"¿Cuántos {object_name} quedan?"
|
||||
)
|
||||
problem = SubtractWithImageReferenceProblem(
|
||||
question=question,
|
||||
object_name=object_name,
|
||||
actor_name=actor_name,
|
||||
figure=selected_figure,
|
||||
remaining_group=FigureGroup(
|
||||
label="quedan",
|
||||
quantity=remaining_quantity,
|
||||
picture=selected_figure,
|
||||
),
|
||||
subtracted_group=FigureGroup(
|
||||
label="sacó",
|
||||
quantity=removed_quantity,
|
||||
picture=selected_figure,
|
||||
),
|
||||
equation=SubtractionEquation(
|
||||
initial_quantity=initial_quantity,
|
||||
removed_quantity=removed_quantity,
|
||||
remaining_quantity=remaining_quantity,
|
||||
),
|
||||
)
|
||||
|
||||
return problem.model_dump()
|
||||
@@ -4,6 +4,7 @@ from app.problems.grade_1 import (
|
||||
compose_and_decompose_numbers,
|
||||
join_corresponding_sums,
|
||||
join_pictures_with_quantity,
|
||||
subtract_with_image_reference,
|
||||
sum_with_image_reference,
|
||||
where_are_more_items,
|
||||
)
|
||||
@@ -14,6 +15,8 @@ from app.schemas.grade_1 import (
|
||||
JoinCorrespondingSumsRequest,
|
||||
JoinPicturesWithQuantityProblem,
|
||||
JoinPicturesWithQuantityRequest,
|
||||
SubtractWithImageReferenceProblem,
|
||||
SubtractWithImageReferenceRequest,
|
||||
SumWithImageReferenceProblem,
|
||||
SumWithImageReferenceRequest,
|
||||
WhereAreMoreItemsProblem,
|
||||
@@ -23,6 +26,25 @@ from app.schemas.grade_1 import (
|
||||
router = APIRouter(prefix="/grade_1", tags=["Grade 1"])
|
||||
|
||||
|
||||
@router.post(
|
||||
"/subtract_with_image_reference",
|
||||
response_model=SubtractWithImageReferenceProblem,
|
||||
)
|
||||
def create_subtract_with_image_reference_problem(
|
||||
request: SubtractWithImageReferenceRequest,
|
||||
) -> dict:
|
||||
try:
|
||||
return subtract_with_image_reference(
|
||||
object_name=request.object_name,
|
||||
initial_quantity=request.initial_quantity,
|
||||
removed_quantity=request.removed_quantity,
|
||||
figure=request.figure.model_dump(),
|
||||
actor_name=request.actor_name,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post(
|
||||
"/join_corresponding_sums",
|
||||
response_model=JoinCorrespondingSumsProblem,
|
||||
|
||||
@@ -10,6 +10,10 @@ from app.schemas.grade_1.join_pictures_with_quantity import (
|
||||
JoinPicturesWithQuantityProblem,
|
||||
JoinPicturesWithQuantityRequest,
|
||||
)
|
||||
from app.schemas.grade_1.subtract_with_image_reference import (
|
||||
SubtractWithImageReferenceProblem,
|
||||
SubtractWithImageReferenceRequest,
|
||||
)
|
||||
from app.schemas.grade_1.sum_with_image_reference import (
|
||||
SumWithImageReferenceProblem,
|
||||
SumWithImageReferenceRequest,
|
||||
@@ -26,6 +30,8 @@ __all__ = [
|
||||
"JoinCorrespondingSumsRequest",
|
||||
"JoinPicturesWithQuantityProblem",
|
||||
"JoinPicturesWithQuantityRequest",
|
||||
"SubtractWithImageReferenceProblem",
|
||||
"SubtractWithImageReferenceRequest",
|
||||
"SumWithImageReferenceProblem",
|
||||
"SumWithImageReferenceRequest",
|
||||
"WhereAreMoreItemsProblem",
|
||||
|
||||
40
app/schemas/grade_1/subtract_with_image_reference.py
Normal file
40
app/schemas/grade_1/subtract_with_image_reference.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from pydantic import BaseModel, Field, NonNegativeInt, PositiveInt
|
||||
|
||||
|
||||
class PictureAsset(BaseModel):
|
||||
id: str = Field(min_length=1)
|
||||
name: str = Field(min_length=1)
|
||||
image_path: str = Field(min_length=1)
|
||||
|
||||
|
||||
class SubtractionEquation(BaseModel):
|
||||
initial_quantity: PositiveInt
|
||||
removed_quantity: PositiveInt
|
||||
remaining_quantity: NonNegativeInt
|
||||
symbol: str = "-"
|
||||
equals_symbol: str = "="
|
||||
|
||||
|
||||
class FigureGroup(BaseModel):
|
||||
label: str = Field(min_length=1)
|
||||
quantity: NonNegativeInt
|
||||
picture: PictureAsset
|
||||
|
||||
|
||||
class SubtractWithImageReferenceProblem(BaseModel):
|
||||
title: str = "¿Cuántos quedan?"
|
||||
question: str
|
||||
object_name: str = Field(min_length=1)
|
||||
actor_name: str = Field(min_length=1)
|
||||
figure: PictureAsset
|
||||
remaining_group: FigureGroup
|
||||
subtracted_group: FigureGroup
|
||||
equation: SubtractionEquation
|
||||
|
||||
|
||||
class SubtractWithImageReferenceRequest(BaseModel):
|
||||
object_name: str = Field(min_length=1)
|
||||
initial_quantity: PositiveInt
|
||||
removed_quantity: PositiveInt
|
||||
figure: PictureAsset
|
||||
actor_name: str = Field(default="Diego", min_length=1)
|
||||
95
tests/test_subtract_with_image_reference_endpoint.py
Normal file
95
tests/test_subtract_with_image_reference_endpoint.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import unittest
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.main import create_app
|
||||
|
||||
|
||||
class SubtractWithImageReferenceEndpointTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.client = TestClient(create_app())
|
||||
self.figure = {
|
||||
"id": "fish",
|
||||
"name": "Fish",
|
||||
"image_path": "/images/fish.png",
|
||||
}
|
||||
|
||||
def test_creates_subtraction_problem(self) -> None:
|
||||
response = self.client.post(
|
||||
"/math/grade_1/subtract_with_image_reference",
|
||||
json={
|
||||
"object_name": "peces",
|
||||
"initial_quantity": 5,
|
||||
"removed_quantity": 2,
|
||||
"actor_name": "Diego",
|
||||
"figure": self.figure,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
problem = response.json()
|
||||
|
||||
self.assertEqual(problem["title"], "¿Cuántos quedan?")
|
||||
self.assertEqual(
|
||||
problem["question"],
|
||||
"Hay 5 peces. Diego sacó 2 peces. ¿Cuántos peces quedan?",
|
||||
)
|
||||
self.assertEqual(problem["object_name"], "peces")
|
||||
self.assertEqual(problem["actor_name"], "Diego")
|
||||
self.assertEqual(problem["figure"], self.figure)
|
||||
self.assertEqual(
|
||||
problem["remaining_group"],
|
||||
{"label": "quedan", "quantity": 3, "picture": self.figure},
|
||||
)
|
||||
self.assertEqual(
|
||||
problem["subtracted_group"],
|
||||
{"label": "sacó", "quantity": 2, "picture": self.figure},
|
||||
)
|
||||
self.assertEqual(
|
||||
problem["equation"],
|
||||
{
|
||||
"initial_quantity": 5,
|
||||
"removed_quantity": 2,
|
||||
"remaining_quantity": 3,
|
||||
"symbol": "-",
|
||||
"equals_symbol": "=",
|
||||
},
|
||||
)
|
||||
|
||||
def test_allows_zero_remaining_figures(self) -> None:
|
||||
response = self.client.post(
|
||||
"/math/grade_1/subtract_with_image_reference",
|
||||
json={
|
||||
"object_name": "peces",
|
||||
"initial_quantity": 2,
|
||||
"removed_quantity": 2,
|
||||
"figure": self.figure,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
problem = response.json()
|
||||
self.assertEqual(problem["equation"]["remaining_quantity"], 0)
|
||||
self.assertEqual(problem["remaining_group"]["quantity"], 0)
|
||||
self.assertEqual(problem["subtracted_group"]["quantity"], 2)
|
||||
|
||||
def test_returns_bad_request_when_removed_quantity_is_too_large(self) -> None:
|
||||
response = self.client.post(
|
||||
"/math/grade_1/subtract_with_image_reference",
|
||||
json={
|
||||
"object_name": "peces",
|
||||
"initial_quantity": 2,
|
||||
"removed_quantity": 5,
|
||||
"figure": self.figure,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertEqual(
|
||||
response.json(),
|
||||
{"detail": "removed_quantity must be less than or equal to initial_quantity"},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user