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" } }