Files
Jacky 1f98f7152d
CI / test (push) Failing after 1m31s
v0.2 Preview: Construction Plan.
2026-08-08 21:25:27 +08:00

107 lines
3.6 KiB
Python

from django.shortcuts import get_object_or_404
from rest_framework import permissions, status, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import LatexAttempt, LatexCourse, LatexExercise
from .serializers import FormulaDocumentSerializer
class FormulaDocumentViewSet(viewsets.ModelViewSet):
serializer_class = FormulaDocumentSerializer
def get_queryset(self):
return self.request.user.formulas.all()
class CourseListView(APIView):
permission_classes = [permissions.AllowAny]
def get(self, request):
courses = LatexCourse.objects.filter(is_published=True).prefetch_related(
"lessons__exercises"
)
return Response(
[
{
"slug": course.slug,
"title": course.title,
"description": course.description,
"lessons": [
{
"slug": lesson.slug,
"title": lesson.title,
"content": lesson.content,
"example_source": lesson.example_source,
"exercise_count": lesson.exercises.count(),
}
for lesson in course.lessons.all()
],
}
for course in courses
]
)
class ExerciseSubmitView(APIView):
@staticmethod
def normalize(source):
source = source or ""
text_commands = (r"\text", r"\mbox", r"\textrm", r"\textsf", r"\texttt")
normalized = []
index = 0
while index < len(source):
command = next(
(item for item in text_commands if source.startswith(item, index)),
None,
)
if command is None:
if not source[index].isspace():
normalized.append(source[index])
index += 1
continue
command_end = index + len(command)
group_start = command_end
while group_start < len(source) and source[group_start].isspace():
group_start += 1
if group_start >= len(source) or source[group_start] != "{":
normalized.append(command)
index = command_end
continue
depth = 0
group_end = group_start
while group_end < len(source):
if source[group_end] == "{":
depth += 1
elif source[group_end] == "}":
depth -= 1
if depth == 0:
group_end += 1
break
group_end += 1
normalized.append(command)
normalized.append(source[group_start:group_end])
index = group_end
return "".join(normalized)
def post(self, request, exercise_id):
exercise = get_object_or_404(LatexExercise, id=exercise_id)
submitted = str(request.data.get("source", ""))[:50_000]
is_correct = self.normalize(submitted) == self.normalize(exercise.expected_source)
LatexAttempt.objects.create(
user=request.user,
exercise=exercise,
submitted_source=submitted,
is_correct=is_correct,
)
return Response(
{
"is_correct": is_correct,
"expected_source": exercise.expected_source if not is_correct else None,
"explanation": exercise.explanation,
},
status=status.HTTP_201_CREATED,
)