-
Notifications
You must be signed in to change notification settings - Fork 0
/
randomizer.go
100 lines (75 loc) · 2.11 KB
/
randomizer.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
package main
import (
"fmt"
"math/rand"
"time"
)
type Randomizer struct {
Client *PinterestClient
ClientBoards map[string]Board
BoardIds []string
Max int
PinsPerBoard int
}
type PinsResult struct {
Id string
Pins []Pin
Error error
}
func NewRandomizer(client *PinterestClient, clientBoards map[string]Board) *Randomizer {
return &Randomizer{Client: client, ClientBoards: clientBoards}
}
// Randomizer fetches pins from selected boards and trims them with the max value specified.
func (rnd *Randomizer) GetRandomizedPins(max int, boardIds []string) ([]Pin, error) {
rand.Seed(time.Now().UnixNano())
rnd.Max = max
rnd.ProccessBoards(boardIds)
return rnd.FetchPinsFromSelectedBoards()
}
func (rnd *Randomizer) ProccessBoards(boardIds []string) {
rnd.BoardIds = boardIds
boardCount := len(rnd.BoardIds)
if boardCount > 0 {
rnd.PinsPerBoard = rnd.Max / boardCount
}
}
func (rnd *Randomizer) FetchPinsFromSelectedBoards() ([]Pin, error) {
resultChan := make(chan PinsResult)
for _, boardId := range rnd.BoardIds {
go func(id string) {
board := rnd.ClientBoards[id]
pins, err := rnd.FetchSomePinsFromBoard(board)
resultChan <- PinsResult{Id: board.Name, Pins: pins, Error: err}
}(boardId)
}
allPins := []Pin{}
for i := 0; i < len(rnd.BoardIds); i++ {
r := <-resultChan
fmt.Printf("Received %d pins from %s \n", len(r.Pins), r.Id)
if r.Error != nil {
return nil, r.Error
}
allPins = append(allPins, r.Pins...)
}
return allPins, nil
}
func (rnd *Randomizer) FetchSomePinsFromBoard(board Board) ([]Pin, error) {
fmt.Printf("Request some pins from %s\n", board.Name)
allPins, err := rnd.Client.FetchAllPins(board)
if err != nil {
return nil, err
}
trimmedPins := rnd.Trim(allPins, rnd.PinsPerBoard)
return trimmedPins, nil
}
func (rnd *Randomizer) Trim(pins []Pin, limit int) []Pin {
for len(pins) > limit {
pins = rnd.Remove(pins, rand.Intn(len(pins)))
}
return pins
}
func (rnd *Randomizer) Remove(pins []Pin, i int) []Pin {
pins[i] = pins[len(pins)-1]
// We do not need to put s[i] at the end, as it will be discarded anyway
return pins[:len(pins)-1]
}