ULP-ActivitySupport – blob
1 #!/usr/bin/env python3\r
2 \r
3 import json\r
4 import math\r
5 \r
6 \r
7 class Position:\r
8 def __init__(self, *, lat=None, lon=None, x=None, y=None):\r
9 if lat is not None and lon is not None:\r
10 self.lat = lat\r
11 self.lon = lon\r
12 if x is not None and y is not None:\r
13 self.x = x\r
14 self.y = y\r
15 \r
16 def __str__(self):\r
17 if hasattr(self, 'lat'):\r
18 return "(%f, %f)" % (self.lat, self.lon)\r
19 if hasattr(self, 'x'):\r
20 return "(%f, %f)" % (self.x, self.y)\r
21 return "(None)"\r
22 \r
23 def difference_to(self, goal):\r
24 if hasattr(self, 'lat'):\r
25 return (goal.lat - self.lat, goal.lon - self.lon)\r
26 if hasattr(self, 'x'):\r
27 return (goal.x - self.x, goal.y - self.y)\r
28 return None\r
29 \r
30 def distance(self, goal):\r
31 rel = self.difference_to(goal)\r
32 return math.sqrt(rel[0] ** 2 + rel[1] ** 2)\r
33 \r
34 def move_by(self, vector):\r
35 if hasattr(self, 'lat'):\r
36 self.lat += vector[0]\r
37 self.lon += vector[1]\r
38 if hasattr(self, 'x'):\r
39 self.x += vector[0]\r
40 self.y += vector[1]\r
41 \r
42 def toJSON(self):\r
43 if hasattr(self, 'lat'):\r
44 return {\r
45 'lat': self.lat,\r
46 'lon': self.lon,\r
47 }\r
48 if hasattr(self, 'x'):\r
49 return {\r
50 'x': self.x,\r
51 'y': self.y,\r
52 }\r
53 return {}\r
54 \r
55 \r
56 class QuestRequirement:\r
57 def __init__(self, req_type):\r
58 self.type = req_type\r
59 if self.type == 'set' or self.type == 'list':\r
60 self.parts = []\r
61 self.minimum = None\r
62 self.ordered = self.type == 'list'\r
63 if self.type == 'position':\r
64 self.position = None\r
65 if self.type == 'suo_proximity':\r
66 self.suo = None\r
67 self.fulfilled = False\r
68 \r
69 def get_active_requirements(self):\r
70 if self.fulfilled:\r
71 return None\r
72 active_requirements = []\r
73 if self.type not in ['set', 'list']:\r
74 active_requirements.append(self)\r
75 else:\r
76 for part in self.parts:\r
77 if part.is_fulfilled():\r
78 continue\r
79 else:\r
80 active_requirements.extend(part.get_active_requirements())\r
81 if self.ordered:\r
82 break\r
83 return active_requirements\r
84 \r
85 def is_fulfilled(self):\r
86 if self.fulfilled:\r
87 return True\r
88 if self.type in ['set', 'list']:\r
89 fulfilled_parts = 0\r
90 for part in self.parts:\r
91 if part.is_fulfilled():\r
92 fulfilled_parts += 1\r
93 minimum = self.minimum\r
94 if minimum is None:\r
95 minimum = len(self.parts)\r
96 if fulfilled_parts >= minimum:\r
97 self.fulfilled = True\r
98 return True\r
99 return False\r
100 \r
101 def from_json(self, req_json):\r
102 data = json.loads(req_json)\r
103 for key in data:\r
104 if key == 'parts':\r
105 self.parts = []\r
106 for part in data['parts']:\r
107 part_json = json.dumps(part)\r
108 new_req = QuestRequirement(part['type'])\r
109 new_req.from_json(part_json)\r
110 self.parts.append(new_req)\r
111 else:\r
112 setattr(self, key, data[key])\r
113 \r
114 \r
115 class Quest:\r
116 def __init__(self, qid = None):\r
117 self.qid = qid\r
118 self.title = None\r
119 self.requirement = None\r
120 self.rewards = None\r
121 self.user = None\r
122 \r
123 \r
124 class Intent:\r
125 def __init__(self, intent_id, position):\r
126 self.id = intent_id\r
127 self.position = position\r
128 \r
129 def toJSON(self):\r
130 return {\r
131 'id': self.id,\r
132 'position': self.position,\r
133 }\r
134 \r
135 \r
136 class User:\r
137 def __init__(self, user_id, name):\r
138 self.id = user_id\r
139 self.name = name\r
140 self.position = None\r
141 self.rotation = 0\r
142 self.color_preference = None\r
143 self.is_virtual = False\r
144 self.intent = {}\r
145 self.mobility = None\r
146 \r
147 def __str__(self):\r
148 return str(self.name) + ": " + str(self.position)\r
149 \r
150 def __repr__(self):\r
151 return "<" + self.__str__() + ">"\r
152 \r
153 def toJSON(self):\r
154 return {\r
155 'id': self.id,\r
156 'name': self.name,\r
157 'position': self.position,\r
158 'rotation': self.rotation,\r
159 'intent': self.intent,\r
160 'color_preference': self.color_preference,\r
161 'mobility': self.mobility,\r
162 'is_virtual': self.is_virtual,\r
163 }\r
164 \r
165 def set_position(self, position):\r
166 self.position = position\r
167 \r
168 def set_rotation(self, rotation):\r
169 self.rotation = rotation\r
170 \r
171 def add_intent(self, intent):\r
172 self.intent[intent.id] = intent\r
173 \r
174 \r
175 class SmartUrbanObject:\r
176 def __init__(self, suo_id, suo_type = None):\r
177 self.id = suo_id\r
178 self.suo_type = suo_type\r
179 self.position = None\r
180 self.rotation = 0\r
181 self.is_virtual = False\r
182 \r
183 def __str__(self):\r
184 return str(self.id) + ": " + str(self.suo_type) + ", " + str(self.position)\r
185 \r
186 def __repr__(self):\r
187 return "<" + self.__str__() + ">"\r
188 \r
189 def toJSON(self):\r
190 return {\r
191 'id': self.id,\r
192 'position': self.position,\r
193 'rotation': self.rotation,\r
194 'suo_type': self.suo_type,\r
195 'range': self.get_range(),\r
196 'is_virtual': self.is_virtual,\r
197 }\r
198 \r
199 def set_position(self, position):\r
200 self.position = position\r
201 \r
202 def set_rotation(self, rotation):\r
203 self.rotation = rotation\r
204 \r
205 def get_range(self):\r
206 return 4\r
207 \r
208 def is_user_in_range(self, user):\r
209 return user.position.distance(self.position) <= self.get_range()\r
210 \r
211 \r
212 class Context:\r
213 def __init__(self, context_id, name = None):\r
214 self.id = context_id\r
215 self.name = name\r
216 self.user = {}\r
217 self.suo = {}\r
218 self.boundaries = {}\r
219 \r
220 def toJSON(self):\r
221 result = {\r
222 'id': self.id,\r
223 'name': self.name,\r
224 'user': self.user,\r
225 'suo': self.suo,\r
226 }\r
227 if 'width' in self.boundaries and 'height' in self.boundaries:\r
228 result['boundaries'] = self.boundaries\r
229 return result;\r
230 \r
231 def add_user(self, user):\r
232 self.user[user.id] = user\r
233 \r
234 def add_suo(self, suo):\r
235 self.suo[suo.id] = suo\r
236 \r
237 def set_boundaries(self, width, height):\r
238 self.boundaries['width'] = width\r
239 self.boundaries['height'] = height\r
240 \r