Skip to content

Commit

Permalink
Refactor strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
yasuflatland-lf committed Aug 21, 2024
1 parent 01cada1 commit 735b5f2
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 118 deletions.
26 changes: 0 additions & 26 deletions backend/graph/services/card.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ type CardService interface {
limit int, updatedSortOrder string, intervalDaysSortOrder string) ([]*model.Card, error)
GetCardsByDefaultLogic(ctx context.Context, cardGroupID int64,
limit int) ([]*repository.Card, error)
GetRandomRecentCards(ctx context.Context, fromDate time.Time, limit int, sortOrder string) ([]*model.Card, error)
}

func NewCardService(db *gorm.DB, defaultLimit int) CardService {
Expand Down Expand Up @@ -341,7 +340,6 @@ func (s *cardService) GetCardsByUserAndCardGroup(
return cards, nil
}

// Shuffle cards
func (s *cardService) ShuffleCards(cards []repository.Card,
limit int) []*model.Card {
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
Expand Down Expand Up @@ -400,27 +398,3 @@ func (s *cardService) GetCardsByDefaultLogic(ctx context.Context,

return cards, nil
}

func (s *cardService) GetRandomRecentCards(
ctx context.Context, fromDate time.Time, limit int, sortOrder string) ([]*model.Card, error) {
var cards []repository.Card

// Validate sortOrder, default to "desc" if not valid
if sortOrder != repo.ASC && sortOrder != repo.DESC {
sortOrder = repo.DESC
}

// Create the query with the fromDate filter, ordering by created, and limit
err := s.db.WithContext(ctx).
Where("created >= ?", fromDate).
Order(fmt.Sprintf("created %s", sortOrder)).
Limit(limit).
Find(&cards).Error

if err != nil {
return nil, goerr.Wrap(err, "Failed to retrieve recent cards")
}

// Shuffle the cards
return s.ShuffleCards(cards, limit), nil
}
78 changes: 0 additions & 78 deletions backend/graph/services/card_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,84 +679,6 @@ func (suite *CardTestSuite) TestCardService() {
assert.NotEqual(suite.T(), shuffledCards1, shuffledCards2, "Different shuffles should result in different orders")
})

suite.Run("Normal_GetRecentCards", func() {
// Arrange
cardService := suite.sv.(services.CardService)
userService := suite.sv.(services.UserService)
cardGroupService := suite.sv.(services.CardGroupService)
roleService := suite.sv.(services.RoleService)
ctx := context.Background()

// Create a user and card group using testutils
createdGroup, _, _ := testutils.CreateUserAndCardGroup(ctx, userService, cardGroupService, roleService)

// Add some cards with different creation times
for i := 0; i < 10; i++ {
input := model.NewCard{
Front: "Recent Front " + strconv.Itoa(i),
Back: "Recent Back " + strconv.Itoa(i),
ReviewDate: time.Now().UTC().Add(-time.Duration(i) * time.Hour),
CardgroupID: createdGroup.ID,
}
_, err := cardService.CreateCard(ctx, input)
assert.NoError(suite.T(), err)
}

// Define the date from which to fetch recent cards
fromDate := time.Now().UTC().Add(-5 * time.Hour) // fetch cards created in the last 5 hours
limit := 5

// Act
recentCards, err := cardService.GetRandomRecentCards(ctx, fromDate, limit,
repo.DESC)

// Assert
assert.NoError(suite.T(), err)
assert.Len(suite.T(), recentCards, limit)
for _, card := range recentCards {
assert.True(suite.T(), card.Created.After(fromDate), "Card should be created after the fromDate")
}
})

suite.Run("Normal_GetRecentCards_LimitExceeds", func() {
// Arrange
cardService := suite.sv.(services.CardService)
userService := suite.sv.(services.UserService)
cardGroupService := suite.sv.(services.CardGroupService)
roleService := suite.sv.(services.RoleService)
ctx := context.Background()

// Reuse the same method to create a user and card group
createdGroup, _, _ := testutils.CreateUserAndCardGroup(ctx, userService, cardGroupService, roleService)

// Add some cards with different creation times
for i := 0; i < 10; i++ {
input := model.NewCard{
Front: "Recent Front " + strconv.Itoa(i),
Back: "Recent Back " + strconv.Itoa(i),
ReviewDate: time.Now().UTC().Add(-time.Duration(i) * time.Hour),
CardgroupID: createdGroup.ID,
}
_, err := cardService.CreateCard(ctx, input)
assert.NoError(suite.T(), err)
}

// Define the date from which to fetch recent cards
fromDate := time.Now().UTC().Add(-24 * time.Hour)
limit := 15 // Exceeds the number of available cards

// Act
recentCards, err := cardService.GetRandomRecentCards(ctx, fromDate, limit,
repo.DESC)

// Assert
assert.NoError(suite.T(), err)
assert.True(suite.T(), len(recentCards) <= limit, "Number of cards should not exceed the limit")
for _, card := range recentCards {
assert.True(suite.T(), card.Created.After(fromDate), "Card should be created after the fromDate")
}
})

}

