From 7c429fb0eb25bf0416f38c5e2397a53854fb80cb Mon Sep 17 00:00:00 2001 From: Barak Michener Date: Fri, 29 Dec 2017 14:20:44 -0800 Subject: [PATCH] Initial supply app --- Pipfile | 14 ++++++ Pipfile.lock | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++ supply.py | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 supply.py diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..ebf08b0 --- /dev/null +++ b/Pipfile @@ -0,0 +1,14 @@ +[[source]] + +url = "https://pypi.python.org/simple" +verify_ssl = true +name = "pypi" + + +[packages] + +matplotlib = "*" + + +[dev-packages] + diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..af518f9 --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,130 @@ +{ + "_meta": { + "hash": { + "sha256": "aed9c28be63899aa45429206673c5a773fc0eca0acea8ec8909e1f1fcd6b4e7c" + }, + "host-environment-markers": { + "implementation_name": "cpython", + "implementation_version": "3.6.3", + "os_name": "posix", + "platform_machine": "x86_64", + "platform_python_implementation": "CPython", + "platform_release": "4.14.5-1-ARCH", + "platform_system": "Linux", + "platform_version": "#1 SMP PREEMPT Sun Dec 10 14:50:30 UTC 2017", + "python_full_version": "3.6.3", + "python_version": "3.6", + "sys_platform": "linux" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.python.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "cycler": { + "hashes": [ + "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d", + "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8" + ], + "version": "==0.10.0" + }, + "matplotlib": { + "hashes": [ + "sha256:83a56f713c8126492081ec6b9e885fafb387e966e5c79b88bcdb15e41ca8dd33", + "sha256:769ccc141fb1891ecc2d39300ebb0efde16e7b4ce3d621fd61894a58676e23d4", + "sha256:c83c2009648e1cffde4a1fbd09718a6ae788040ea30f9024bff66fd66262ef39", + "sha256:d6bcda04e8eecac0286e2e893dd025f677a5b49f98872f6646b804e648e9da38", + "sha256:82d4b630f2b73f7282a5c18d64a3a4b2ad2fb9141e43309beb68893770b7127f", + "sha256:4871f85541b559ef10ab0f69f2251d2ac1dca4f14b0819f016191e6daf1ba03c", + "sha256:61107a27999fd6af94c5043f8493335b8b93e788a99ccd5e850bfaaa994a5a57", + "sha256:b8f516d63d81c6b0049bdb72d49e8d7f71b2cbb8f2c8e157354a12c728da20df", + "sha256:6271352603a629d0a1d50fdd98362575043058d354739a6d746eb699be7f81b9", + "sha256:6330d4923351be834abaf4e64ec3c6240947f7dd05d80ce932e09636939cead5", + "sha256:81de6cc0c1053e9439613475436504df1e5ea1d8072b49ab0dd1f41526085f6e", + "sha256:2c66b11ccd48b0aba68b6b8d2045536ff3368b178259762826e2fe2c6bc74b90", + "sha256:168c4fbccd155863ac37a6ccfe3b206a8267c34bc1c46d8e5901f72f6c160ee2", + "sha256:673acab3ea8733e639ddde7baf4ec665763e92871571d254fe00b592cfad99d4", + "sha256:c3a9e2699d63ae18e8c0242359b67725473e92fd60af73d334819dc52e1b53d4", + "sha256:4028fc0d48cc602fc8a0c399d41c20d052034763622d49ddf784da21315adec8", + "sha256:e4524148786bcdf936f8d431925073470d47197483bad69a21f217bb1e79d776", + "sha256:659f5e1aa0e0f01488c61eff47560c43b8be511c6a29293d7f3896ae17bd8b23" + ], + "version": "==2.1.1" + }, + "numpy": { + "hashes": [ + "sha256:910e7ae5eeee8d322775187692c5c66719cd58d230fbfd57245ea3cf75716910", + "sha256:f5c9ca457057cd5e12ddab36cded8b1f38bf1f45bf550d4ca2839b11ec57f597", + "sha256:d29e72413b66df23c75b9b469253c823698ea2e00f58e9e0df64b7a50696e8ac", + "sha256:539345898a4ae17421c159ae2a350901a5e6ce3da8f24168c6c67b3536e13de8", + "sha256:929928932f91082a168e36984179deddd58f8e98822ad2f33a2955d7c4eec596", + "sha256:62b09f3d1ea01d79c16a6642cb21599f53b9338c59971b2418a573155d2202ec", + "sha256:c4b1914d86c43399438518a2ac8bcba2fb64dd5a18efddded3783b9daae70933", + "sha256:6c6feb0647380db6e1d5d49ef9fb59c42240f25fb8df8b6e82ecb436c7e0621a", + "sha256:da2f47e46d7a93b73891d1981378717dc73c6ad5cc4fd23c934bfea7847fa958", + "sha256:4c767b6d9c9a071bb36ea34eb240ee5192fe0bc4c13be5e6c51e0350a30f7ac0", + "sha256:b2f98838f4bbc3bf23af7e97ffcad18a2dc6bbb0726796781e02b9347af6685f", + "sha256:11fcbed36c101a3b9c4636e791efccba82409ebbedaba938c97be8bdddd029cc", + "sha256:8969c8f987f8bcc3e30c014532cfc20e4a8f86a50c361596e086310853adacb7", + "sha256:2875e8055a1ea8d933b1c9d0f8714c0aa11c097bfadfcb8564c4d868fbf09a41", + "sha256:09b87d652c03508447d0f618e1d3ae57595acd3e0f0c11ac91bf68ed7bdb3a28", + "sha256:9cad35b911e150f00bb8080950c7e9f172714bbd0234f5ab74b4e3e2d9288b37", + "sha256:479863de17f66810db00bccf35289555365da45d3b053ccf539b95ab3b9c24f6", + "sha256:b162c6b044960b4ea0f42be049ce2af1d18c60f82748f0a27bd5ad182a731bf3", + "sha256:fa656dccfa9141774440575a6e7875d08b93f4a332eb5ae40877b26bed291c01", + "sha256:7dfa5b49fb2a080bd0d39bfbcff1177bacb14fcb28c857fd65fd0c18938935de", + "sha256:e8e0e75db757e41463888939d26c8058b4ecd25e563c597e9119f512dc0ee1da", + "sha256:c8dc6aa96882df6323bf9545934e37c6e05959bd789ae4b14d50509b093907aa", + "sha256:36ee86d5adbabc4fa2643a073f93d5504bdfed37a149a3a49f4dde259f35a750" + ], + "version": "==1.13.3" + }, + "pyparsing": { + "hashes": [ + "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010", + "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", + "sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e", + "sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07", + "sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5", + "sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18", + "sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58" + ], + "version": "==2.2.0" + }, + "python-dateutil": { + "hashes": [ + "sha256:95511bae634d69bc7329ba55e646499a842bc4ec342ad54a8cdb65645a0aad3c", + "sha256:891c38b2a02f5bb1be3e4793866c8df49c7d19baabf9c1bad62547e0b4866aca" + ], + "version": "==2.6.1" + }, + "pytz": { + "hashes": [ + "sha256:80af0f3008046b9975242012a985f04c5df1f01eed4ec1633d56cc47a75a6a48", + "sha256:feb2365914948b8620347784b6b6da356f31c9d03560259070b2f30cff3d469d", + "sha256:59707844a9825589878236ff2f4e0dc9958511b7ffaae94dc615da07d4a68d33", + "sha256:d0ef5ef55ed3d37854320d4926b04a4cb42a2e88f71da9ddfdacfde8e364f027", + "sha256:c41c62827ce9cafacd6f2f7018e4f83a6f1986e87bfd000b8cfbd4ab5da95f1a", + "sha256:8cc90340159b5d7ced6f2ba77694d946fc975b09f1a51d93f3ce3bb399396f94", + "sha256:dd2e4ca6ce3785c8dd342d1853dd9052b19290d5bf66060846e5dc6b8d6667f7", + "sha256:699d18a2a56f19ee5698ab1123bbcc1d269d061996aeb1eda6d89248d3542b82", + "sha256:fae4cffc040921b8a2d60c6cf0b5d662c1190fe54d718271db4eb17d44a185b7" + ], + "version": "==2017.3" + }, + "six": { + "hashes": [ + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb", + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9" + ], + "version": "==1.11.0" + } + }, + "develop": {} +} diff --git a/supply.py b/supply.py new file mode 100644 index 0000000..b033c69 --- /dev/null +++ b/supply.py @@ -0,0 +1,146 @@ +import math +import random +import matplotlib.pyplot as plt + +BACKLOG_COST = 25 +SUPPLY_COST = 5 + +class Base: + w1 = 0 + w2 = 0 + def request(self): + return 0 + + def reconcile(self, req, got): + a = self.w2 + self.w2 = self.w1 + self.w1 = req + return a + + def cost(self): + return (0, 0) + +class Chain: + supply = 0 + backlog = 0 + last_req = 0 + last_got = 0 + last_ship = 0 + + def __init__(self, initial): + self.supply = initial + + def reconcile(self, req, got): + self.last_req = req + self.last_got = got + self.supply += got + self.backlog += req + out = 0 + if self.backlog > self.supply: + out = self.supply + self.backlog = self.backlog - self.supply + self.supply = 0 + else: + out = self.backlog + self.supply = self.supply - self.backlog + self.backlog = 0 + self.last_ship = out + return out + + def cost(self): + return (self.supply, self.backlog) + +class PlayerChain(Chain): + inp = 0 + name = "Player" + def __init__(self, name, initial): + self.name = name + super().__init__(initial) + + def request(self): + print(self.name) + print("Supply: ", self.supply, " | Backlog: ", self.backlog) + print("Last Requested ", self.last_req, " | Last Recieved: ", self.last_got, " | Last Shipped: ", self.last_ship) + x = input("How many to request [%d]? " % self.inp) + if x != "": + self.inp = int(x) + return self.inp + +class StupidAI(Chain): + def request(self): + if self.supply > 0: + # if self.supply < (self.last_req / 2): + # return self.last_req + return 0 + if self.backlog > 0: + return self.backlog + self.last_req + return self.last_req + +class LessStupidAI(Chain): + def request(self): + return self.last_req + +def variableRequestGenerator(turns, low, high): + for i in range(turns): + x = random.randint(low, high) + yield x + +def simpleRequestGenerator(turns, init=5): + x = init + for i in range(turns): + if i >= x: + yield 8 + else: + yield 4 + +TURNS = 50 + +def main(): + global TURNS + global SUPPLY_COST + global BACKLOG_COST + g = variableRequestGenerator(TURNS, 8, 14) + #chain = [StupidAI(12), PlayerChain("Manufacturer", 12), Base()] + chain = [PlayerChain("me", 12), LessStupidAI(12), LessStupidAI(12), LessStupidAI(12), Base()] + turn = 0 + total_sold = 0 + history = [] + for topreq in g: + turn += 1 + print("\nTurn ", turn) + requests = [x.request() for x in chain] + requests = requests[:-1] + requests.insert(0, topreq) + got = 0 + for i, c in reversed(list(enumerate(chain))): + got = c.reconcile(requests[i], got) + print("Sold ", got, " units.") + total_sold += got + history.append([x.cost() for x in chain]) + print("**********") + print("Sold a total of %d units." % total_sold) + print("Front player was short %d turns." % len([1 for x in history if x[0][1] > 0])) + plot_cost(history) + +def plot_cost(history): + total_cost = [sum([x[0] * SUPPLY_COST + x[1] * BACKLOG_COST for x in y]) for y in history] + print("Final cost: %d" % integrate(total_cost)[-1]) + plt.figure(1) + plt.subplot(211) + for i in range(len(history[0]) - 1): + plt.plot([y[0] - y[1] for y in [x[i] for x in history]]) + plt.axhline(0, color='black') + plt.subplot(212) + plt.plot(integrate(total_cost)) + plt.show() + +def integrate(l): + x = 0 + out = [] + for i in l: + x += i + out.append(x) + return out + +if __name__ == "__main__": + main()