Skip to content

Commit

Permalink
Models refactor + compute delivery time + display time
Browse files Browse the repository at this point in the history
  • Loading branch information
cfstcyr committed Nov 13, 2023
1 parent fc3accb commit 93fa7b6
Show file tree
Hide file tree
Showing 17 changed files with 485 additions and 200 deletions.
23 changes: 23 additions & 0 deletions src/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from datetime import datetime, timedelta


class Config:
INITIAL_DEPART_TIME = datetime(year=1, month=1, day=1, hour=8)
"""Time when the delivery driver starts his tour from the warehouse.
"""

TIME_WINDOW_SIZE = timedelta(hours=1)
"""Time window size.
"""

TRAVELING_SPEED = 15
"""Speed at which the delivery driver travels between two points in km/h.
"""

DELIVERY_TIME = timedelta(minutes=5)
"""Time it takes to deliver a package.
"""

KMH_TO_MS = 3.6
"""Conversion factor from km/h to m/s.
"""
4 changes: 2 additions & 2 deletions src/models/delivery_man/delivery_man.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import uuid
from dataclasses import dataclass, field
from typing import List
from uuid import UUID, uuid4


@dataclass
class DeliveryMan:
name: str
availabilities: List[int]
id: str = field(default_factory=lambda: str(uuid.uuid4()))
id: UUID = field(default_factory=uuid4)
11 changes: 7 additions & 4 deletions src/models/tour/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from src.models.tour.computed_delivery import ComputedDelivery
from src.models.tour.computed_tour import ComputedTour
from src.models.tour.delivery import (
ComputedDelivery,
Delivery,
DeliveryID,
DeliveryRequest,
)
from src.models.tour.delivery_location import DeliveryLocation
from src.models.tour.delivery_request import DeliveryRequest
from src.models.tour.tour_request import TourRequest
from src.models.tour.tour import ComputedTour, Tour, TourID, TourRequest
9 changes: 0 additions & 9 deletions src/models/tour/computed_delivery.py

This file was deleted.

15 changes: 0 additions & 15 deletions src/models/tour/computed_tour.py

This file was deleted.

65 changes: 65 additions & 0 deletions src/models/tour/delivery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from dataclasses import dataclass, field
from datetime import time

from src.models.delivery_man.delivery_man import DeliveryMan
from src.models.tour.delivery_location import DeliveryLocation

DeliveryID = int
"""Type alias for a delivery ID
"""


@dataclass
class Delivery:
"""Base class for a delivery. This represent a delivery that can be requested or computed which has a location."""

location: DeliveryLocation
"""Location of the delivery
"""

@property
def id(self) -> DeliveryID:
"""ID of the delivery that is unique for a DeliveryLocation
Returns:
DeliveryID: ID of the delivery
"""
return hash(f"{self.location.segment.id}{self.location.positionOnSegment}")


@dataclass
class DeliveryRequest(Delivery):
"""Represents a delivery request that has a location and a time window."""

time_window: int
"""Time window of the request. This number represent the hour of the time window.
For example, time_window=8 means that the time window if from 8h to 9h.
"""


@dataclass
class ComputedDelivery(Delivery):
"""Represent a computed delivery that has a location and a time."""

time: time
"""Computed time of the delivery
"""

@staticmethod
def create_from_request(
delivery_request: DeliveryRequest, time: time
) -> "ComputedDelivery":
"""Creates an instance of ComputedDelivery from a DeliveryRequest and a time.
Args:
delivery_request (DeliveryRequest): Delivery request to create the computed delivery from
time (time): Computed time of the delivery
Returns:
ComputedDelivery: Created instance
"""
return ComputedDelivery(
location=delivery_request.location,
time=time,
)
9 changes: 0 additions & 9 deletions src/models/tour/delivery_request.py

This file was deleted.

84 changes: 84 additions & 0 deletions src/models/tour/tour.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from dataclasses import dataclass, field
from typing import Dict, List
from uuid import UUID

from src.models.delivery_man.delivery_man import DeliveryMan
from src.models.map import Segment
from src.models.tour.delivery import (
ComputedDelivery,
Delivery,
DeliveryID,
DeliveryRequest,
)

TourID = UUID
"""Type alias for Tour ID
"""


@dataclass
class Tour:
"""Base class for tour. This represent a tour that can be request or computed."""

id: TourID
"""ID of the tour. This ID is the same as its DeliveryMan ID.
"""

deliveries: Dict[DeliveryID, Delivery]
"""Map of deliveries of the tour identified by their ID
"""

delivery_man: DeliveryMan
"""Delivery man completing the tour
"""

color: str
"""Color to use to display the tour
"""


@dataclass
class TourRequest(Tour):
"""Represents a tour request that has a list of delivery requests."""

deliveries: Dict[DeliveryID, DeliveryRequest]
"""Map of delivery requests of the tour identified by their ID
"""


@dataclass
class ComputedTour(Tour):
"""Represents a computed tour that has a list of computed deliveries and a route."""

deliveries: Dict[DeliveryID, ComputedDelivery]
"""Map of computed deliveries of the tour identified by their ID
"""

route: List[Segment]
"""List of segments of the route
"""

