Beispiel #1
0
async def car_routine(startt, startx, starty, manager):
    await asyncio.sleep(startt)

    car = Car(startx, starty)
    manager.cars.append(car)

    x, y = car.aDestX, car.aDestY
    cli = await CarWebsocket.create(base_url="ws://localhost:8765")
    # request a parking space
    await cli.send_parking_request(wsmodels.Location(float(x), float(y)), {})
    car.drawing = True

    # Receive the parking allocation information
    space = await cli.receive(wsmodels.ParkingAllocationMessage)
    car.set_allocated_destination(space.lot.location.longitude,
                                  space.lot.location.latitude)

    await cli.send_parking_acceptance(space.lot.id)

    # TODO await confirmation of acceptance

    while True:
        # Send the location of the car at time intervals, while listening for deallocation
        if manager.stop_flag:
            break
        try:
            await asyncio.shield(
                asyncio.wait_for(
                    cli.receive(wsmodels.ParkingCancellationMessage), 3))
        except futures.TimeoutError:
            pass
        x, y = car.get_position(time.time())
        await cli.send_location(wsmodels.Location(float(x), float(y)))
    async def set_allocated_destination(self, lot, now):
        self.aDestX = lot.location.latitude
        self.aDestY = lot.location.longitude
        # now = time.time()

        # cut the last waypoint short to car's current place and time
        lat, long = self.get_position(now)
        add = get_route(wsmodels.Location(lat, long), lot.location, now,
                        self.speed)

        if len(self.waypoints) > 1:
            if self.waypoints[-2].time < now:
                self.waypoints = self.waypoints[:-1]
            else:
                self.waypoints = self.waypoints[:-2]

        self.waypoints += add

        # self.waypoints[-1].time = now
        #
        # self.waypoints[-1].lat = lat
        # self.waypoints[-1].long = long
        #
        # self.waypoints += get_route(wsmodels.Location(lat, long), lot.location, now, self.speed)

        attempt = Attempt(self.waypoints[-1].time, 20, self)

        self.targetid = lot.id

        await self.manager.lotdict[lot.id].register(attempt)
