-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintersection2.py
More file actions
339 lines (293 loc) · 15.9 KB
/
intersection2.py
File metadata and controls
339 lines (293 loc) · 15.9 KB
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
import kivy
from kivy.uix.label import Label
from kivy.animation import Animation
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import NumericProperty, ReferenceListProperty
from kivy.clock import Clock
from kivy.core.window import Window
from random import randint
from random import random
from functools import partial
from time import clock
Window.size = (600, 600)
'''
car model : [id, where come from, where to go]
where to go: (turns, nbr way(0 or 1))
turns: forward(1),right(0),left(2)
intersec path[pos]:
_|0 |_
3
1_ _
| 2|
'''
global carsPassed
global timeC
global mode
global switchTimer
global nbrCars
nbrCars = 3
mode = "trafficLights"
trafPara = 20
switchTimer = 0
carsPassed = [0,0,0]
timeC = 0
class BG(Widget):
def __init__(self, **kwargs):
super(BG, self).__init__(**kwargs)
self.nbrCars = Label()
self.tick = Label()
self.add_widget(self.nbrCars)
self.add_widget(self.tick)
self.nbrCars.y = 20
def update(self, *largs):
self.nbrCars.text = "Cars in : " + str(carsPassed[0])
self.tick.text = "Time : " + str(timeC)
class Car(Widget):
angle = NumericProperty(0)
r = NumericProperty(0)
g = NumericProperty(0)
b = NumericProperty(0)
def on_angle(self, item, angle):
if angle == 360:
item.angle = 0
class Layout(FloatLayout):
pass
class Inter2App(App):
global doNextMoveF
global doNextMoveR
doNextMoveF = []
doNextMoveR = []
def intersecProg(self, layout, inQueue, outQueue, inter1, *largs):
global carsPassed
global timeC
global switchTimer
c = Window.center
c = [c[0] - 20, c[1] - 20]
nbrWays = 2
animDur = 0
roadAlign = 40
dirToTake = ((1, 0), (0, 1), (-1, 0), (0, -1))
startPos = (((0, 0), (0, 1)), ((3, 0), (2, 0)), ((3, 3), (3, 2)), ((0, 3), (1, 3)))
endPos = (((0, 3), (0, 2)), ((0, 0), (1, 0)), ((3, 0), (3, 1)), ((3, 3), (2, 3)))
pathAnim = [
((c[0] - roadAlign * 3, c[1] + roadAlign * 3), (c[0] - roadAlign, c[1] + roadAlign * 3), (c[0] + roadAlign, c[1] + roadAlign * 3), (c[0] + roadAlign * 3, c[1] + roadAlign * 3)),
((c[0] - roadAlign * 3, c[1] + roadAlign), (c[0] - roadAlign, c[1] + roadAlign), (c[0] + roadAlign, c[1] + roadAlign), (c[0] + roadAlign * 3, c[1] + roadAlign)),
((c[0] - roadAlign * 3, c[1] - roadAlign), (c[0] - roadAlign, c[1] - roadAlign), (c[0] + roadAlign, c[1] - roadAlign), (c[0] + roadAlign * 3, c[1] - roadAlign)),
((c[0] - roadAlign * 3, c[1] - roadAlign * 3), (c[0] - roadAlign, c[1] - roadAlign * 3), (c[0] + roadAlign, c[1] - roadAlign * 3), (c[0] + roadAlign * 3, c[1] - roadAlign * 3)),
]
inQueueAnim = [
((c[0] - roadAlign * 3, c[1] + roadAlign * 11), (c[0] - roadAlign, c[1] + roadAlign * 11)),
((c[0] - roadAlign * 11, c[1] - roadAlign * 3), (c[0] - roadAlign * 11, c[1] - roadAlign)),
((c[0] + roadAlign * 3, c[1] - roadAlign * 11), (c[0] + roadAlign, c[1] - roadAlign * 11)),
((c[0] + roadAlign * 11, c[1] + roadAlign * 3), (c[0] + roadAlign * 11, c[1] + roadAlign))
]
outQueueAnim = [
((c[0] + roadAlign * 3, c[1] + roadAlign * 11), (c[0] + roadAlign, c[1] + roadAlign * 11)),
((c[0] - roadAlign * 11, c[1] + roadAlign * 3), (c[0] - roadAlign * 11, c[1] + roadAlign)),
((c[0] - roadAlign * 3, c[1] - roadAlign * 11), (c[0] - roadAlign, c[1] - roadAlign * 11)),
((c[0] + roadAlign * 11, c[1] - roadAlign * 3), (c[0] + roadAlign * 11, c[1] - roadAlign))
]
def moveCar(car, futurePos, ttDur, layout, doRemove):
oldPos = car[3].pos[:]
angle = car[3].angle
movex, movey = futurePos[0] - oldPos[0], futurePos[1] - oldPos[1]
if movex < 0:
correctAngle = 270
if angle == 0: correctAngle = -90
elif movex > 0:
correctAngle = 90
elif movey < 0:
correctAngle = 0
if angle == 270: correctAngle = 360
else:
correctAngle = 180
def forwardAnim(futurePos, dur, *largs):
doNextMoveR.pop()
anim = Animation(pos=futurePos, duration=ttDur-dur)
doNextMoveF.append(False)
anim.start(largs[1])
anim.bind(on_complete=partial(popNextMoveF, doRemove, layout))
dur = ttDur*0.1
if correctAngle == angle: dur = 0
doNextMoveR.append(False)
rotat = Animation(angle=correctAngle, duration=dur)
rotat.start(car[3])
rotat.bind(on_complete=partial(forwardAnim, futurePos, dur))
def checkPass(currentPos, posToGo, time):
if time in inter1[posToGo[0]][posToGo[1]]:
potBlocCar = inter1[posToGo[0]][posToGo[1]][time]
if potBlocCar[2][0] == 1 and potBlocCar[1][1] != potBlocCar[2][1]: # check if goes forward and changes way
if (time+1) in inter1[currentPos[0]][currentPos[1]]:
if potBlocCar[0] == inter1[currentPos[0]][currentPos[1]][time+1][0]: # check if that car goes where you are
return True
if (time + 1) in inter1[posToGo[0]][posToGo[1]]:
return True
else:
return False
def popNextMoveF(bool, layout, *largs):
if bool: layout.remove_widget(largs[1])
doNextMoveF.pop()
if len(doNextMoveF)+len(doNextMoveR) == 0:
# adding cars
for i in range(1, nbrCars + 1):
startPt = (randint(0, 3), randint(0, 1))
destination = (randint(0, 2), randint(0, 1))
if len(inQueue[startPt[0]][startPt[1]]) <= 10:
inQueue[startPt[0]][startPt[1]].append([[i, startPt, destination, Car(r=random() * 0.4 + 0.5, g=random() * 0.4 + 0.5, b=random() * 0.4 + 0.5)], -1])
# update stats
timeC += 1
if timeC % 100 == 0:
carsPassed[2] = (carsPassed[2]*(timeC//100-1) + carsPassed[0]-carsPassed[1])/(timeC//100)
print(carsPassed[2]/100)
carsPassed[1] = carsPassed[0]
# move by 1 every car
for x in range(0, nbrWays*2):
for y in range(0, nbrWays * 2):
newInterCase = {}
if inter1[x][y] != {0: []}:
for time, car in inter1[x][y].items():
carDest = ((car[1][0] + car[2][0] + 1) % 4, car[2][1])
if endPos[carDest[0]][carDest[1]] == (x, y) and time == 0:
#outQueue[carDest[0]][carDest[1]].append(car) # move car to outqueue if reach destination
moveCar(car, outQueueAnim[carDest[0]][carDest[1]], animDur, layout, True)
carsPassed[0] += 1
elif time != 0:
newInterCase.update({time - 1: car}) # move by 1 on timeline in case
inter1[x][y] = newInterCase # change the state of the case
if 0 in inter1[x][y]:
moveCar(newInterCase[0], pathAnim[x][y], animDur, layout, False)
for j in range(0, len(inQueue)): # remove or reduce timer for cars in inqueue
road = inQueue[j]
newRoad = []
for way in road:
itemToKeep = []
for i in range(0, len(way)):
item = way[i]
if item[1] != 0:
if item[1] != -1:
item[1] -= 1
itemToKeep.append(item)
newRoad.append(itemToKeep[:])
inQueue[j] = newRoad[:]
# take care of queue (add paths for cars)
if mode == "trafficLights":
if switchTimer <= trafPara:
roadList = [0, 2]
elif switchTimer == trafPara*2+1:
switchTimer = 0
roadList = [0, 2]
else: roadList = [1, 3]
switchTimer += 1
else:
roadList = range(0, 4)
for road in roadList:
for way in range(0, nbrWays):
if mode == "trafficLights": maxListIndex = min(len(inQueue[road][way]), 1)
else: maxListIndex = len(inQueue[road][way])
for carIndex in range(0, maxListIndex):
if inQueue[road][way][carIndex][1] == -1:
car = inQueue[road][way][carIndex][0]
doNotPath = True
markdown = 0
testPath = []
while doNotPath: # search for path
doNotPath = False
markdown += 1
x, y = startPos[car[1][0]][car[1][1]]
doNotPath = doNotPath or markdown in inter1[x][y]
testPath = [markdown]
if car[2][0] != 1: # not forward
futurePath = [(x, y)]
for i in range(0, car[2][0] + abs(car[2][1] - int(car[2][0]*(1/2)))): # go straight until facing exit
x, y = x + dirToTake[car[1][0]][0], y + dirToTake[car[1][0]][1]
futurePath.append((x, y))
doNotPath = doNotPath or checkPass(futurePath[-2], (x, y), markdown + i)
testPath.append(markdown + i + 1)
x, y = futurePath[-1]
markDone = car[2][0] + abs(car[2][1] - int(car[2][0]*(1/2)))
for i in range(0, car[2][0] + abs(car[1][1] - int(car[2][0]*(1/2)))): # straight after the turn towards exit
turnDir = (car[1][0]+car[2][0]-1) % 4
x, y = x + dirToTake[turnDir][0], y + dirToTake[turnDir][1]
futurePath.append((x, y))
doNotPath = doNotPath or checkPass(futurePath[-2], (x, y), markdown + i + markDone)
testPath.append(markdown + i + markDone)
else: # forward
futurePath = [(x, y)]
if car[1][1] != car[2][1]: # if have to change way
indexChange = 0
doNotPath = True
while doNotPath and indexChange < nbrWays*2:
doNotPath = False
testPath = []
x, y = startPos[car[1][0]][car[1][1]]
futurePath = [(x, y)]
doNotPath = doNotPath or markdown in inter1[x][y]
testPath.append(markdown)
for i in range(0, nbrWays*2):
if i == indexChange:
changeMovX = startPos[car[1][0]][car[2][1]][0] - startPos[car[1][0]][car[1][1]][0]
changeMovY = startPos[car[1][0]][car[2][1]][1] - startPos[car[1][0]][car[1][1]][1]
x, y = x + changeMovX, y + changeMovY
doNotPath = doNotPath or (markdown + i) in inter1[x][y]
testPath.append("front collide test: " + str(markdown + i))
else:
x, y = x + dirToTake[car[1][0]][0], y + dirToTake[car[1][0]][1]
futurePath.append((x, y))
doNotPath = doNotPath or checkPass(futurePath[-2], (x, y), markdown + i)
testPath.append(markdown + i + 1)
indexChange += 1
else: # if no change way
for i in range(0, nbrWays * 2 - 1):
x, y = x + dirToTake[car[1][0]][0], y + dirToTake[car[1][0]][1]
futurePath.append((x, y))
doNotPath = doNotPath or checkPass(futurePath[-2], (x, y), markdown + i)
for i in range(0, len(futurePath)): # Add whole path at end timeline
x, y = futurePath[i]
if (markdown + i) in inter1[x][y]:
print("Error duplicate time key " + str(markdown + i))
print("Newkey from" + str(car[0]))
print(" tested " + str(testPath))
print(" adding from " + str(markdown) + " to " + str(markdown + len(futurePath) - 1))
print("Oldkey from" + str(inter1[x][y][markdown + i][0]))
inter1[x][y].update({markdown + i: car})
'''for i in range(0, 4):
for j in range(0, 4):
print("In case " + str(i) + ", " + str(j))
list = []
for key, item in inter1[i][j].items():
list.append(str(key) + ": " + str(item[0]))
print(list)'''
inQueue[road][way][carIndex][1] = markdown - 1 # Add when car exit inQueue
layout.add_widget(car[3])
anim = Animation(pos=inQueueAnim[car[1][0]][car[1][1]], duration=0)
anim &= Animation(angle=90 * car[1][0], duration=0)
doNextMoveF.append(False)
anim.start(car[3])
anim.bind(on_complete=partial(popNextMoveF, False))
'''print("This move:")
for i in range(0, 4):
for j in range(0, 4):
print("In case " + str(i) + ", " + str(j))
list = []
for key, item in inter1[i][j].items():
list.append(str(key)+": "+str(item[0]))
print(list)'''
def build(self):
inQueue = [[[], []], [[], []], [[], []], [[], []]]
inter1 = [
[{}, {}, {}, {}],
[{}, {}, {}, {}],
[{}, {}, {}, {}],
[{}, {}, {}, {}]
]
outQueue = [[[], []], [[], []], [[], []], [[], []]]
layout = Layout()
mainBG = BG()
layout.add_widget(mainBG)
Clock.schedule_interval(partial(self.intersecProg, layout, inQueue, outQueue, inter1), 1/80)
Clock.schedule_interval(mainBG.update, 1 / 80)
return layout
if __name__ == '__main__':
Inter2App().run()