nehemiah/src/urban_meal_delivery/db/replay/simulations.py
Alexander Hess e4e543bd40
Add ORM models for the simulation data
- add new ORM models `ReplaySimulation` and `ReplayedOrder`
  to store the data generated by the routing simulations
- add migrations script to create the corresponding database tables
  + create "replay_simulations" and "replayed_orders" tables
  + add missing check constraints to "orders" table
  + add unique constraint to "orders" table to enable compound key
  + drop unnecessary check constraints from the "orders" table
- add tests for the new ORM models
  + add `simulation`, `replayed_order`, `make_replay_order()`, and
    `pre_order` fixtures
  + add `ReplayedOrderFactor` faker class
- fix some typos
2021-09-16 11:58:55 +02:00

46 lines
1.5 KiB
Python

"""Provide the ORM's `ReplaySimulation` model for the replay simulations."""
import sqlalchemy as sa
from sqlalchemy import orm
from urban_meal_delivery.db import meta
class ReplaySimulation(meta.Base):
"""A simulation of the UDP's routing given a strategy ...
... for the orders as they arrived in reality.
"""
__tablename__ = 'replay_simulations'
# Columns
id = sa.Column(sa.Integer, primary_key=True, autoincrement=True) # noqa:WPS125
city_id = sa.Column(sa.SmallInteger, nullable=False, index=True)
strategy = sa.Column(sa.Unicode(length=100), nullable=False, index=True)
# `.run` may be used as random seed.
run = sa.Column(sa.SmallInteger, nullable=False)
# Constraints
__table_args__ = (
sa.ForeignKeyConstraint(
['city_id'], ['cities.id'], onupdate='RESTRICT', ondelete='RESTRICT',
),
# A `.strategy` can be replayed several times per `.city`.
sa.UniqueConstraint('city_id', 'strategy', 'run'),
sa.CheckConstraint('run >= 0', name='run_is_a_count'),
)
# Relationships
city = orm.relationship('City', back_populates='replays')
orders = orm.relationship('ReplayedOrder', back_populates='simulation')
def __repr__(self) -> str:
"""Non-literal text representation."""
return '<{cls}({strategy} #{run} in {city})>'.format(
cls=self.__class__.__name__,
strategy=self.strategy,
run=self.run,
city=self.city.name,
)