async def hello(websocket, path):

    # receive a request
    m = await websocket.recv()
    print(m)
    # request = json.loads(request)
    # message = deserialize_ws_message(request)

    # send an allocation
    message = serialize_model(
        wsmodels.ParkingAllocationMessage(
            wsmodels.ParkingLot(1, "x", 1.0, wsmodels.Location(200.0, 300.0))))
    await websocket.send(message)

    deallocation = wsmodels.ParkingCancellationMessage(1)

    while True:
        await websocket.recv()
        if random.randint(1, 10) == 1:
            await asyncio.sleep(1)
            await websocket.send(serialize_model(deallocation))
    def __init__(self, starttime, loc, dest, manager):
        self.startX = loc.latitude
        self.startY = loc.longitude
        self.destX = dest.latitude
        self.destY = dest.longitude
        self.waypoints = []
        self.drawing = True
        self.drawhozpos = True
        self.drawverpos = True
        self.drawup = True
        self.starttime = starttime
        self.bestLot = None
        self.tried = []
        self.manager = manager
        self.first_attempt = None
        self.targetid = None

        closeness = 250
        self.speed = 20
        stupidity = 0.5

        self.waypoints.append(Waypoint(starttime, self.startX, self.startY))

        currentX = self.startX
        currentY = self.startY

        lasttime = time.time()

        while geodistance(currentX, currentY, self.destX,
                          self.destY) > closeness:
            # pick a random place to go next, that is probably but not definitely closer to the destination
            mu = (currentX + self.destX) * 0.5
            sigma = abs(currentX - self.destX) * stupidity
            newX = random.normalvariate(mu, sigma)

            mu = (currentY + self.destY) * 0.5
            sigma = abs(currentY - self.destY) * stupidity
            newY = random.normalvariate(mu, sigma)

            p = self.manager.point_to_location(
                self.manager.random_car.randint(1, 9) * self.manager.height /
                10,
                self.manager.random_car.randint(1, 9) * self.manager.width /
                10)

            newX = p.longitude
            newY = p.latitude

            # distance = math.sqrt((currentX - newX)**2 + (currentY - newY)**2)
            distance = geodistance(currentX, currentY, newX, newY)

            duration = distance / self.speed

            self.waypoints += get_route(wsmodels.Location(currentX, currentY),
                                        wsmodels.Location(newX, newY),
                                        lasttime, self.speed)

            currentX = newX
            currentY = newY

            # self.waypoints.append(Waypoint(lasttime + duration, newX, newY))

            lasttime += duration

        bestLot = None
        bestDistance = 10000000000000
        # once close enough to the destination, find the nearest parking lot
        for ilot in manager.lots:
            currentDistance = geodistance(currentX, currentY,
                                          ilot.lot.location.latitude,
                                          ilot.lot.location.longitude)
            if currentDistance < bestDistance:
                bestDistance = currentDistance
                bestLot = ilot

        # drive to the closest lot
        duration = bestDistance / self.speed
        # arrival = lasttime + duration
        # self.waypoints.append(Waypoint(arrival, bestLot.lot.location.latitude, bestLot.lot.location.longitude))
        self.waypoints += get_route(wsmodels.Location(currentX, currentY),
                                    bestLot.lot.location, lasttime, self.speed)
        self.bestLot = bestLot
        attempt = Attempt(self.waypoints[-1].time, 20, self)
        self.first_attempt = attempt
        self.tried.append(bestLot)
        self.targetid = bestLot.lot.id
    async def run_tk(self, root, interval):
        w = tk.Canvas(root, width=self.width * 1.5, height=self.height)
        w.pack()
        last_interval = time.time()

        for i in range(11):
            w.create_rectangle(i * self.width * 0.1 - (self.width * 0.025),
                               0,
                               i * self.width * 0.1 + (self.width * 0.025),
                               self.height,
                               fill="grey",
                               width=0)

        for i in range(11):
            w.create_rectangle(0,
                               i * self.height * 0.1 - (self.height * 0.025),
                               self.width,
                               i * self.height * 0.1 + (self.height * 0.025),
                               fill="grey",
                               width=0)
            w.create_line(0,
                          i * self.height * 0.1,
                          self.width,
                          i * self.height * 0.1,
                          fill="yellow",
                          dash=(5, 5))

        for i in range(10):
            w.create_line(i * self.width * 0.1,
                          0,
                          i * self.width * 0.1,
                          self.height,
                          dash=(5, 5),
                          fill="yellow")

        try:
            while not self.stop_flag:
                w.delete("ani")
                now = time.time()

                for car in self.cars:
                    if car.drawing:
                        x, y = self.loc_to_point(
                            wsmodels.Location(*car.get_position(now)))
                        if car.reallocated:
                            fill = "red"
                        else:
                            fill = "blue"
                        w.create_oval(x,
                                      y,
                                      x + 5,
                                      y + 5,
                                      width=0,
                                      fill=fill,
                                      tags="ani")

                for rogue in self.rogues:
                    if rogue.drawing:
                        if now > rogue.starttime:
                            x, y = self.loc_to_point(
                                wsmodels.Location(*rogue.get_position(now)))
                            if rogue.drawup:
                                if rogue.drawverpos:
                                    x -= 5
                                else:
                                    x += 5
                            else:
                                if rogue.drawhozpos:
                                    y -= 5
                                else:
                                    y += 5
                            if x <= self.width:
                                w.create_oval(x,
                                              y,
                                              x + 5,
                                              y + 5,
                                              width=0,
                                              fill='black',
                                              tags="ani")

                w.delete("outline")
                for simlot in self.lots:
                    x, y = self.loc_to_point(simlot.lot.location)
                    available = int(20 * simlot.available /
                                    simlot.lot.capacity)
                    dxy = self.width * 0.05
                    offsetw = self.width * 0.025
                    offseth = self.height * 0.025
                    # shadow
                    w.create_rectangle(x + available + offsetw,
                                       y + offseth - available + 4,
                                       x + available + dxy + offsetw,
                                       y + dxy + offseth - available,
                                       tags="outline",
                                       fill="#444444444444",
                                       stipple="gray75",
                                       width=0)
                    w.create_polygon(x + available + offsetw,
                                     y + dxy + offseth - available - 2,
                                     x + available + dxy + offsetw,
                                     y + dxy + offseth - available - 2,
                                     x + offsetw + dxy,
                                     y + dxy + offseth,
                                     fill="#444444444444",
                                     tags="outline",
                                     width=0,
                                     stipple="gray75")
                    # colourful bit
                    if simlot.available == 0:
                        red = "ffff"
                        green = "0000"
                    else:
                        if simlot.available < simlot.lot.capacity * 0.5:
                            red = "ffff"
                            green = hex(
                                int(65535 * 2 * (simlot.available /
                                                 simlot.lot.capacity)))[2:]
                        else:
                            red = hex(
                                int(65535 * 2 *
                                    (1 -
                                     (simlot.available / simlot.lot.capacity)))
                            )[2:]
                            green = "ffff"
                    w.create_rectangle(x + self.width * 0.025,
                                       y + self.height * 0.025 - available,
                                       x + dxy + self.width * 0.025,
                                       y + dxy + self.height * 0.025,
                                       width=0,
                                       fill="#" + red + green + "0000",
                                       tags="ani")
                    # outline of roof
                    w.create_rectangle(x + self.width * 0.025,
                                       y + self.height * 0.025 - available,
                                       x + dxy + self.width * 0.025,
                                       y + dxy + self.height * 0.025 -
                                       available,
                                       tags="outline")

                    #roof point
                    if red != "0" and green != "0":
                        darkred = hex(
                            int(65535 * (
                                1 -
                                (simlot.available / simlot.lot.capacity))))[2:]
                        darkgreen = hex(
                            int(65535 *
                                (simlot.available / simlot.lot.capacity)))[2:]
                    else:
                        darkred = "0000"
                        darkgreen = "8888"
                    dark = "#" + darkred + darkgreen + "0000"
                    roofcenterx = x + offsetw + (dxy * 0.5)
                    roofcentery = y + offseth + (dxy * 0.25) - available
                    rooftopleftx = x + offsetw
                    rooftoplefty = y + offseth - available
                    rooftoprightx = x + dxy + offsetw
                    rooftoprighty = y + offseth - available
                    roofbottomrightx = x + dxy + offsetw
                    roofbottomrighty = y + offseth - available + dxy
                    roofbottomleftx = x + offsetw
                    roofbottomlefty = y + offseth - available + dxy
                    w.create_polygon(roofcenterx,
                                     roofcentery,
                                     rooftopleftx,
                                     rooftoplefty,
                                     rooftoprightx,
                                     rooftoprighty,
                                     fill=dark,
                                     tags="outline")
                    w.create_polygon(roofcenterx,
                                     roofcentery,
                                     roofbottomrightx,
                                     roofbottomrighty,
                                     rooftoprightx,
                                     rooftoprighty,
                                     fill=dark,
                                     tags="outline")

                    w.create_line(roofbottomleftx,
                                  roofbottomlefty,
                                  roofcenterx,
                                  roofcentery,
                                  tags="outline")
                    w.create_line(roofbottomleftx,
                                  rooftoplefty,
                                  roofcenterx,
                                  roofcentery,
                                  tags="outline")
                    w.create_line(roofbottomrightx,
                                  roofbottomlefty,
                                  roofcenterx,
                                  roofcentery,
                                  tags="outline")
                    w.create_line(roofbottomrightx,
                                  rooftoplefty,
                                  roofcenterx,
                                  roofcentery,
                                  tags="outline")

                    # outline of wall
                    w.create_rectangle(x + self.width * 0.025,
                                       y + dxy + self.height * 0.025 -
                                       available,
                                       x + dxy + self.width * 0.025,
                                       y + dxy + self.height * 0.025,
                                       tags="outline")

                w.delete("graph")
                now = time.time()
                if now - last_interval >= 0.5:
                    last_interval = now
                    self.stats[Stats.LOTUTILITY].append(
                        self.stats[Stats.LOTUTILITY][-1])
                for g in range(len(self.graphs)):
                    graph = self.graphs[g]
                    graph.draw(w, self.width * 1.1,
                               self.height * 0.1 + (g * 0.5 * self.height),
                               self.width * 1.4,
                               self.height * 0.4 + (g * 0.5 * self.height))

                root.update()
                await asyncio.sleep(interval)
            root.destroy()
        except tk.TclError as e:
            if "application has been destroyed" not in e.args[0]:
                raise
 def point_to_location(self, x: float, y: float) -> wsmodels.Location:
     """Assuming (0, 0) x/y maps to Location(0, 0), compute the Location for an arbitrary x, y point
     """
     return wsmodels.Location(x / SCALE, y / SCALE)
