/
completion_suggester.go
109 lines (101 loc) · 3.21 KB
/
completion_suggester.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package core
import (
"fmt"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
// Given slice of Suggesters will take the first one, if not enough
// suggestions will take the second one, ect...
// The OriginalOrder here is the index of the suggester, e.g.,
// 0, 0, 0, 1, 1, 2, 2, 2, 2 (3 items from suggeter #0, 2 from #1, 4 from #4)
type CompletionSuggester struct {
suggesters []Suggester
}
func MakeCompletionSuggester(suggesters []Suggester) *CompletionSuggester {
return &CompletionSuggester{suggesters}
}
func init() {
RegisterSuggester("CompletionSuggester", func(suggesterContext SuggesterContext) Suggester {
return MakeCompletionSuggester([]Suggester(nil))
})
}
func (suggester *CompletionSuggester) MarshalSpec() (SuggesterSpec, error) {
log.Infof("Marshal!")
var specs []SuggesterSpec
for i := range suggester.suggesters {
if spec, err := suggester.suggesters[i].MarshalSpec(); err != nil {
return SuggesterSpec{}, err
} else {
specs = append(specs, spec)
}
}
return SuggesterSpec{
Name: "CompletionSuggester",
Specs: specs,
}, nil
}
func (suggester *CompletionSuggester) UnmarshalSpec(suggesterContext SuggesterContext, spec SuggesterSpec) error {
if spec.Name != "CompletionSuggester" {
return errors.New(fmt.Sprintf("Expected suggester name to be: 'CompletionSuggester', got: '%s'.", spec.Name))
}
if len(spec.Args) != 0 {
return errors.New("CompletionSuggester expected to have no arguments.")
}
if len(spec.Specs) == 0 {
return errors.New("CompletionSuggester expected to have some suggesters, got 0.")
}
for i := range spec.Specs {
if newSuggester, err := MakeSuggesterFromName(suggesterContext, spec.Specs[i].Name); err != nil {
return err
} else {
if err := newSuggester.UnmarshalSpec(suggesterContext, spec.Specs[i]); err != nil {
return err
}
suggester.suggesters = append(suggester.suggesters, newSuggester)
}
}
return nil
}
func (suggester *CompletionSuggester) More(request MoreRequest) ([]ContentItem, error) {
if len(request.CurrentFeed) >= request.MoreItems {
return request.CurrentFeed, nil
}
allItems := make([][]ContentItem, len(suggester.suggesters))
suggestedSize := 0
for i := range request.CurrentFeed {
order := request.CurrentFeed[i].OriginalOrder[0]
request.CurrentFeed[i].OriginalOrder = request.CurrentFeed[i].OriginalOrder[1:]
allItems[order] = append(allItems[order], request.CurrentFeed[i])
suggestedSize++
}
for i, s := range suggester.suggesters {
suggesterRequest := request
suggesterRequest.CurrentFeed = allItems[i]
suggestedSize -= len(allItems[i])
err := error(nil)
if allItems[i], err = s.More(suggesterRequest); err != nil {
return nil, err
} else {
for j := range allItems[i] {
allItems[i][j].OriginalOrder = append([]int64{int64(i)}, allItems[i][j].OriginalOrder...)
}
suggestedSize += len(allItems[i])
}
if suggestedSize >= request.MoreItems {
break
}
}
completion := []ContentItem(nil)
for i := range allItems {
j := 0
for len(completion) < request.MoreItems && j < len(allItems[i]) {
completion = append(completion, allItems[i][j])
j++
}
}
//fmt.Printf("Completion:\n")
//for i, ci := range completion {
// fmt.Printf("%d: %+v\n", i+1, ci)
//}
return completion, nil
}