-
Notifications
You must be signed in to change notification settings - Fork 0
/
getshowsbylocation.go
148 lines (121 loc) · 4.48 KB
/
getshowsbylocation.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package services
import (
"math"
"net/http"
"time"
"github.com/Wolechacho/ticketmaster-backend/database/entities"
"github.com/Wolechacho/ticketmaster-backend/enums"
)
type GetShowsByLocationRequest struct {
UserId string `json:"userId"`
}
type GetShowsByLocationResponse struct {
Results []ShowsDTO
StatusCode int
}
type ShowsDTO struct {
ShowId string `json:"showId"`
Date time.Time `json:"showDate"`
startTime int64
endTime int64
MovieId string `json:"movieId"`
Title string `json:"movieTitle"`
Description string `json:"movieDescription"`
Language string `json:"language"`
Genre int `json:"genre"`
StartTime time.Time `json:"showStartTime"`
EndTime time.Time `json:"showEndTime"`
AddressLine string `json:"address"`
Coordinates entities.Coordinate `json:"coordinates"`
Distance float64 `json:"distance"`
}
type UserDTO struct {
UserId string
IsDeprecated bool
Coordinates entities.Coordinate
CityId string
}
func distance(coordinate1, coordinate2 entities.Coordinate, unit ...string) float64 {
const PI float64 = 3.141592653589793
radlat1 := float64(PI * float64(coordinate1.Latitude) / 180)
radlat2 := float64(PI * float64(coordinate2.Latitude) / 180)
theta := float64(float64(coordinate1.Longitude) - float64(coordinate2.Longitude))
radtheta := float64(PI * theta / 180)
dist := math.Sin(radlat1)*math.Sin(radlat2) + math.Cos(radlat1)*math.Cos(radlat2)*math.Cos(radtheta)
if dist > 1 {
dist = 1
}
dist = math.Acos(dist)
dist = dist * 180 / PI
dist = dist * 60 * 1.1515
if len(unit) > 0 {
if unit[0] == "K" {
dist = dist * 1.609344
} else if unit[0] == "N" {
dist = dist * 0.8684
}
}
return dist
}
func (showService ShowService) GetShowsByUserLocation(request GetShowsByLocationRequest) (GetShowsByLocationResponse, error) {
//get show that are not deprecated nor cancelled
//sort them by the earliest show date and time
userQuery, err := showService.DB.Table("users").
Where("users.Id = ?", request.UserId).
Where("users.IsDeprecated = ?", false).
Joins("join addresses on users.Id = addresses.EntityId").
Where("addresses.EntityId = ?", request.UserId).
Where("addresses.IsDeprecated = ?", false).
Where("addresses.AddressType = ?", enums.User).
Select("users.Id AS UserId, users.IsDeprecated, addresses.CityId,addresses.Coordinates").
Rows()
if err != nil {
return GetShowsByLocationResponse{StatusCode: http.StatusInternalServerError}, err
}
defer userQuery.Close()
var user UserDTO
i := 0
for userQuery.Next() {
if i > 1 {
break
}
err = userQuery.Scan(&user.UserId, &user.IsDeprecated, &user.CityId, &user.Coordinates)
if err != nil {
return GetShowsByLocationResponse{StatusCode: http.StatusInternalServerError}, err
}
i++
}
showQuery, err := showService.DB.Table("addresses").
Where("addresses.CityId = ?", user.CityId).
Where("addresses.IsDeprecated = ?", false).
Where("addresses.AddressType = ?", enums.Cinema).
Joins("join cinemas on addresses.EntityId = cinemas.Id").
Where("cinemas.IsDeprecated = ?", false).
Joins("join cinemaHalls on cinemas.Id = cinemaHalls.CinemaId").
Where("cinemaHalls.IsDeprecated = ?", false).
Joins("join shows on cinemaHalls.Id = shows.CinemaHallId").
Where("shows.IsDeprecated = ?", false).
Where("shows.IsCancelled = ?", false).
Joins("join movies on shows.MovieId = movies.Id").
Where("movies.IsDeprecated = ?", false).
Select("shows.Id AS ShowId, shows.Date, shows.StartTime, shows.EndTime,movies.Id AS MovieId, movies.Title, movies.Description, movies.Language, movies.Genre,addresses.AddressLine, addresses.Coordinates").
Rows()
if err != nil {
return GetShowsByLocationResponse{StatusCode: http.StatusInternalServerError}, err
}
defer showQuery.Close()
shows := []ShowsDTO{}
for showQuery.Next() {
show := &ShowsDTO{}
err = showQuery.Scan(&show.ShowId, &show.Date, &show.startTime, &show.endTime, &show.MovieId, &show.Title,
&show.Description, &show.Language, &show.Genre, &show.AddressLine, &show.Coordinates)
if err != nil {
return GetShowsByLocationResponse{StatusCode: http.StatusInternalServerError}, err
}
show.StartTime = time.Unix(show.startTime, 0)
show.EndTime = time.Unix(show.endTime, 0)
show.Distance = distance(user.Coordinates, show.Coordinates)
shows = append(shows, *show)
}
return GetShowsByLocationResponse{Results: shows, StatusCode: http.StatusOK}, nil
}