181 lines
4.4 KiB
Go
181 lines
4.4 KiB
Go
package assessment
|
|
|
|
import (
|
|
"Yimaru-Backend/internal/domain"
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
func (s *Service) GetActiveAssessmentQuestions(
|
|
ctx context.Context,
|
|
) ([]domain.AssessmentQuestion, error) {
|
|
|
|
questions, err := s.initialAssessmentStore.GetActiveAssessmentQuestions(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// IMPORTANT:
|
|
// Do NOT expose correct answers to the client
|
|
for i := range questions {
|
|
for j := range questions[i].Options {
|
|
questions[i].Options[j].IsCorrect = false
|
|
}
|
|
}
|
|
|
|
return questions, nil
|
|
}
|
|
|
|
func (s *Service) CreateAssessmentQuestion(
|
|
ctx context.Context,
|
|
q domain.AssessmentQuestion,
|
|
) (domain.AssessmentQuestion, error) {
|
|
|
|
// Basic validation
|
|
if q.Title == "" {
|
|
return domain.AssessmentQuestion{}, errors.New("question title is required")
|
|
}
|
|
|
|
if q.QuestionType == "" {
|
|
return domain.AssessmentQuestion{}, errors.New("question type is required")
|
|
}
|
|
|
|
if q.DifficultyLevel == "" {
|
|
return domain.AssessmentQuestion{}, errors.New("difficulty level is required")
|
|
}
|
|
|
|
// Multiple choice / true-false must have options
|
|
if q.QuestionType != string(domain.QuestionTypeShortAnswer) {
|
|
if len(q.Options) < 2 {
|
|
return domain.AssessmentQuestion{}, errors.New("at least two options are required")
|
|
}
|
|
|
|
hasCorrect := false
|
|
for _, opt := range q.Options {
|
|
if opt.OptionText == "" {
|
|
return domain.AssessmentQuestion{}, errors.New("option text cannot be empty")
|
|
}
|
|
if opt.IsCorrect {
|
|
hasCorrect = true
|
|
}
|
|
}
|
|
|
|
if !hasCorrect {
|
|
return domain.AssessmentQuestion{}, errors.New("at least one correct option is required")
|
|
}
|
|
}
|
|
|
|
// Persist via repository
|
|
return s.initialAssessmentStore.CreateAssessmentQuestion(ctx, q)
|
|
}
|
|
|
|
// func (s *Service) SubmitAssessment(
|
|
// ctx context.Context,
|
|
// userID int64,
|
|
// responses []domain.UserAnswer,
|
|
// ) (domain.AssessmentAttempt, error) {
|
|
|
|
// if userID <= 0 {
|
|
// return domain.AssessmentAttempt{}, errors.New("invalid user id")
|
|
// }
|
|
|
|
// if len(responses) == 0 {
|
|
// return domain.AssessmentAttempt{}, errors.New("no responses submitted")
|
|
// }
|
|
|
|
// // Step 1: Validate and evaluate answers
|
|
// for i, ans := range responses {
|
|
// if ans.QuestionID == 0 {
|
|
// return domain.AssessmentAttempt{}, errors.New("invalid question id")
|
|
// }
|
|
|
|
// isCorrect, err := s.validateAnswer(ctx, ans)
|
|
// if err != nil {
|
|
// return domain.AssessmentAttempt{}, err
|
|
// }
|
|
|
|
// responses[i].IsCorrect = isCorrect
|
|
// }
|
|
|
|
// // Step 2: Persist assessment attempt + answers
|
|
// attempt, err := s.initialAssessmentStore.SaveAssessmentAttempt(
|
|
// ctx,
|
|
// userID,
|
|
// responses,
|
|
// )
|
|
// if err != nil {
|
|
// return domain.AssessmentAttempt{}, err
|
|
// }
|
|
|
|
// // Step 3: Update user's knowledge level
|
|
// if err := s.userStore.UpdateUserKnowledgeLevel(
|
|
// ctx,
|
|
// userID,
|
|
// attempt.KnowledgeLevel,
|
|
// ); err != nil {
|
|
// return domain.AssessmentAttempt{}, err
|
|
// }
|
|
|
|
// // Step 4: Send in-app notification
|
|
// notification := &domain.Notification{
|
|
|
|
// RecipientID: userID,
|
|
// Level: domain.NotificationLevelInfo,
|
|
// Reciever: domain.NotificationRecieverSideCustomer,
|
|
// IsRead: false,
|
|
// DeliveryStatus: domain.DeliveryStatusSent,
|
|
// DeliveryChannel: domain.DeliveryChannelInApp,
|
|
// Payload: domain.NotificationPayload{
|
|
// Headline: "Knowledge Assessment Completed",
|
|
// Message: "Your knowledge assessment is complete. Your knowledge level is " + attempt.KnowledgeLevel + ".",
|
|
// Tags: []string{"assessment", "knowledge-level"},
|
|
// },
|
|
// Timestamp: time.Now(),
|
|
// Type: domain.NOTIFICATION_TYPE_KNOWLEDGE_LEVEL_UPDATE,
|
|
// }
|
|
|
|
// if err := s.notificationSvc.SendNotification(ctx, notification); err != nil {
|
|
// return domain.AssessmentAttempt{}, err
|
|
// }
|
|
|
|
// return attempt, nil
|
|
// }
|
|
|
|
func (s *Service) validateAnswer(
|
|
ctx context.Context,
|
|
answer domain.UserAnswer,
|
|
) (bool, error) {
|
|
|
|
// Multiple choice / True-False
|
|
if answer.SelectedOptionID != 0 {
|
|
option, err := s.initialAssessmentStore.GetOptionByID(
|
|
ctx,
|
|
answer.SelectedOptionID,
|
|
)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return option.IsCorrect, nil
|
|
}
|
|
|
|
// Short answer (future-proofing)
|
|
if answer.ShortAnswer != "" {
|
|
// Placeholder: subjective/manual evaluation
|
|
// For now, mark incorrect
|
|
return false, nil
|
|
}
|
|
|
|
return false, errors.New("invalid answer submission")
|
|
}
|
|
|
|
func CalculateKnowledgeLevel(score float64) string {
|
|
switch {
|
|
case score >= 80:
|
|
return "ADVANCED"
|
|
case score >= 50:
|
|
return "INTERMEDIATE"
|
|
default:
|
|
return "BEGINNER"
|
|
}
|
|
}
|