140 lines
5.1 KiB
Python
140 lines
5.1 KiB
Python
from app.repositories import UserAnswerRepository, QuizRepository, UserRepository
|
|
from app.schemas.requests import UserAnswerSchema
|
|
from app.schemas.response import AnsweredQuizResponse
|
|
from app.models import UserAnswerEntity
|
|
from app.models.entities import AnswerItemEntity
|
|
from app.exception import ValidationException
|
|
from app.helpers import DatetimeUtil
|
|
|
|
|
|
class AnswerService:
|
|
def __init__(
|
|
self,
|
|
answer_repository: UserAnswerRepository,
|
|
quiz_repository: QuizRepository,
|
|
user_repositroy: UserRepository,
|
|
):
|
|
self.answer_repository = answer_repository
|
|
self.quiz_repository = quiz_repository
|
|
self.user_repositroy = user_repositroy
|
|
|
|
def get_answer_by_id(self, answer_id):
|
|
return self.answer_repository.get_answer_by_id(answer_id)
|
|
|
|
def get_answer(self, quiz_id, user_id, session_id):
|
|
if quiz_id is not None:
|
|
return self.answer_repository
|
|
|
|
def create_answer(self, answer_data: UserAnswerSchema):
|
|
quiz_data = self.quiz_repository.get_by_id(answer_data.quiz_id)
|
|
if not quiz_data:
|
|
raise ValidationException(message="Quiz not found")
|
|
user_data = self.user_repositroy.get_user_by_id(answer_data.user_id)
|
|
if not user_data:
|
|
raise ValidationException(message="user is not registered")
|
|
total_quiz_played = quiz_data.total_user_playing + 1
|
|
self.quiz_repository.update_user_playing(
|
|
quiz_id=quiz_data.id, total_user=total_quiz_played
|
|
)
|
|
|
|
question_map = {q.index: q for q in quiz_data.question_listings}
|
|
|
|
answer_item_Entity = []
|
|
total_correct = 0
|
|
for user_answer in answer_data.answers:
|
|
question = question_map.get(user_answer.question_index)
|
|
if question is None:
|
|
raise ValueError(
|
|
f"Question index {user_answer.question_index} tidak ditemukan di kuis."
|
|
)
|
|
|
|
correct = False
|
|
if question.type == "fill_the_blank":
|
|
correct = (
|
|
user_answer.answer.strip().lower()
|
|
== question.target_answer.strip().lower()
|
|
)
|
|
elif question.type == "true_false":
|
|
correct = user_answer.answer == question.target_answer
|
|
elif question.type == "option":
|
|
|
|
answer_index = int(user_answer.answer)
|
|
if 0 <= answer_index < len(question.options):
|
|
correct = str(answer_index) == question.target_answer
|
|
else:
|
|
raise ValueError(
|
|
f"Index jawaban tidak valid untuk soal {question.index}"
|
|
)
|
|
|
|
else:
|
|
raise ValueError(f"Tipe soal tidak dikenali: {question.type}")
|
|
|
|
user_answer.is_correct = correct
|
|
if correct:
|
|
total_correct += 1
|
|
|
|
answer_item_Entity.append(
|
|
AnswerItemEntity(
|
|
question_index=user_answer.question_index,
|
|
answer=user_answer.answer,
|
|
is_correct=user_answer.is_correct,
|
|
time_spent=user_answer.time_spent,
|
|
)
|
|
)
|
|
total_questions = len(quiz_data.question_listings)
|
|
total_score = (
|
|
total_correct * 100 // total_questions
|
|
) # contoh perhitungan: nilai 100 dibagi rata
|
|
|
|
# Buat entitas yang akan disimpan
|
|
answer_entity = UserAnswerEntity(
|
|
session_id=answer_data.session_id,
|
|
quiz_id=answer_data.quiz_id,
|
|
user_id=answer_data.user_id,
|
|
answered_at=answer_data.answered_at,
|
|
answers=answer_item_Entity,
|
|
total_correct=total_correct,
|
|
total_questions=total_questions,
|
|
total_score=total_score,
|
|
)
|
|
|
|
return self.answer_repository.create(answer_entity)
|
|
|
|
def update_answer(self, answer_id, answer_data):
|
|
return self.answer_repository.update(answer_id, answer_data)
|
|
|
|
def delete_answer(self, answer_id):
|
|
return self.answer_repository.delete_by_id(answer_id)
|
|
|
|
def get_answer_session(self, session_id: str, user_id: str) -> AnsweredQuizResponse:
|
|
answer_data: UserAnswerEntity = (
|
|
self.answer_repository.get_by_userid_and_sessionid(
|
|
session_id=session_id,
|
|
user_id=user_id,
|
|
)
|
|
)
|
|
|
|
if not answer_data:
|
|
return None
|
|
|
|
data = AnsweredQuizResponse(
|
|
id=str(answer_data.id),
|
|
session_id=answer_data.session_id,
|
|
quiz_id=answer_data.quiz_id,
|
|
user_id=answer_data.user_id,
|
|
answered_at=DatetimeUtil.to_string(answer_data.answered_at),
|
|
answers=[
|
|
{
|
|
"question_index": ans.question_index,
|
|
"answer": ans.answer,
|
|
"is_correct": ans.is_correct,
|
|
"time_spent": ans.time_spent,
|
|
}
|
|
for ans in answer_data.answers
|
|
],
|
|
total_score=answer_data.total_score,
|
|
total_correct=answer_data.total_correct,
|
|
)
|
|
|
|
return data
|