func TestCardTestSuite(t *testing.T) {
Expand Down
8 changes: 7 additions & 1 deletion backend/pkg/usecases/swipe_manager/default_state_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ func (d *defaultStateStrategy) Run(ctx context.Context,
newSwipeRecord model.NewSwipeRecord) ([]*model.Card, error) {

// Fetch random recent added words
cards, err := d.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(ctx, newSwipeRecord.CardGroupID, config.Cfg.PGQueryLimit, repo.DESC, repo.ASC)
cards, err := d.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(
ctx,
newSwipeRecord.CardGroupID,
config.Cfg.PGQueryLimit,
repo.DESC,
repo.ASC)

if err != nil {
return nil, goerr.Wrap(err)
}
Expand Down
23 changes: 16 additions & 7 deletions backend/pkg/usecases/swipe_manager/difficult_state_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
repo "backend/pkg/repository"
"github.com/m-mizutani/goerr"
"golang.org/x/net/context"
"time"
)

type difficultStateStrategy struct {
Expand All @@ -30,18 +29,28 @@ func NewDifficultStateStrategy(swipeManagerUsecase SwipeManagerUsecase) Difficul

func (d *difficultStateStrategy) Run(ctx context.Context,
newSwipeRecord model.NewSwipeRecord) ([]*model.Card, error) {
// Past 1 week
fromDate := time.Now().AddDate(0, 0, -7)

// Fetch random recent created card within a week.
cards, err := d.swipeManagerUsecase.Srv().GetRandomRecentCards(
ctx, fromDate, d.amountOfSwipes, repo.DESC)
// Fetch random recent added words from remembered ones
cards, err := d.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(
ctx,
newSwipeRecord.CardGroupID,
config.Cfg.PGQueryLimit,
repo.DESC,
repo.DESC)

if err != nil {
return nil, goerr.Wrap(err)
}

return cards, nil
cardAmount, err := d.swipeManagerUsecase.DetermineCardAmount(
cards,
d.amountOfSwipes)

if err != nil {
return nil, goerr.Wrap(err)
}

return cards[:cardAmount], nil
}

func (d *difficultStateStrategy) IsApplicable(ctx context.Context, newSwipeRecord model.NewSwipeRecord, latestSwipeRecords []*repository.SwipeRecord) bool {
Expand Down
13 changes: 11 additions & 2 deletions backend/pkg/usecases/swipe_manager/easy_state_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,21 @@ func (e *easyStateStrategy) Run(ctx context.Context,
newSwipeRecord model.NewSwipeRecord) ([]*model.Card, error) {

// Fetch random unknown words
cards, err := e.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(ctx, newSwipeRecord.CardGroupID, config.Cfg.PGQueryLimit, repo.ASC, repo.ASC)
cards, err := e.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(
ctx,
newSwipeRecord.CardGroupID,
config.Cfg.PGQueryLimit,
repo.ASC,
repo.ASC)

if err != nil {
return nil, goerr.Wrap(err)
}

cardAmount, err := e.swipeManagerUsecase.DetermineCardAmount(cards, e.amaountOfUnKnownWords)
cardAmount, err := e.swipeManagerUsecase.DetermineCardAmount(
cards,
e.amaountOfUnKnownWords)

if err != nil {
return nil, goerr.Wrap(err)
}
Expand Down
25 changes: 24 additions & 1 deletion backend/pkg/usecases/swipe_manager/good_state_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"backend/graph/services"
"backend/pkg/config"
"backend/pkg/logger"
repo "backend/pkg/repository"
"github.com/m-mizutani/goerr"
"golang.org/x/net/context"
)

Expand All @@ -30,7 +32,28 @@ func NewGoodStateStrategy(swipeManagerUsecase SwipeManagerUsecase) GoodStateStra
// Run ChangeState changes the state of the given swipe records to GOOD
func (g *goodStateStrategy) Run(ctx context.Context,
newSwipeRecord model.NewSwipeRecord) ([]*model.Card, error) {
return nil, nil

// Default algorithm, random words updated old, but the interval is closer
cards, err := g.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(
ctx,
newSwipeRecord.CardGroupID,
config.Cfg.PGQueryLimit,
repo.ASC,
repo.ASC)

if err != nil {
return nil, goerr.Wrap(err)
}

cardAmount, err := g.swipeManagerUsecase.DetermineCardAmount(
cards,
g.amountOfSwipes)

if err != nil {
return nil, goerr.Wrap(err)
}

return cards[:cardAmount], nil
}

func (g *goodStateStrategy) IsApplicable(ctx context.Context, newSwipeRecord model.NewSwipeRecord, latestSwipeRecords []*repository.SwipeRecord) bool {
Expand Down
13 changes: 11 additions & 2 deletions backend/pkg/usecases/swipe_manager/inwhile_state_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,21 @@ func NewInWhileStateStrategy(swipeManagerUsecase SwipeManagerUsecase) InWhileSta
func (d *inWhileStateStrategy) Run(ctx context.Context,
newSwipeRecord model.NewSwipeRecord) ([]*model.Card, error) {
// Fetch random known words, sorting by the most recent updates
cards, err := d.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(ctx, newSwipeRecord.CardGroupID, config.Cfg.PGQueryLimit, repo.DESC, repo.DESC)
cards, err := d.swipeManagerUsecase.Srv().GetRandomCardsFromRecentUpdates(
ctx,
newSwipeRecord.CardGroupID,
config.Cfg.PGQueryLimit,
repo.DESC,
repo.DESC)

if err != nil {
return nil, goerr.Wrap(err, "failed to fetch random cards")
}

cardAmount, err := d.swipeManagerUsecase.DetermineCardAmount(cards, d.amountOfKnownWords)
cardAmount, err := d.swipeManagerUsecase.DetermineCardAmount(
cards,
d.amountOfKnownWords)

if err != nil {
return nil, goerr.Wrap(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (suite *SwipeManagerTestSuite) TestUpdateRecords() {
assert.NotEmpty(suite.T(), swipeRecords)
})

suite.Run("Normal_NewDifficultStateStrategy", func() {
suite.Run("Normal_DifficultStateStrategy", func() {
// Arrange
card, _, user, err := testutils.CreateUserCardAndCardGroup(ctx,
suite.userService, suite.cardGroupService, suite.roleService, suite.cardService)
Expand Down

0 comments on commit 735b5f2

Please sign in to comment.