async def car_routine(startt, start_loc, manager):
    await asyncio.sleep(startt)

    car_id = str(uuid4())
    cli = await CarWebsocket.create(
        base_url=manager.app_url.replace('http', 'ws') + "/ws", user_id=car_id)

    car = Car(start_loc, manager, cli)
    manager.cars.append(car)

    # x, y = car.aDestX, car.aDestY
    destws = manager.point_to_location(random.randint(0, manager.width),
                                       random.randint(0, manager.height))
    dest = restmodels.Location(destws.latitude, destws.longitude)
    # TODO this was originally setting everything to 0 - do this properly later

    # request a parking space
    logger.info(f'requesting allocation for car {car_id}')
    waiting = True
    while waiting and not manager.stop_flag:
        await cli.send_parking_request(dest, {})
        car.drawing = True

        futs = [
            cli.receive(wsmodels.ParkingAllocationMessage),
            cli.receive(wsmodels.ErrorMessage)
        ]
        (fut, ), *_ = await asyncio.wait(futs,
                                         return_when=asyncio.FIRST_COMPLETED)
        space = fut.result()
        logger.debug('got result: {}'.format(space))
        if not isinstance(space, wsmodels.ErrorMessage):
            break
        await asyncio.sleep(1)

    if not manager.stop_flag:
        logger.info(f"allocation recieved: for car {car_id}: '{space._type}'")
        now = time.time()
        await car.set_allocated_destination(space.lot, now)

        await cli.send_parking_acceptance(space.lot.id)
        x, y = car.get_position(time.time())
        await cli.send_location(wsmodels.Location(float(x), float(y)))

    if not manager.stop_flag:
        await cli.receive(wsmodels.ConfirmationMessage)
        logger.info("conf recieved")

    while not manager.stop_flag and not car.finished:
        # Send the location of the car at time intervals, while listening for deallocation
        try:
            deallocation = await asyncio.shield(
                asyncio.wait_for(
                    cli.receive(wsmodels.ParkingDeallocationMessage), 3))
        except futures.TimeoutError:
            deallocation = None
        if deallocation is not None and not car.finished:
            logger.info("Recieved deallocation")
            print("deallocated")
            car.reallocated = True
            waiting = True
            while waiting and not manager.stop_flag:
                await cli.send_parking_request(dest, {})
                car.drawing = True

                futs = [
                    cli.receive(wsmodels.ParkingAllocationMessage),
                    cli.receive(wsmodels.ErrorMessage)
                ]
                (fut, ), *_ = await asyncio.wait(
                    futs, return_when=asyncio.FIRST_COMPLETED)
                space = fut.result()
                logger.debug('got result: {}'.format(space))
                if not isinstance(space, wsmodels.ErrorMessage):
                    break
                await asyncio.sleep(1)

            if not manager.stop_flag:
                logger.info(
                    f"allocation recieved: for car {car_id}: '{space._type}'")
                now = time.time()
                await car.set_allocated_destination(space.lot, now)

                await cli.send_parking_acceptance(space.lot.id)
        logger.info(f'<Car {car_id}>: heartbeat ** send location')
        x, y = car.get_position(time.time())
        # TODO this will probably change with the API
        await cli.send_location(wsmodels.Location(float(x), float(y)))