-
Notifications
You must be signed in to change notification settings - Fork 0
/
query.go
119 lines (111 loc) · 2.7 KB
/
query.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
110
111
112
113
114
115
116
117
118
119
package maps_recommendations
import (
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"net/url"
"sync"
"time"
)
var APIKey string
type Place struct {
*googleGeometry `json:"geometry"`
Name string `json:"name"`
Icon string `json:"icon"`
Photos []*googlePhoto `json:"photos"`
Vicinity string `json:"vicinity"`
}
func (p *Place) Public() interface{} {
return map[string]interface{}{
"name": p.Name,
"icon": p.Icon,
"photos": p.Photos,
"vicinity": p.Vicinity,
"lat": p.Lat,
"lng": p.Lng,
}
}
type Query struct {
Lat float64
Lng float64
Journey []string
Radius int
CostRangeStr string
}
func (q *Query) find(types string) (*googleResponse, error) {
u := "https://maps.googleapis.com/maps/api/place/nearbysearch/json"
vals := make(url.Values)
vals.Set("location", fmt.Sprintf("%g,%g", q.Lat, q.Lng))
vals.Set("radius", fmt.Sprintf("%d", q.Radius))
vals.Set("types", types)
vals.Set("key", APIKey)
if len(q.CostRangeStr) > 0 {
r, err := ParseCostRange(q.CostRangeStr)
if err != nil {
return nil, err
}
vals.Set("minprice", fmt.Sprintf("%d", int(r.From)-1))
vals.Set("maxprice", fmt.Sprintf("%d", int(r.To)-1))
}
res, err := http.Get(u + "?" + vals.Encode())
if err != nil {
return nil, err
}
defer res.Body.Close()
var response googleResponse
if err := json.NewDecoder(res.Body).Decode(&response); err != nil {
return nil, err
}
return &response, nil
}
func (q *Query) Run() []interface{} {
rand.Seed(time.Now().UnixNano())
var w sync.WaitGroup
var l sync.Mutex
places := make([]interface{}, len(q.Journey))
for i, r := range q.Journey {
w.Add(1)
go func(types string, i int) {
defer w.Done()
response, err := q.find(types)
if err != nil {
log.Println("Failed to find places:", err)
return
}
if len(response.Results) == 0 {
log.Println("No places found for", types)
return
}
for _, result := range response.Results {
for _, photo := range result.Photos {
photo.URL = "https://maps.googleapis.com/maps/api/place/photo?" +
"maxwidth=1000&photoreference=" + photo.PhotoRef + "&key=" + APIKey
}
}
randI := rand.Intn(len(response.Results))
l.Lock()
places[i] = response.Results[randI]
l.Unlock()
}(r, i)
}
w.Wait()
return places
}
type googleResponse struct {
Results []Place `json:"results"`
}
type googleGeometry struct {
googleLocation `json:"location"`
}
type googleLocation struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
type googlePhoto struct {
Height int `json:"height"`
Width int `json:"width"`
PhotoRef string `json:"photo_reference"`
URL string `json:"url"`
}