Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,19 +192,31 @@ def submit_lesson(lesson_id: str, submission: Submission) -> dict:
question_ids = {question["id"] for question in lesson["questions"]}
results, correct_count = grade_answers(submission.answers, question_ids)
total = len(question_ids)
passed = correct_count >= 2
code_question_ids = [
question["id"] for question in lesson["questions"] if question["kind"] == "code"
]
code_correct = bool(code_question_ids) and all(
any(r["question_id"] == question_id and r["correct"] for r in results)
for question_id in code_question_ids
)
passed = (not code_question_ids or code_correct) and correct_count * 3 >= total * 2
gained = 0
if passed:
gained, _ = save_lesson(lesson_id, correct_count, total, lesson["xp"])
return {
"passed": passed,
"correct_count": correct_count,
"total_count": total,
"code_correct": code_correct,
"xp_gained": gained,
"results": results,
"message": "Урок пройден! Новый урок уже открыт."
if passed
else "Нужно минимум 2 верных ответа из 3. Попробуй ещё раз — это нормально.",
else (
"Для зачёта нужно решить задачу на код"
if correct_count * 3 >= total * 2 and not code_correct
else "Нужно минимум 2 верных ответа из 3. Попробуй ещё раз — это нормально."
),
}


Expand Down
31 changes: 31 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,34 @@ def test_extended_course_unlocks_after_foundation() -> None:
assert code_check.status_code == 200
assert code_check.json()["correct"] is True
client.post("/api/reset")


def test_lesson_requires_correct_code_for_completion() -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore the extended-course test's body

Defining the new test here prematurely ends test_extended_course_unlocks_after_foundation, leaving that test with only a reset while its original assertions are now appended to the code-completion test. Consequently, running the extended-course test by node ID reports success without checking that the extended curriculum unlocks; keep those assertions in their original test and end the new test after its own scenarios.

Useful? React with 👍 / 👎.

with TestClient(app) as client:
client.post("/api/reset")
two_without_code = [
{"question_id": "hello-print", "answer": "print('Привет')"},
{"question_id": "hello-string", "answer": "строка"},
{"question_id": "hello-code", "answer": ""},
]
response = client.post("/api/lessons/hello/submit", json={"answers": two_without_code})
assert response.json()["passed"] is False
assert response.json()["message"] == "Для зачёта нужно решить задачу на код"

code_and_one_other = [
{"question_id": "hello-print", "answer": "print('неверно')"},
{"question_id": "hello-string", "answer": "строка"},
{"question_id": "hello-code", "answer": "print('Я начинаю путь в Python!')"},
]
response = client.post("/api/lessons/hello/submit", json={"answers": code_and_one_other})
assert response.json()["passed"] is True

code_only = [
{"question_id": "hello-print", "answer": "неверно"},
{"question_id": "hello-string", "answer": "неверно"},
{"question_id": "hello-code", "answer": "print('Я начинаю путь в Python!')"},
]
client.post("/api/reset")
response = client.post("/api/lessons/hello/submit", json={"answers": code_only})
assert response.json()["passed"] is False
client.post("/api/reset")
Loading