/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/service/interesting.go
154 строки
3 KB
Mike Maxim
interesting people RPC initial implementation CORE-5414 (#7470)
21 июн 2017, 00:06
21 июн 2017, 00:06
ce79d7f
Код
Авторство
О чём код?
package service import ( "context" "sort" "github.com/keybase/client/go/libkb" "github.com/keybase/client/go/protocol/keybase1" ) type rankedList struct { uids []keybase1.UID ranks map[string]int } func newRankedList(uids []keybase1.UID) *rankedList { r := &rankedList{ uids: uids, ranks: make(map[string]int), } for index, uid := range uids { r.ranks[uid.String()] = index } return r } func (r *rankedList) UIDs() []keybase1.UID { return r.uids } func (r *rankedList) Rank(uid keybase1.UID) float64 { var index int var ok bool if index, ok = r.ranks[uid.String()]; !ok { return 0 } total := float64(len(r.uids)) return ((total - float64(index)) / total) } type weightedRankedList struct { *rankedList weight float64 } func newWeightedRankedList(rl *rankedList, weight float64) *weightedRankedList { return &weightedRankedList{ rankedList: rl, weight: weight, } } func (w *weightedRankedList) Weight() float64 { return w.weight } type linearWeightedSelector struct { libkb.Contextified lists []*weightedRankedList } func newLinearWeightedSelector(g *libkb.GlobalContext, lists []*weightedRankedList) *linearWeightedSelector { return &linearWeightedSelector{ Contextified: libkb.NewContextified(g), lists: lists, } } func (w *linearWeightedSelector) getAllUIDs() (res []keybase1.UID) { m := make(map[string]bool) for _, list := range w.lists { uids := list.UIDs() for _, uid := range uids { m[uid.String()] = true } } for uid := range m { res = append(res, keybase1.UID(uid)) } return res } func (w *linearWeightedSelector) Select(maxUsers int) (res []keybase1.UID) { type userScore struct { uid keybase1.UID score float64 } var scores []userScore for _, uid := range w.getAllUIDs() { total := 0.0 // Get score in each list to get a total score for _, list := range w.lists { total += list.Rank(uid) * list.Weight() } scores = append(scores, userScore{ uid: uid, score: total, }) } sort.Slice(scores, func(i, j int) bool { return scores[i].score > scores[j].score }) for _, score := range scores { res = append(res, score.uid) if len(res) > maxUsers { break } } return res } type interestingPeopleFn func(uid keybase1.UID) ([]keybase1.UID, error) type interestingPeopleSource struct { fn interestingPeopleFn weight float64 } type interestingPeople struct { libkb.Contextified sources []interestingPeopleSource } func newInterestingPeople(g *libkb.GlobalContext) *interestingPeople { return &interestingPeople{ Contextified: libkb.NewContextified(g), } } func (i *interestingPeople) AddSource(fn interestingPeopleFn, weight float64) { i.sources = append(i.sources, interestingPeopleSource{ fn: fn, weight: weight, }) } func (i interestingPeople) Get(ctx context.Context, maxUsers int) ([]keybase1.UID, error) { uid := i.G().Env.GetUID() if uid.IsNil() { return nil, libkb.LoginRequiredError{} } var weightedLists []*weightedRankedList for _, source := range i.sources { ppl, err := source.fn(uid) if err != nil { i.G().Log.Debug("interestingPeople: failed to get list from source: %s", err.Error()) return nil, err } weightedLists = append(weightedLists, newWeightedRankedList(newRankedList(ppl), source.weight)) } return newLinearWeightedSelector(i.G(), weightedLists).Select(maxUsers), nil }