feat: initial commit
This commit is contained in:
114
internal/store/quiz.go
Normal file
114
internal/store/quiz.go
Normal file
@ -0,0 +1,114 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (s *Store) UpsertQuizCategory(ctx context.Context, category *QuizCategory) error {
|
||||
return errors.WithStack(s.Do(ctx, func(db *gorm.DB) error {
|
||||
var existing *QuizCategory
|
||||
err := db.Find(&existing, "name = ? and theme = ?", category.Name, category.Theme).Error
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if existing != nil {
|
||||
category.Model = existing.Model
|
||||
}
|
||||
|
||||
if err := db.Save(category).Error; err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *Store) UpsertQuizEntry(ctx context.Context, entry *QuizEntry) error {
|
||||
return errors.WithStack(s.Do(ctx, func(db *gorm.DB) error {
|
||||
var existing *QuizEntry
|
||||
err := db.Find(&existing, "provider = ? and provider_id = ?", entry.Provider, entry.ProviderID).Error
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if existing != nil {
|
||||
entry.Model = existing.Model
|
||||
}
|
||||
|
||||
if err := db.Save(entry).Error; err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *Store) GetQuizTurn(ctx context.Context, playInterval time.Duration) (*QuizTurn, error) {
|
||||
var quizTurn *QuizTurn
|
||||
err := s.Tx(ctx, func(tx *gorm.DB) error {
|
||||
now := time.Now().UTC()
|
||||
|
||||
err := tx.Model(&quizTurn).Preload("Entries").Preload("Entries.Category").Order("ended_at DESC").First(&quizTurn, "ended_at >= ?", now).Error
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if quizTurn != nil && quizTurn.ID != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
quizTurn = &QuizTurn{
|
||||
StartedAt: now.Round(time.Hour),
|
||||
EndedAt: now.Add(playInterval).Round(time.Hour),
|
||||
}
|
||||
|
||||
alreadyUsed := make([]uint, 0)
|
||||
err = tx.Table("quiz_turn_entries").Pluck("quiz_entry_id", &alreadyUsed).Error
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
query := tx.Model(&QuizEntry{})
|
||||
|
||||
if len(alreadyUsed) > 0 {
|
||||
query = query.Where("id NOT IN ?", alreadyUsed)
|
||||
}
|
||||
|
||||
var entryIDs []uint
|
||||
err = query.Pluck("id", &entryIDs).Error
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
for range 3 {
|
||||
index := rand.IntN(len(entryIDs))
|
||||
quizTurn.Entries = append(quizTurn.Entries, &QuizEntry{
|
||||
Model: gorm.Model{
|
||||
ID: entryIDs[index],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if err := tx.Save(quizTurn).Error; err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
err = tx.Model(&QuizTurn{}).Preload("Entries").Preload("Entries.Category").First(&quizTurn).Error
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return quizTurn, nil
|
||||
}
|
Reference in New Issue
Block a user