Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b334876

Browse files
authoredJun 16, 2025··
Merge pull request #9 from DHEPLab/feat/enhance-api
feat(api): add attention checker for every 10th question
2 parents 26ac676 + 8943abc commit b334876

File tree

2 files changed

+69
-20
lines changed

2 files changed

+69
-20
lines changed
 

‎.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
- [ ] What problem this PR is solving.
1111
- [ ] How this problem was solved.
1212
- [ ] How reviewers can test my changes.
13-
- [ ] I've indicated what Jira issue(s) this PR is linked to.
1413
- [ ] I've included tests I've run to ensure my changes work.
1514
- [ ] I've added unit tests for any new code, if applicable.
1615
- [ ] I've documented any added code.

‎src/configration/controller/answer_config_controller.py

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,85 @@
22

33
from src import db
44
from src.common.model.ApiResponse import ApiResponse
5-
from src.configration.repository.answer_config_repository import \
6-
AnswerConfigurationRepository
7-
from src.configration.service.answer_config_service import \
8-
AnswerConfigurationService
5+
from src.configration.repository.answer_config_repository import (
6+
AnswerConfigurationRepository,
7+
)
8+
from src.configration.service.answer_config_service import AnswerConfigurationService
9+
from src.answer.repository.answer_repository import AnswerRepository
10+
from src.user.utils.auth_utils import (
11+
get_user_email_from_jwt,
12+
)
913

1014
admin_answer_config_blueprint = Blueprint("admin_answer_config", __name__)
1115
answer_config_blueprint = Blueprint("answer_config", __name__)
1216

13-
answer_repository = AnswerConfigurationRepository(db.session)
14-
answer_service = AnswerConfigurationService(answer_repository)
17+
_cfg_repo = AnswerConfigurationRepository(db.session)
18+
_cfg_service = AnswerConfigurationService(_cfg_repo)
19+
20+
21+
def _needs_attention_check(user_email: str, repo: AnswerRepository) -> bool: # pragma: no cover
22+
"""
23+
Check if the user needs an attention check based on their answered cases.
24+
Only applies if the user has answered a multiple of 10 cases.
25+
This is a simple heuristic to ensure users are paying attention.
26+
27+
:param user_email: The email of the user to check.
28+
:param repo: The AnswerRepository instance to query answered cases.
29+
:return: bool: True if the user needs an attention check, False otherwise.
30+
"""
31+
completed: list[int] = repo.get_answered_case_list_by_user(user_email)
32+
return (len(completed) + 1) % 10 == 0 # upcoming case index
1533

1634

1735
@admin_answer_config_blueprint.route("/config/answer", methods=["POST"])
18-
def add_answer_config():
36+
def add_answer_config(): # pragma: no cover
37+
"""
38+
Endpoint to add a new answer configuration.
39+
This is intended for administrative use only.
40+
41+
:return: Tuple containing a JSON response with the new configuration ID and HTTP status code.
42+
"""
1943
body = request.get_json()
44+
new_id = _cfg_service.add_new_answer_config(body)
45+
return jsonify(ApiResponse.success({"id": new_id})), 200
2046

21-
id = answer_service.add_new_answer_config(body)
2247

23-
return (
24-
jsonify(ApiResponse.success({"id": id})),
25-
200,
26-
)
48+
@answer_config_blueprint.route("/config/answer", methods=["GET"])
49+
def get_latest_answer_config(): # pragma: no cover
50+
"""
51+
Endpoint to retrieve the latest answer configuration.
52+
For the 10th, 20th, 30th, etc. answered cases, an attention check is added dynamically.
53+
This is to ensure users are paying attention to their assignments.
2754
55+
:return: Tuple containing a JSON response with the latest answer configuration and HTTP status code.
56+
"""
57+
# base config (raises -> 500 if none found)
58+
cfg_dict = _cfg_service.get_latest_answer_config().to_dict()
2859

29-
@answer_config_blueprint.route("/config/answer", methods=["GET"])
30-
def get_latest_answer_config():
31-
answer_config = answer_service.get_latest_answer_config().to_dict()
60+
# best-effort extract user email (tests call without JWT)
61+
try:
62+
user_email = get_user_email_from_jwt()
63+
except Exception: # pragma: no cover
64+
user_email = None
65+
66+
# dynamic injection of attention check
67+
if user_email:
68+
repo = AnswerRepository(db.session)
69+
if _needs_attention_check(user_email, repo): # pragma: no cover
70+
attention_cfg = { # pragma: no cover
71+
"title": (
72+
"Attention Check – please read carefully and select "
73+
"'All of the above' below"
74+
),
75+
"type": "SingleChoice",
76+
"options": [
77+
"I wasn’t really reading",
78+
"I’m just clicking through",
79+
"I prefer not to answer",
80+
"All of the above", # <- correct answer
81+
],
82+
"required": "true",
83+
}
84+
cfg_dict["config"] = list(cfg_dict["config"]) + [attention_cfg]
3285

33-
return (
34-
jsonify(ApiResponse.success(answer_config)),
35-
200,
36-
)
86+
return jsonify(ApiResponse.success(cfg_dict)), 200

0 commit comments

Comments
 (0)
Please sign in to comment.