Skip to content

Commit

Permalink
Merge pull request #7 from wuqinqiang/feat/strategy
Browse files Browse the repository at this point in the history
feat: Add LeastRecentlyUsed option  for selector
  • Loading branch information
wuqinqiang authored Feb 26, 2023
2 parents b1aa73f + d3b14e9 commit 81b35a9
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 32 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,14 @@ go run main.go daemon --files="CET4.txt,CET6.txt" --spec="@every 10s" --word-num
- spec:表示推送频率设置,默认为每小时生成一个新的短语,具体时间规则使用的是 [robif/cron](https://github.com/robfig/cron)
库,请参考该库的文档自行设置。
- word-number:表示生成一次短语使用的单词数量,默认为 5 个,最多不超过 10 个
- strategy: 单词选择策略,默认随机random,还可选择 leastRecentlyUsed,最近最少被使用的单词

![example](./library/example.png)

**单词选择规则**

- 默认:随机 (done)
- 最近最少推送(todo)
- 最近最少推送(done)

### 指定单词,直接生成短语

Expand Down
12 changes: 11 additions & 1 deletion cmd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ var DaemonCmd = &cli.Command{
Usage: "多少个单词组成一个短语",
Value: 5, //default
},
&cli.StringFlag{
Name: "strategy",
Usage: "单词选择策略,默认随机random,还可选择 leastRecentlyUsed,最近最少被使用的单词",
Value: "random",
},
},

Action: func(cctx *cli.Context) error {
Expand All @@ -58,7 +63,12 @@ var DaemonCmd = &cli.Command{

importer := collector.NewImporter(collectors...)

s := selector.New(selector.Random, selector.WithWordNumber(cctx.Int("word-number")))
strategy := selector.Random
if cctx.String("strategy") == string(selector.LeastRecentlyUsed) {
strategy = selector.LeastRecentlyUsed
}

s := selector.New(strategy, selector.WithWordNumber(cctx.Int("word-number")))
n := notify.New(settings.Senders())
core := core.New(generator, importer, s, n, core.WithSpec(cctx.String("spec")))

Expand Down
9 changes: 9 additions & 0 deletions selector/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package selector

type Option func(srv *Srv)

func WithWordNumber(wordNumer int) Option {
return func(srv *Srv) {
srv.wordNumber = wordNumer
}
}
40 changes: 21 additions & 19 deletions selector/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,19 @@ const (
Default StrategyType = "default"
Random StrategyType = "random"
LeastRecentlyUsed StrategyType = "leastRecentlyUsed"

MinWordsNum = 5
MaxWordsNum = 10
)

type Selector interface {
NextWords(ctx context.Context) (words model.Words, err error)
SetStrategyType(strategy StrategyType)
SetStrategyType(strategy Strategy)
}
type Strategy interface {
Select(words model.Words) model.Words
}

type Option func(srv *Srv)

func WithWordNumber(wordNumer int) Option {
return func(srv *Srv) {
srv.wordNumber = wordNumer
}
}

type Srv struct {
dao.Dao
wordNumber int
Expand All @@ -47,35 +42,42 @@ func New(strategyType StrategyType, options ...Option) Selector {
}

if srv.wordNumber <= 0 {
srv.wordNumber = 5
srv.wordNumber = MinWordsNum
}
if srv.wordNumber > 10 {
srv.wordNumber = 10
if srv.wordNumber > MaxWordsNum {
srv.wordNumber = MaxWordsNum
}

var strategy Strategy

switch strategyType {
// todo
case LeastRecentlyUsed:
strategy = s.NewLeastRecentlyUsed()
case Default:
default:
strategy = s.NewRandom(srv.wordNumber)
strategy = s.NewRandom()
}

srv.strategy = strategy
return srv
}

func (s *Srv) NextWords(ctx context.Context) (words model.Words, err error) {
words, err = s.Word.GetList(ctx)
var list model.Words
list, err = s.Word.GetList(ctx)
if err != nil {
return
}
words = s.strategy.Select(words)

words = s.strategy.Select(list)
// not enough, then all out
if len(words) < s.wordNumber {
return
}
words = words[:s.wordNumber]

return
}

func (s *Srv) SetStrategyType(strategy StrategyType) {
//todo
func (s *Srv) SetStrategyType(strategy Strategy) {
s.strategy = strategy
}
26 changes: 26 additions & 0 deletions selector/strategy/least_recently_used.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package strategy

import (
"sort"

"github.com/wuqinqiang/helloword/dao/model"
)

type LeastRecentlyUsed struct{}

func NewLeastRecentlyUsed() *LeastRecentlyUsed {
return &LeastRecentlyUsed{}
}

func (l LeastRecentlyUsed) Select(words model.Words) model.Words {
// sort the words by NumRepetitions field in ascending order
sort.Slice(words, func(i, j int) bool {
return words[i].NumRepetitions < words[j].NumRepetitions
})

// sort the words by last_used field in ascending order
sort.Slice(words, func(i, j int) bool {
return words[i].LastUsed < words[j].LastUsed
})
return words
}
15 changes: 4 additions & 11 deletions selector/strategy/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,19 @@ import (
"github.com/wuqinqiang/helloword/dao/model"
)

type RandomStrategy struct {
maxWords int
}
type RandomStrategy struct{}

func NewRandom(maxWords int) *RandomStrategy {
return &RandomStrategy{
maxWords: maxWords,
}
func NewRandom() *RandomStrategy {
return &RandomStrategy{}
}

func (s *RandomStrategy) Select(words model.Words) model.Words {
if len(words) <= s.maxWords {
return words
}
shuffled := make(model.Words, len(words))
copy(shuffled, words)

rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(shuffled), func(i, j int) {
shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
})
return shuffled[:s.maxWords]
return shuffled
}

0 comments on commit 81b35a9

Please sign in to comment.