-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.js
206 lines (180 loc) · 5.32 KB
/
app.js
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
const express = require('express')
const gju = require("geojson-utils")
const {gameArea,players} = require("./gameData")
const app = express()
const graphqlHTTP = require("express-graphql")
const {buildSchema} = require("graphql")
const fetch = require("node-fetch")
const SERVER_URL = "http://localhost:3000"
const schema = buildSchema(`
type Status{
"""
TRUE if coordinates was inside gameArea, otherwise FALSE
"""
status: String
"""
Contains a string with a description of whether given coordinates was inside or not inside the gameArea
"""
msg: String
}
type Coordinate {
latitude: Float!
longitude:Float!
}
type Coordinates {
coordinates: [Coordinate]
}
"""
Contains userName of a Team found
"""
type Name {
name : String
}
type Point {
"""
Will ALWAYS have the value Point
"""
type : String
"""
Array with longitude followed by latitude [lon,lat]
"""
coordinates: [Float]
}
type Player {
"""
Will ALWAYS have the value --> Feature <--
"""
type: String
"""
userName of Player (or Team)
"""
properties : Name
"""
GeoJson Point with the users location
"""
geometry : Point
}
"""
Represents a user found, with the distance to the caller
"""
type User {
"""
Distance to the user seached for
"""
distance: Float
"""
userName of the user found
"""
to: String
}
"""
Error for a call, with msg and statuscode
"""
type Error {
msg: String
statuscode : Int
}
union Response = User | Error
type Query {
"""
Returns a GeoJson Polygon representing the legal gameArea
"""
gameArea : Coordinates
"""
Check whether caller, given his latitude and lontitude, is inside the gameArea
"""
isUserInArea("Callers latitude" latitude: Float!,"Callers longitude" longitude:Float!) : Status!
"""
Given callers latitude and longitude all nearby Teams will be found (inside the given radius)
"""
findNearbyPlayers(latitude: Float!, longitude: Float!,distance: Int!):[Player]!
"""
Given callers latitude and longitude, and the userName of the Team to find, returs the distance to this Team
"""
distanceToUser("callers latitude" latitude: Float!,
"callers longitude" longitude: Float!,
"user to find" userName: String) : User!
}
`)
const root = {
isUserInArea: async ({longitude,latitude}) => {
const res = await fetch(`${SERVER_URL}/geoapi/isuserinarea/${longitude}/${latitude}`).then(res=>res.json())
return {status:res.status,msg:res.msg}
},
gameArea : async () => {
const gameArea = await fetch(`${SERVER_URL}/geoapi/gamearea`).then(res=>res.json())
return gameArea
},
findNearbyPlayers: async ({longitude,latitude,distance}) => {
const res = await fetch(`${SERVER_URL}/geoapi/findNearbyPlayers/${longitude}/${latitude}/${distance}`).then(res=>res.json())
return res
},
distanceToUser: async ({longitude,latitude,userName}) => {
const res = await fetch(`${SERVER_URL}/geoapi/distanceToUser/${longitude}/${latitude}/${userName}`).then(res=>res.json())
if(!res.distance){
throw new Error("User not found")
}
return res
}
}
/*
Create a new polygon meant to be used on clients by React Native's MapView which
requres an object as the one we create below
NOTE --> how we swap longitude, latitude values
*/
polygonForClient = {};
polygonForClient.coordinates = gameArea.coordinates[0].map(point => {
return {latitude: point[1],longitude: point[0]}
})
app.use("/geographql",graphqlHTTP({
schema,
rootValue:root,
graphiql:true
}))
//Returns a polygon, representing the gameArea
app.get("/geoapi/gamearea",(req,res)=>{
res.json(polygonForClient);
});
app.get('/geoapi/isuserinarea/:lon/:lat', function(req, res) {
const lon = req.params.lon;
const lat = req.params.lat;
const point = {"type":"Point","coordinates":[lon,lat]}
let isInside = gju.pointInPolygon(point,gameArea);
let result = {};
result.status = isInside;
let msg = isInside ? "Point was inside the tested polygon":
"Point was NOT inside tested polygon";
result.msg = msg;
res.json(result);
});
app.get('/geoapi/findNearbyPlayers/:lon/:lat/:rad', function(req, res) {
const lon = Number(req.params.lon);
const lat = Number(req.params.lat);
const rad = Number(req.params.rad);
const point = {"type":"Point","coordinates":[lon,lat]}
let isInside = gju.pointInPolygon(point,gameArea);
let result = [];
players.forEach(player => {
if (gju.geometryWithinRadius(player.geometry, point, rad)) {
result.push(player);
}
})
res.json(result);
});
app.get('/geoapi/distanceToUser/:lon/:lat/:username', function(req, res) {
const {lon,lat,username} = req.params
const point = {"type":"Point","coordinates":[Number(lon),Number(lat)]}
console.log(point,username);
const user = players.find((player)=> {
return player.properties.name===username
});
if(!user){
res.status(404);
return res.json({msg:"User not found"});
}
let distance = gju.pointDistance(point,user.geometry);
result = {distance:distance,to:username}
res.json(result);
});
app.get('/', (req, res) => res.send('Geo Demo!'))
app.listen(3000, () => console.log('Example app listening on port 3000!'))