go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/kana-server/pkg/model/manager.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package model
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  
    14  	"go.charczuk.com/sdk/db"
    15  	"go.charczuk.com/sdk/db/dbutil"
    16  	"go.charczuk.com/sdk/uuid"
    17  
    18  	"go.charczuk.com/projects/kana-server/pkg/types"
    19  )
    20  
    21  var (
    22  	quizCols            = db.TypeMetaFor(types.Quiz{})
    23  	quizTableName       = types.Quiz{}.TableName()
    24  	quizResultCols      = db.TypeMetaFor(types.QuizResult{})
    25  	quizResultTableName = types.QuizResult{}.TableName()
    26  
    27  	getQuizzesForUserQuery     = fmt.Sprintf("SELECT %s FROM %s WHERE user_id = $1 ORDER BY created_utc desc", db.ColumnNamesCSV(quizCols.Columns()), quizTableName)
    28  	getQuizResultsForUserQuery = fmt.Sprintf("SELECT %s FROM %s WHERE user_id = $1 ORDER BY created_utc desc", db.ColumnNamesCSV(quizResultCols.Columns()), quizResultTableName)
    29  	getQuizResultsForQuizQuery = fmt.Sprintf("SELECT %s FROM %s WHERE quiz_id = $1 ORDER BY created_utc desc", db.ColumnNamesCSV(quizResultCols.Columns()), quizResultTableName)
    30  )
    31  
    32  // New returns a new model manager.
    33  func New(conn *db.Connection, opts ...db.InvocationOption) *Manager {
    34  	return &Manager{
    35  		BaseManager: dbutil.NewBaseManager(conn, opts...),
    36  	}
    37  }
    38  
    39  // Manager implements database functions.
    40  type Manager struct {
    41  	dbutil.BaseManager
    42  }
    43  
    44  // AllQuzzes returns all the quizzes.
    45  func (m Manager) AllQuzzes(ctx context.Context, userID uuid.UUID) (output []*types.Quiz, err error) {
    46  	lookup := map[string]*types.Quiz{}
    47  	err = m.Invoke(ctx, db.OptLabel("all_quizzes")).Query(getQuizzesForUserQuery, userID).Each(func(r db.Rows) error {
    48  		var q types.Quiz
    49  		if populateErr := db.PopulateInOrder(&q, r, quizCols.Columns()); populateErr != nil {
    50  			return populateErr
    51  		}
    52  		output = append(output, &q)
    53  		lookup[q.ID.String()] = &q
    54  		return nil
    55  	})
    56  	if err != nil {
    57  		return
    58  	}
    59  	err = m.Invoke(ctx, db.OptLabel("all_quizzes_results")).Query(getQuizResultsForUserQuery, userID).Each(func(r db.Rows) error {
    60  		var qr types.QuizResult
    61  		if populateErr := db.PopulateInOrder(&qr, r, quizResultCols.Columns()); populateErr != nil {
    62  			return populateErr
    63  		}
    64  		if quiz, ok := lookup[qr.QuizID.String()]; ok {
    65  			quiz.Results = append(quiz.Results, qr)
    66  		} else {
    67  			return fmt.Errorf("quiz for quiz result not found: %s", qr.QuizID.String())
    68  		}
    69  		return nil
    70  	})
    71  	return
    72  }
    73  
    74  // AllQuizResults returns all the quiz results for a given user.
    75  func (m Manager) AllQuizResults(ctx context.Context, userID uuid.UUID) (output []types.QuizResult, err error) {
    76  	err = m.Invoke(ctx, db.OptLabel("all_quiz_results")).Query(getQuizResultsForUserQuery, userID).OutMany(&output)
    77  	return
    78  }
    79  
    80  // CreateQuiz creates a quiz.
    81  func (m Manager) CreateQuiz(ctx context.Context, q types.Quiz) error {
    82  	return m.Invoke(ctx).Create(&q)
    83  }
    84  
    85  // GetQuiz gets a quiz and associated results.
    86  func (m Manager) GetQuiz(ctx context.Context, id uuid.UUID) (output types.Quiz, found bool, err error) {
    87  	found, err = m.Invoke(ctx).Get(&output, id)
    88  	if err != nil || !found {
    89  		return
    90  	}
    91  	err = m.Invoke(ctx, db.OptLabel("get_quiz_results_for_quiz")).Query(getQuizResultsForQuizQuery, id).Each(func(r db.Rows) error {
    92  		var qr types.QuizResult
    93  		if populateErr := db.PopulateInOrder(&qr, r, quizResultCols.Columns()); populateErr != nil {
    94  			return populateErr
    95  		}
    96  		output.Results = append(output.Results, qr)
    97  		return nil
    98  	})
    99  	return
   100  }
   101  
   102  // UpdateQuiz updates a quiz.
   103  func (m Manager) UpdateQuiz(ctx context.Context, q types.Quiz) error {
   104  	_, err := m.Invoke(ctx).Update(&q)
   105  	return err
   106  }
   107  
   108  // AddQuizResult creates a new quiz result.
   109  func (m Manager) AddQuizResult(ctx context.Context, qr types.QuizResult) error {
   110  	return m.Invoke(ctx).Create(&qr)
   111  }