@staticmethod
def create_from_request(
tour_request: TourRequest,
deliveries: Dict[DeliveryID, ComputedDelivery],
route: List[Segment],
) -> "ComputedTour":
"""Creates an instance of ComputedTour from a TourRequest, a list of computed deliveries and a route.
Args:
tour_request (TourRequest): Tour request to create the computed tour from
deliveries (Dict[DeliveryID, ComputedDelivery]): Map of computed deliveries of the tour identified by their ID
route (List[Segment]): List of segments of the route
Returns:
ComputedTour: Created instance
"""

return ComputedTour(
id=tour_request.id,
deliveries=deliveries,
delivery_man=tour_request.delivery_man,
route=route,
color=tour_request.color,
)
11 changes: 0 additions & 11 deletions src/models/tour/tour_request.py

This file was deleted.

23 changes: 14 additions & 9 deletions src/services/command/commands/add_delivery_request_command.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
from typing import Optional

from src.models.delivery_man.delivery_man import DeliveryMan
from src.models.map.position import Position
from src.models.tour.delivery_request import DeliveryRequest
from src.models.tour import DeliveryRequest, TourID
from src.services.command.abstract_command import AbstractCommand
from src.services.tour.tour_service import TourService


class AddDeliveryRequestCommand(AbstractCommand):
__position: Position
__delivery_man: DeliveryMan
__tour_id: TourID
__time_window: int
__delivery_request: Optional[DeliveryRequest] = None

def __init__(
self, position: Position, delivery_man: DeliveryMan, time_window: int
) -> None:
def __init__(self, position: Position, tour_id: TourID, time_window: int) -> None:
"""
Args:
position (Position): Position of the delivery request
tour_id (TourID): Tour ID to which to add the delivery request (Same as DeliveryMan ID)
time_window (int): Time window of the delivery request
"""

super().__init__("Ajout d'une demande de livraison")
self.__position = position
self.__delivery_man = delivery_man
self.__tour_id = tour_id
self.__time_window = time_window

def execute(self) -> None:
self.__delivery_request = TourService.instance().add_delivery_request(
position=self.__position,
delivery_man=self.__delivery_man,
tour_id=self.__tour_id,
time_window=self.__time_window,
)

Expand All @@ -33,6 +37,7 @@ def undo(self) -> None:
raise Exception("Cannot undo a command that has not been executed")

TourService.instance().remove_delivery_request(
self.__delivery_request, self.__delivery_man
delivery_request_id=self.__delivery_request.id,
tour_id=self.__tour_id,
)
self.__delivery_request = None
33 changes: 22 additions & 11 deletions src/services/command/commands/remove_delivery_request_command.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
from src.models.delivery_man.delivery_man import DeliveryMan
from src.models.tour import DeliveryRequest
from typing import Optional

from src.models.tour import DeliveryRequest, TourID
from src.services.command.abstract_command import AbstractCommand
from src.services.tour.tour_service import TourService


class RemoveDeliveryRequestCommand(AbstractCommand):
__delivery_request: DeliveryRequest
__delivery_man: DeliveryMan
__delivery_request_id: TourID
__tour_id: Optional[TourID] = None
__delivery_request: Optional[DeliveryRequest] = None

def __init__(
self, delivery_request: DeliveryRequest, delivery_man: DeliveryMan
self, delivery_request_id: TourID, tour_id: Optional[TourID] = None
) -> None:
"""
Args:
delivery_request_id (TourID): ID of the delivery request to remove
tour_id (Optional[TourID], optional): ID of the tour to remove the delivery from (same as DeliveryMan ID). Defaults to None.
"""
super().__init__("Retrait d'une demande de livraison")
self.__delivery_request = delivery_request
self.__delivery_man = delivery_man
self.__delivery_request_id = delivery_request_id
self.__tour_id = tour_id

def execute(self) -> None:
TourService.instance().remove_delivery_request(
self.__delivery_request, self.__delivery_man
self.__delivery_request = TourService.instance().remove_delivery_request(
delivery_request_id=self.__delivery_request_id, tour_id=self.__tour_id
)

def undo(self) -> None:
if not self.__delivery_request:
raise Exception("No delivery request to undo")

TourService.instance().add_delivery_request(
position=self.__delivery_request.location.segment.origin,
delivery_man=self.__delivery_man,
time_window=self.__delivery_request.timeWindow,
tour_id=self.__tour_id,
time_window=self.__delivery_request.time_window,
)
self.__delivery_request = None
12 changes: 12 additions & 0 deletions src/services/delivery_man/delivery_man_service.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Dict, List, Optional, Tuple
from uuid import UUID

from reactivex import Observable, combine_latest
from reactivex.subject import BehaviorSubject
Expand Down Expand Up @@ -46,6 +47,17 @@ def selected_values(
"""
return combine_latest(self.__selected_delivery_man, self.__selected_time_window)

def get_delivery_man(self, id: UUID) -> DeliveryMan:
"""Get delivery man from its ID.
Args:
id (UUID): ID of the delivery man
Returns:
DeliveryMan: Delivery man
"""
return self.__delivery_men.value[id]

def create_delivery_man(self, name: str) -> None:
"""Creates a Delivery Man and pass it back.
Expand Down
Loading

0 comments on commit 93fa7b6

Please sign in to comment.