from optapy import constraint_provider
from optapy.score import HardSoftScore
from optapy.constraint import Joiners, ConstraintFactory
from domain import Reservation, Employee, Seat
@constraint_provider
def define_constraints(constraint_factory: ConstraintFactory):
return [
#HARD CONSTRAINTS
seat_conflict(constraint_factory),
one_reservation_per_date(constraint_factory),
# employee_conflict(constraint_factory),
#SOFT CONSTRAINTS
prefered_seat(constraint_factory),
team_seat(constraint_factory)
]
def seat_conflict(constraint_factory: ConstraintFactory):
return constraint_factory.for_each_unique_pair(Reservation,
Joiners.equal(lambda res: res.date),
Joiners.equal(lambda res: res.seat)
).penalize("Seat conflict", HardSoftScore.ONE_HARD)
def one_reservation_per_date(constraint_factory: ConstraintFactory):
return constraint_factory.for_each_unique_pair(Reservation,
Joiners.equal(lambda res: res.employee),
Joiners.equal(lambda res: res.date)
).penalize("employee_conflict", HardSoftScore.ONE_HARD)
def employee_conflict(constraint_factory: ConstraintFactory):
return constraint_factory.for_each(Reservation).join(Employee,
Joiners.equal(lambda res: res.employee),
Joiners.equal(lambda res: res.date),
Joiners.equal(lambda res: res.seat)
).penalize("employee_conflict", HardSoftScore.ONE_HARD)
def prefered_seat(constraint_factory: ConstraintFactory):
return constraint_factory.for_each(Reservation).join(Employee,
Joiners.equal(lambda res: res.employee.uuid,
lambda emp: emp.uuid),
Joiners.equal(lambda res: res.seat.seat_id,
lambda emp: emp.id_emplacement_pref)
).penalize("Prefered Seat Constraint", HardSoftScore.ONE_SOFT)
def team_seat(constraint_factory: ConstraintFactory):
return constraint_factory.for_each(Reservation).join(Employee,
Joiners.equal(lambda res: res.employee.uuid,
lambda emp: emp.uuid),
Joiners.equal(lambda res: res.seat.team_id,
lambda emp: emp.idequipe)
).penalize("Team Seat Constraint", HardSoftScore.ONE_SOFT)
ZnJvbSBvcHRhcHkgaW1wb3J0IGNvbnN0cmFpbnRfcHJvdmlkZXIKZnJvbSBvcHRhcHkuc2NvcmUgaW1wb3J0IEhhcmRTb2Z0U2NvcmUKZnJvbSBvcHRhcHkuY29uc3RyYWludCBpbXBvcnQgSm9pbmVycywgQ29uc3RyYWludEZhY3RvcnkKCmZyb20gZG9tYWluIGltcG9ydCBSZXNlcnZhdGlvbiwgRW1wbG95ZWUsIFNlYXQKCgpAY29uc3RyYWludF9wcm92aWRlcgpkZWYgZGVmaW5lX2NvbnN0cmFpbnRzKGNvbnN0cmFpbnRfZmFjdG9yeTogQ29uc3RyYWludEZhY3RvcnkpOgogICAgcmV0dXJuIFsKICAgICAgICAjSEFSRCBDT05TVFJBSU5UUwogICAgICAgIHNlYXRfY29uZmxpY3QoY29uc3RyYWludF9mYWN0b3J5KSwKICAgICAgICBvbmVfcmVzZXJ2YXRpb25fcGVyX2RhdGUoY29uc3RyYWludF9mYWN0b3J5KSwKICAgICAgICAjIGVtcGxveWVlX2NvbmZsaWN0KGNvbnN0cmFpbnRfZmFjdG9yeSksCiAgICAgICAgI1NPRlQgQ09OU1RSQUlOVFMKICAgICAgICBwcmVmZXJlZF9zZWF0KGNvbnN0cmFpbnRfZmFjdG9yeSksCiAgICAgICAgdGVhbV9zZWF0KGNvbnN0cmFpbnRfZmFjdG9yeSkKICAgIF0KICAgIApkZWYgc2VhdF9jb25mbGljdChjb25zdHJhaW50X2ZhY3Rvcnk6IENvbnN0cmFpbnRGYWN0b3J5KToKICAgIHJldHVybiBjb25zdHJhaW50X2ZhY3RvcnkuZm9yX2VhY2hfdW5pcXVlX3BhaXIoUmVzZXJ2YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKb2luZXJzLmVxdWFsKGxhbWJkYSByZXM6IHJlcy5kYXRlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEpvaW5lcnMuZXF1YWwobGFtYmRhIHJlczogcmVzLnNlYXQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLnBlbmFsaXplKCJTZWF0IGNvbmZsaWN0IiwgSGFyZFNvZnRTY29yZS5PTkVfSEFSRCkKCmRlZiBvbmVfcmVzZXJ2YXRpb25fcGVyX2RhdGUoY29uc3RyYWludF9mYWN0b3J5OiBDb25zdHJhaW50RmFjdG9yeSk6CiAgICByZXR1cm4gY29uc3RyYWludF9mYWN0b3J5LmZvcl9lYWNoX3VuaXF1ZV9wYWlyKFJlc2VydmF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSm9pbmVycy5lcXVhbChsYW1iZGEgcmVzOiByZXMuZW1wbG95ZWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSm9pbmVycy5lcXVhbChsYW1iZGEgcmVzOiByZXMuZGF0ZSkgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLnBlbmFsaXplKCJlbXBsb3llZV9jb25mbGljdCIsIEhhcmRTb2Z0U2NvcmUuT05FX0hBUkQpCgpkZWYgZW1wbG95ZWVfY29uZmxpY3QoY29uc3RyYWludF9mYWN0b3J5OiBDb25zdHJhaW50RmFjdG9yeSk6CiAgICByZXR1cm4gY29uc3RyYWludF9mYWN0b3J5LmZvcl9lYWNoKFJlc2VydmF0aW9uKS5qb2luKEVtcGxveWVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKb2luZXJzLmVxdWFsKGxhbWJkYSByZXM6IHJlcy5lbXBsb3llZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEpvaW5lcnMuZXF1YWwobGFtYmRhIHJlczogcmVzLmRhdGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKb2luZXJzLmVxdWFsKGxhbWJkYSByZXM6IHJlcy5zZWF0KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLnBlbmFsaXplKCJlbXBsb3llZV9jb25mbGljdCIsIEhhcmRTb2Z0U2NvcmUuT05FX0hBUkQpCgoKZGVmIHByZWZlcmVkX3NlYXQoY29uc3RyYWludF9mYWN0b3J5OiBDb25zdHJhaW50RmFjdG9yeSk6CiAgICByZXR1cm4gY29uc3RyYWludF9mYWN0b3J5LmZvcl9lYWNoKFJlc2VydmF0aW9uKS5qb2luKEVtcGxveWVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKb2luZXJzLmVxdWFsKGxhbWJkYSByZXM6IHJlcy5lbXBsb3llZS51dWlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbWJkYSBlbXA6IGVtcC51dWlkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSm9pbmVycy5lcXVhbChsYW1iZGEgcmVzOiByZXMuc2VhdC5zZWF0X2lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbWJkYSBlbXA6IGVtcC5pZF9lbXBsYWNlbWVudF9wcmVmKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLnBlbmFsaXplKCJQcmVmZXJlZCBTZWF0IENvbnN0cmFpbnQiLCBIYXJkU29mdFNjb3JlLk9ORV9TT0ZUKQogICAgCmRlZiB0ZWFtX3NlYXQoY29uc3RyYWludF9mYWN0b3J5OiBDb25zdHJhaW50RmFjdG9yeSk6CiAgICByZXR1cm4gY29uc3RyYWludF9mYWN0b3J5LmZvcl9lYWNoKFJlc2VydmF0aW9uKS5qb2luKEVtcGxveWVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKb2luZXJzLmVxdWFsKGxhbWJkYSByZXM6IHJlcy5lbXBsb3llZS51dWlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbWJkYSBlbXA6IGVtcC51dWlkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSm9pbmVycy5lcXVhbChsYW1iZGEgcmVzOiByZXMuc2VhdC50ZWFtX2lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbWJkYSBlbXA6IGVtcC5pZGVxdWlwZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKS5wZW5hbGl6ZSgiVGVhbSBTZWF0IENvbnN0cmFpbnQiLCBIYXJkU29mdFNjb3JlLk9ORV9TT0ZUKQo=