Created
February 4, 2019 07:34
-
-
Save lolobosse/4dcbc39373709cbd56be0e22e138dbe7 to your computer and use it in GitHub Desktop.
Airline Manager Plane combination calculator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
# from constraint import * | |
# | |
# problem = Problem() | |
# | |
# problem.addVariable("Q400 Eco", [80, 0, 0]) | |
# problem.addVariable("Q400 Aff", [0, 44, 0]) | |
# problem.addVariable("Q400 First", [0, 0, 19]) | |
# problem.addVariable("ORY", [368, 107, 19, 4.25]) | |
# problem.addConstraint(lambda a, b) | |
from itertools import chain, combinations | |
class Plane: | |
def __init__(self, name, eco, affaire, first, speed, range, price): | |
self.name = name | |
self.eco = eco | |
self.affaire = affaire | |
self.first = first | |
self.speed = speed | |
self.range = range | |
self.price = price | |
def __repr__(self): | |
return self.name | |
@staticmethod | |
def round_to_upper_quarter(time): | |
return math.ceil(time*4)/4 | |
def required_time(self, point): | |
if isinstance(point, Airport): | |
point = point.distance | |
if point > self.range: | |
return None | |
exact_flight_time = float(point) * float(2.0) / float(self.speed) | |
flight_time = exact_flight_time+2 | |
return self.round_to_upper_quarter(flight_time) | |
def capacity(self): | |
return self.eco + self.affaire + self.first | |
class Airport: | |
def __init__(self, name, eco, affaire, first, distance): | |
factor = 1.0 | |
self.name = name | |
self.eco = int(eco * factor) | |
self.affaire = int(affaire * factor) | |
self.first = int(first * factor) | |
self.distance = distance | |
def __repr__(self): | |
return self.name | |
class Planning: | |
def __init__(self, planes, airports): | |
self.planes = planes | |
self.airports = airports | |
def planification(self): | |
flights = [] | |
lost = [] | |
for a in airports: | |
for p in planes: | |
if p.range < a.distance: | |
continue | |
if p.eco > 0: | |
need_a_plane = a.eco // (p.eco*2) | |
_lost = a.eco % (p.eco*2) | |
lost.append((a, _lost)) | |
if need_a_plane > 0: | |
for i in range(1, need_a_plane+1): | |
flights.append((p,a)) | |
if p.affaire > 0: | |
need_a_plane = a.affaire // (p.affaire * 2) | |
_lost = a.affaire % (p.affaire * 2) | |
lost.append((a, _lost)) | |
if need_a_plane > 0: | |
for i in range(1, need_a_plane + 1): | |
flights.append((p, a)) | |
if p.first > 0: | |
need_a_plane = a.first // (p.first * 2) | |
_lost = a.first % (p.first * 2) | |
lost.append((a, _lost)) | |
if need_a_plane > 0: | |
for i in range(1, need_a_plane + 1): | |
flights.append((p, a)) | |
return flights, lost | |
@staticmethod | |
def powerset(iterable): | |
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" | |
s = list(iterable) | |
return list(chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))) | |
def order_per_plane(self, flights): | |
flights_per_plane = {} | |
for f in flights: | |
is_in_list = flights_per_plane.get(f[0], False) | |
if is_in_list: | |
flights_per_plane[f[0]].append(f[1]) | |
else: | |
flights_per_plane[f[0]]=[f[1]] | |
planes = [] | |
left = [] | |
for item, values in flights_per_plane.items(): | |
remaining_values = values | |
remaining_time = sum([item.required_time(x) for x in remaining_values]) | |
while remaining_time > 0: | |
powerset = self.powerset(values) | |
exact = False | |
for _set in powerset: | |
sum_flights = sum([item.required_time(x) for x in _set]) | |
if sum_flights == 24: | |
exact = True | |
planes.append((item, _set, sum_flights)) | |
for sset in _set: | |
remaining_values.remove(sset) | |
remaining_time = sum([item.required_time(x) for x in remaining_values]) | |
break | |
if exact: | |
continue | |
remaining = [(_set, sum([item.required_time(x) for x in _set])) for _set in powerset if sum([item.required_time(x) for x in _set]) < 24] | |
selected = max(remaining, key=lambda x: x[1]) | |
sum_flights = selected[1] | |
_set = selected[0] | |
if sum_flights >= 22: | |
planes.append((item, _set, sum_flights)) | |
for sset in _set: | |
remaining_values.remove(sset) | |
remaining_time = sum([item.required_time(x) for x in remaining_values]) | |
else: | |
left.append((item, remaining_values, remaining_time)) | |
remaining_time = 0 | |
return planes, left | |
q400 = [Plane("Q400 Eco", 80, 0, 0, 667, 2400, 26500000), Plane("Q400 Aff", 0, 44, 0, 667, 2400, 26500000), Plane("Q400 First", 0, 0, 18, 667, 2400, 26500000)] | |
sukkoi = [Plane("Sukkoi eco", 98, 0, 0, 828, 4578, 42500000), Plane("Sukkoi Aff", 0, 54, 0, 828, 4578,42500000), Plane("Sukkoi First", 0, 0, 23, 828, 4578,42500000)] | |
mix = [Plane("Sukkoi eco", 98, 0, 0, 828, 4578,42500000), Plane("Q400 Aff", 0, 44, 0, 667, 2400, 26500000), Plane("Q400 First", 0, 0, 18, 667, 2400, 26500000)] | |
plane_choices = [q400, sukkoi, mix] | |
for planes in plane_choices: | |
print('*'*50) | |
# Airport("GIB",1028,249,90,1949), Airport("ALP", 1537, 202,56,2475) | |
airports = [Airport("ORY", 72, 107, 19, 694), Airport("BCN", 147, 117, 132, 1095), Airport("ATH", 327, 163, 127, 1518), | |
Airport("HAM", 16, 65, 12, 600), Airport("MXP", 0, 312, 8, 381), Airport("AER", 536, 167, 81, 2233), | |
Airport("LGW", 81, 56, 102, 913), Airport("BMA", 1116, 297, 108, 1287)] | |
planning = Planning(planes, airports) | |
p, lost = planning.planification() | |
plan, remaining = planning.order_per_plane(p) | |
print(str(len(plan))+" "+str(plan)) | |
print("Not scheduled " +str(remaining)) | |
lost_via_schedule = sum([x[0].capacity()*len(x[1]) for x in remaining]) *2 | |
lost_via_dividend = sum([x[1] for x in lost]) | |
price = int(sum([p[0].price for p in plan])) | |
pax = sum([x[0].capacity()*len(x[1]) for x in plan]) * 2 | |
print("Lost %d (Scheduled: %d, Dividend: %d)" % (lost_via_schedule+lost_via_dividend, lost_via_schedule, lost_via_dividend)) | |
print("Price %d M; PAX %d $/PAX %d" % (price /1000000, pax, int(price/pax))) | |
print('*'*50) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment