From df0f14bcc24e2d0096a0e8f3640bcb883d0a9771 Mon Sep 17 00:00:00 2001 From: BlackYps <52536103+BlackYps@users.noreply.github.com> Date: Sun, 25 Sep 2022 16:00:09 +0200 Subject: [PATCH] Automated seasons (#55) --- Pipfile | 2 + Pipfile.lock | 811 ++++++++++++---------- service.py | 4 + service/__init__.py | 2 +- service/config.py | 1 + service/db/models.py | 3 + service/generate_season.sql | 113 +++ service/season_generator.py | 45 ++ tests/data/test-data.sql | 12 +- tests/unit_tests/test_league_service.py | 41 -- tests/unit_tests/test_season_generator.py | 64 ++ 11 files changed, 699 insertions(+), 399 deletions(-) create mode 100644 service/generate_season.sql create mode 100644 service/season_generator.py create mode 100644 tests/unit_tests/test_season_generator.py diff --git a/Pipfile b/Pipfile index 254c7fd..840ca95 100644 --- a/Pipfile +++ b/Pipfile @@ -17,6 +17,7 @@ aio_pika = "*" aiocron = "*" prometheus_client = "*" yoyo-migrations = "*" +pamqp = "==2.3.0" [dev-packages] pytest = "*" @@ -27,6 +28,7 @@ python-coveralls = "*" mock = "*" pytest-mock = "*" vulture = "*" +freezegun = "*" [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index ceb8503..0e8bf4b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "06ac7d18c22aaf894db873b7f932dcb5e713849842409f2fa9bffe0048552c09" + "sha256": "21c1e122848d3ce6d9313940ad90f884c9a0b5904d81eb6f0c9a7aeb02d137a2" }, "pipfile-spec": 6, "requires": { @@ -18,27 +18,27 @@ "default": { "aio-pika": { "hashes": [ - "sha256:1d4305a5f78af3857310b4fe48348cdcf6c097e0e275ea88c2cd08570531a369", - "sha256:e69afef8695f47c5d107bbdba21bdb845d5c249acb3be53ef5c2d497b02657c0" + "sha256:4bf23e54bceb86b789d4b4a72ed65f2d83ede429d5f343de838ca72e54f00475", + "sha256:d89658148def0d8b8d795868a753fe2906f8d8fccee53e4a1b5093ddd3d2dc5c" ], "index": "pypi", - "version": "==6.8.0" + "version": "==6.8.2" }, "aiocron": { "hashes": [ - "sha256:ad7d3b9bd88897934ffd18937ff235ab9fb01358280fd40e01461fd5f76348bd", - "sha256:f06d7b84b86d6cb7156c01e640b4122da86afaa4873c6bcf79e57c4762e48789" + "sha256:48546513faf2eb7901e65a64eba7b653c80106ed00ed9ca3419c3d10b6555a01", + "sha256:b6313214c311b62aa2220e872b94139b648631b3103d062ef29e5d3230ddce6d" ], "index": "pypi", - "version": "==1.7" + "version": "==1.8" }, "aiomysql": { "hashes": [ - "sha256:811569c0db118dd2685f0878f5cebf17a11e89a995fa14261d5fa0254113842c", - "sha256:a81a97da3dd732635926a8ea6adbbf2d1345799680bf61b5f89e730bcec88cc5" + "sha256:0d686c4fdae6b67d1825d8be60fa3b0e644fca2c84d3c936d850fc259c8e107e", + "sha256:b66fa1481ca71c5ee0d933ec3abf51f6136543a3710ba80b134eb33da7ed6f13" ], "index": "pypi", - "version": "==0.0.21" + "version": "==0.1.1" }, "aiormq": { "hashes": [ @@ -72,200 +72,247 @@ }, "croniter": { "hashes": [ - "sha256:0f97b361fe343301a8f66f852e7d84e4fb7f21379948f71e1bbfe10f5d015fbd", - "sha256:a70dfc9d52de9fc1a886128b9148c89dd9e76b67d55f46516ca94d2d73d58219" + "sha256:12369c67e231c8ce5f98958d76ea6e8cb5b157fda4da7429d245a931e4ed411e", + "sha256:72ef78d0f8337eb35393b8893ebfbfbeb340f2d2ae47e0d2d78130e34b0dd8b9" ], "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.0.15" + "version": "==1.3.7" }, "greenlet": { "hashes": [ - "sha256:04e1849c88aa56584d4a0a6e36af5ec7cc37993fdc1fda72b56aa1394a92ded3", - "sha256:05e72db813c28906cdc59bd0da7c325d9b82aa0b0543014059c34c8c4ad20e16", - "sha256:07e6d88242e09b399682b39f8dfa1e7e6eca66b305de1ff74ed9eb1a7d8e539c", - "sha256:090126004c8ab9cd0787e2acf63d79e80ab41a18f57d6448225bbfcba475034f", - "sha256:1796f2c283faab2b71c67e9b9aefb3f201fdfbee5cb55001f5ffce9125f63a45", - "sha256:2f89d74b4f423e756a018832cd7a0a571e0a31b9ca59323b77ce5f15a437629b", - "sha256:34e6675167a238bede724ee60fe0550709e95adaff6a36bcc97006c365290384", - "sha256:3e594015a2349ec6dcceda9aca29da8dc89e85b56825b7d1f138a3f6bb79dd4c", - "sha256:3f8fc59bc5d64fa41f58b0029794f474223693fd00016b29f4e176b3ee2cfd9f", - "sha256:3fc6a447735749d651d8919da49aab03c434a300e9f0af1c886d560405840fd1", - "sha256:40abb7fec4f6294225d2b5464bb6d9552050ded14a7516588d6f010e7e366dcc", - "sha256:44556302c0ab376e37939fd0058e1f0db2e769580d340fb03b01678d1ff25f68", - "sha256:476ba9435afaead4382fbab8f1882f75e3fb2285c35c9285abb3dd30237f9142", - "sha256:4870b018ca685ff573edd56b93f00a122f279640732bb52ce3a62b73ee5c4a92", - "sha256:4adaf53ace289ced90797d92d767d37e7cdc29f13bd3830c3f0a561277a4ae83", - "sha256:4eae94de9924bbb4d24960185363e614b1b62ff797c23dc3c8a7c75bbb8d187e", - "sha256:5317701c7ce167205c0569c10abc4bd01c7f4cf93f642c39f2ce975fa9b78a3c", - "sha256:5c3b735ccf8fc8048664ee415f8af5a3a018cc92010a0d7195395059b4b39b7d", - "sha256:5cde7ee190196cbdc078511f4df0be367af85636b84d8be32230f4871b960687", - "sha256:655ab836324a473d4cd8cf231a2d6f283ed71ed77037679da554e38e606a7117", - "sha256:6ce9d0784c3c79f3e5c5c9c9517bbb6c7e8aa12372a5ea95197b8a99402aa0e6", - "sha256:6e0696525500bc8aa12eae654095d2260db4dc95d5c35af2b486eae1bf914ccd", - "sha256:75ff270fd05125dce3303e9216ccddc541a9e072d4fc764a9276d44dee87242b", - "sha256:8039f5fe8030c43cd1732d9a234fdcbf4916fcc32e21745ca62e75023e4d4649", - "sha256:84488516639c3c5e5c0e52f311fff94ebc45b56788c2a3bfe9cf8e75670f4de3", - "sha256:84782c80a433d87530ae3f4b9ed58d4a57317d9918dfcc6a59115fa2d8731f2c", - "sha256:8ddb38fb6ad96c2ef7468ff73ba5c6876b63b664eebb2c919c224261ae5e8378", - "sha256:98b491976ed656be9445b79bc57ed21decf08a01aaaf5fdabf07c98c108111f6", - "sha256:990e0f5e64bcbc6bdbd03774ecb72496224d13b664aa03afd1f9b171a3269272", - "sha256:9b02e6039eafd75e029d8c58b7b1f3e450ca563ef1fe21c7e3e40b9936c8d03e", - "sha256:a11b6199a0b9dc868990456a2667167d0ba096c5224f6258e452bfbe5a9742c5", - "sha256:a414f8e14aa7bacfe1578f17c11d977e637d25383b6210587c29210af995ef04", - "sha256:a91ee268f059583176c2c8b012a9fce7e49ca6b333a12bbc2dd01fc1a9783885", - "sha256:ac991947ca6533ada4ce7095f0e28fe25d5b2f3266ad5b983ed4201e61596acf", - "sha256:b050dbb96216db273b56f0e5960959c2b4cb679fe1e58a0c3906fa0a60c00662", - "sha256:b97a807437b81f90f85022a9dcfd527deea38368a3979ccb49d93c9198b2c722", - "sha256:bad269e442f1b7ffa3fa8820b3c3aa66f02a9f9455b5ba2db5a6f9eea96f56de", - "sha256:bf3725d79b1ceb19e83fb1aed44095518c0fcff88fba06a76c0891cfd1f36837", - "sha256:c0f22774cd8294078bdf7392ac73cf00bfa1e5e0ed644bd064fdabc5f2a2f481", - "sha256:c1862f9f1031b1dee3ff00f1027fcd098ffc82120f43041fe67804b464bbd8a7", - "sha256:c8d4ed48eed7414ccb2aaaecbc733ed2a84c299714eae3f0f48db085342d5629", - "sha256:cf31e894dabb077a35bbe6963285d4515a387ff657bd25b0530c7168e48f167f", - "sha256:d15cb6f8706678dc47fb4e4f8b339937b04eda48a0af1cca95f180db552e7663", - "sha256:dfcb5a4056e161307d103bc013478892cfd919f1262c2bb8703220adcb986362", - "sha256:e02780da03f84a671bb4205c5968c120f18df081236d7b5462b380fd4f0b497b", - "sha256:e2002a59453858c7f3404690ae80f10c924a39f45f6095f18a985a1234c37334", - "sha256:e22a82d2b416d9227a500c6860cf13e74060cf10e7daf6695cbf4e6a94e0eee4", - "sha256:e41f72f225192d5d4df81dad2974a8943b0f2d664a2a5cfccdf5a01506f5523c", - "sha256:f253dad38605486a4590f9368ecbace95865fea0f2b66615d121ac91fd1a1563", - "sha256:fddfb31aa2ac550b938d952bca8a87f1db0f8dc930ffa14ce05b5c08d27e7fd1" - ], - "markers": "python_version >= '3' and (platform_machine == 'arch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", - "version": "==1.1.1" + "sha256:0118817c9341ef2b0f75f5af79ac377e4da6ff637e5ee4ac91802c0e379dadb4", + "sha256:048d2bed76c2aa6de7af500ae0ea51dd2267aec0e0f2a436981159053d0bc7cc", + "sha256:07c58e169bbe1e87b8bbf15a5c1b779a7616df9fd3e61cadc9d691740015b4f8", + "sha256:095a980288fe05adf3d002fbb180c99bdcf0f930e220aa66fcd56e7914a38202", + "sha256:0b181e9aa6cb2f5ec0cacc8cee6e5a3093416c841ba32c185c30c160487f0380", + "sha256:1626185d938d7381631e48e6f7713e8d4b964be246073e1a1d15c2f061ac9f08", + "sha256:184416e481295832350a4bf731ba619a92f5689bf5d0fa4341e98b98b1265bd7", + "sha256:1dd51d2650e70c6c4af37f454737bf4a11e568945b27f74b471e8e2a9fd21268", + "sha256:1ec2779774d8e42ed0440cf8bc55540175187e8e934f2be25199bf4ed948cd9e", + "sha256:2cf45e339cabea16c07586306a31cfcc5a3b5e1626d365714d283732afed6809", + "sha256:2fb0aa7f6996879551fd67461d5d3ab0c3c0245da98be90c89fcb7a18d437403", + "sha256:44b4817c34c9272c65550b788913620f1fdc80362b209bc9d7dd2f40d8793080", + "sha256:466ce0928e33421ee84ae04c4ac6f253a3a3e6b8d600a79bd43fd4403e0a7a76", + "sha256:4f166b4aca8d7d489e82d74627a7069ab34211ef5ebb57c300ec4b9337b60fc0", + "sha256:510c3b15587afce9800198b4b142202b323bf4b4b5f9d6c79cb9a35e5e3c30d2", + "sha256:5b756e6730ea59b2745072e28ad27f4c837084688e6a6b3633c8b1e509e6ae0e", + "sha256:5fbe1ab72b998ca77ceabbae63a9b2e2dc2d963f4299b9b278252ddba142d3f1", + "sha256:6200a11f003ec26815f7e3d2ded01b43a3810be3528dd760d2f1fa777490c3cd", + "sha256:65ad1a7a463a2a6f863661329a944a5802c7129f7ad33583dcc11069c17e622c", + "sha256:694ffa7144fa5cc526c8f4512665003a39fa09ef00d19bbca5c8d3406db72fbe", + "sha256:6f5d4b2280ceea76c55c893827961ed0a6eadd5a584a7c4e6e6dd7bc10dfdd96", + "sha256:7532a46505470be30cbf1dbadb20379fb481244f1ca54207d7df3bf0bbab6a20", + "sha256:76a53bfa10b367ee734b95988bd82a9a5f0038a25030f9f23bbbc005010ca600", + "sha256:77e41db75f9958f2083e03e9dd39da12247b3430c92267df3af77c83d8ff9eed", + "sha256:7a43bbfa9b6cfdfaeefbd91038dde65ea2c421dc387ed171613df340650874f2", + "sha256:7b41d19c0cfe5c259fe6c539fd75051cd39a5d33d05482f885faf43f7f5e7d26", + "sha256:7c5227963409551ae4a6938beb70d56bf1918c554a287d3da6853526212fbe0a", + "sha256:870a48007872d12e95a996fca3c03a64290d3ea2e61076aa35d3b253cf34cd32", + "sha256:88b04e12c9b041a1e0bcb886fec709c488192638a9a7a3677513ac6ba81d8e79", + "sha256:8c287ae7ac921dfde88b1c125bd9590b7ec3c900c2d3db5197f1286e144e712b", + "sha256:903fa5716b8fbb21019268b44f73f3748c41d1a30d71b4a49c84b642c2fed5fa", + "sha256:9537e4baf0db67f382eb29255a03154fcd4984638303ff9baaa738b10371fa57", + "sha256:9951dcbd37850da32b2cb6e391f621c1ee456191c6ae5528af4a34afe357c30e", + "sha256:9b2f7d0408ddeb8ea1fd43d3db79a8cefaccadd2a812f021333b338ed6b10aba", + "sha256:9c88e134d51d5e82315a7c32b914a58751b7353eb5268dbd02eabf020b4c4700", + "sha256:9fae214f6c43cd47f7bef98c56919b9222481e833be2915f6857a1e9e8a15318", + "sha256:a3a669f11289a8995d24fbfc0e63f8289dd03c9aaa0cc8f1eab31d18ca61a382", + "sha256:aa741c1a8a8cc25eb3a3a01a62bdb5095a773d8c6a86470bde7f607a447e7905", + "sha256:b0877a9a2129a2c56a2eae2da016743db7d9d6a05d5e1c198f1b7808c602a30e", + "sha256:bcb6c6dd1d6be6d38d6db283747d07fda089ff8c559a835236560a4410340455", + "sha256:caff52cb5cd7626872d9696aee5b794abe172804beb7db52eed1fd5824b63910", + "sha256:cbc1eb55342cbac8f7ec159088d54e2cfdd5ddf61c87b8bbe682d113789331b2", + "sha256:cd16a89efe3a003029c87ff19e9fba635864e064da646bc749fc1908a4af18f3", + "sha256:ce5b64dfe8d0cca407d88b0ee619d80d4215a2612c1af8c98a92180e7109f4b5", + "sha256:d58a5a71c4c37354f9e0c24c9c8321f0185f6945ef027460b809f4bb474bfe41", + "sha256:db41f3845eb579b544c962864cce2c2a0257fe30f0f1e18e51b1e8cbb4e0ac6d", + "sha256:db5b25265010a1b3dca6a174a443a0ed4c4ab12d5e2883a11c97d6e6d59b12f9", + "sha256:dd0404d154084a371e6d2bafc787201612a1359c2dee688ae334f9118aa0bf47", + "sha256:de431765bd5fe62119e0bc6bc6e7b17ac53017ae1782acf88fcf6b7eae475a49", + "sha256:df02fdec0c533301497acb0bc0f27f479a3a63dcdc3a099ae33a902857f07477", + "sha256:e8533f5111704d75de3139bf0b8136d3a6c1642c55c067866fa0a51c2155ee33", + "sha256:f2f908239b7098799b8845e5936c2ccb91d8c2323be02e82f8dcb4a80dcf4a25", + "sha256:f8bfd36f368efe0ab2a6aa3db7f14598aac454b06849fb633b762ddbede1db90", + "sha256:ffe73f9e7aea404722058405ff24041e59d31ca23d1da0895af48050a07b6932" + ], + "markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))", + "version": "==1.1.3" }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3.5'", - "version": "==3.2" + "version": "==3.3" }, "importlib-metadata": { "hashes": [ - "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", - "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" + "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670", + "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23" ], "markers": "python_version < '3.8'", - "version": "==4.8.1" + "version": "==4.12.0" }, "multidict": { "hashes": [ - "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a", - "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93", - "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632", - "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656", - "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79", - "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7", - "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d", - "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5", - "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224", - "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26", - "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea", - "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348", - "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6", - "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76", - "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1", - "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f", - "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952", - "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a", - "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37", - "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9", - "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359", - "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8", - "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da", - "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3", - "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d", - "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf", - "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841", - "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d", - "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93", - "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f", - "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647", - "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635", - "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456", - "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda", - "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5", - "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281", - "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80" - ], - "markers": "python_version >= '3.6'", - "version": "==5.1.0" + "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60", + "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c", + "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672", + "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51", + "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032", + "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2", + "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b", + "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80", + "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88", + "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a", + "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d", + "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389", + "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c", + "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9", + "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c", + "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516", + "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b", + "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43", + "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee", + "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227", + "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d", + "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae", + "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7", + "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4", + "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9", + "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f", + "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013", + "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9", + "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e", + "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693", + "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a", + "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15", + "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb", + "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96", + "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87", + "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376", + "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658", + "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0", + "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071", + "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360", + "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc", + "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3", + "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba", + "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8", + "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9", + "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2", + "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3", + "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68", + "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8", + "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d", + "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49", + "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608", + "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57", + "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86", + "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20", + "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293", + "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849", + "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937", + "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d" + ], + "markers": "python_version >= '3.7'", + "version": "==6.0.2" }, "pamqp": { "hashes": [ "sha256:2f81b5c186f668a67f165193925b6bfd83db4363a6222f599517f29ecee60b02", "sha256:5cd0f5a85e89f20d5f8e19285a1507788031cfca4a9ea6f067e3cf18f5e294e8" ], + "index": "pypi", "version": "==2.3.0" }, "prometheus-client": { "hashes": [ - "sha256:3a8baade6cb80bcfe43297e33e7623f3118d660d41387593758e2fb1ea173a86", - "sha256:b014bc76815eb1399da8ce5fc84b7717a3e63652b0c0f8804092c9363acab1b2" + "sha256:522fded625282822a89e2773452f42df14b5a8e84a86433e3f8a189c1d54dc01", + "sha256:5459c427624961076277fdc6dc50540e2bacb98eebde99886e59ec55ed92093a" ], "index": "pypi", - "version": "==0.11.0" + "version": "==0.14.1" }, "pymysql": { "hashes": [ - "sha256:3943fbbbc1e902f41daf7f9165519f140c4451c179380677e6a848587042561a", - "sha256:d8c059dcd81dedb85a9f034d5e22dcb4442c0b201908bede99e306d65ea7c8e7" + "sha256:41fc3a0c5013d5f039639442321185532e3e2c8924687abe6537de157d403641", + "sha256:816927a350f38d56072aeca5dfb10221fe1dc653745853d30a216637f5d7ad36" ], - "version": "==0.9.3" + "markers": "python_version >= '3.6'", + "version": "==1.0.2" }, "python-dateutil": { "hashes": [ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, + "pytz-deprecation-shim": { + "hashes": [ + "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6", + "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==0.1.0.post0" + }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "sqlalchemy": { "hashes": [ - "sha256:0865579cfae8406ba2eae7ff84ef1dc85190121706e0305939c98c6128282efb", - "sha256:087eb1c405279d076bfc54d472bda31f72baef7f308cfce93daa199c3e9c344c", - "sha256:0a9622a7d0a121f8cc8a6c202fe615d14002c8793f0c570ffee0e4ea3ce987a4", - "sha256:112eceaf51b38acd7b3287ccc0100e8ffe48291e65c400cf8b2036f08894b4dd", - "sha256:1c663510cd54fbb5fd20c98d00b013eaf2ec7552064811032e1fcfa3e980b0a4", - "sha256:2a3ab0813fe2df8fba5ce4b969f81f1895ae71d8afaf4d187e6a0da6b320a51f", - "sha256:3639e2dd1d592e4f4e2bcc857601699d3d9c6b162b72435bdd2da3cedcb8abd6", - "sha256:37f7ec52d422369d3d21f5ca5c10ff18da0c75a133acb6a2e78c2b059eb216cf", - "sha256:41b1515eb462565e61afed2d5e68643ce0dcb14d09f56a1e7b06144f20f41b60", - "sha256:5368ff1d334ee0956f6459f3ac7ac08da87ab00bc7ccda096d498bf68b49d1c1", - "sha256:541e82e35ea9d9b57a55e0f1b639b508a5d8b3c167896bf205b3b3b7d9704329", - "sha256:59536e16442b41adeda2bd0a22b49cd376c265b22a74fb65c4f389dcf54a11b5", - "sha256:599f3c2a16caa4a2ad1971d1f3d6b5a92bb861f70e81ed0088311c73752f2598", - "sha256:63a442eea6dc801044096ad209a46117ccf63ade4fb05a81e4a5354719e0d77f", - "sha256:738f3a8dcb2cd2c359a1ea7c6b8dab8d818e2dfd9441128fe687045f4c476c59", - "sha256:7c4335e19a6abc510a4755c628adb1db4b775835ad84e022fead2153fd0839f5", - "sha256:7d7d646c179ccd58b08110eade9e69399981bb4c9696123e34a159c9721e6449", - "sha256:7e18d6da1d0a8093bc1f2f3fa25cfbb0db8f2022e5e0cc83f39056b7b259ee20", - "sha256:91ee87314037d0fd622edc0aab88867138acfe26e1697000a3bde571aaf9515d", - "sha256:9bb3346868f345d6ed97ddeb9ba5c82699173d62f3400b960f455a0e238165ef", - "sha256:a5252f9c564ffa8cfd02b6b48eba4aec166546a71e149ea38f1079229976e5fa", - "sha256:b1e6945b29c630b4696f7b3e43210c3d6ca35709ee0a0ac2251c6ed5891b8dda", - "sha256:b7cfcefe265a28ac43eedc7f0c4c657511c5607aa4b50d1e5b039b29f04a780f", - "sha256:c7d572b0771b7866d21413902080eb61334dabb9831d64caf0cf68cb07ba9370", - "sha256:c9da7bf322493158db09127f7c5e80ebda0ed2296b036fade424c5a45c44f59c", - "sha256:ca82199171dd6016381ea5b6fa22cd838389c2e03facd448bd9e15be2bb27a8d", - "sha256:cd6b08acc9f07d60eb866d30eb48db1f39cc04863407a5ff04736961fd1f2e52", - "sha256:d34650edaa2a9eccd86a08fb5a303144b0e58898d16f684617207d9ff0e6e447", - "sha256:eb4681927c1beeaa3c8d4d8eb3541d427eef5d54410d02924ecdc651e6688304", - "sha256:fb7b2eb3f02daa88a6c2dcd665511313cf5b51a0e18e8c4d95ce36bb09463615" + "sha256:0002e829142b2af00b4eaa26c51728f3ea68235f232a2e72a9508a3116bd6ed0", + "sha256:0005bd73026cd239fc1e8ccdf54db58b6193be9a02b3f0c5983808f84862c767", + "sha256:0292f70d1797e3c54e862e6f30ae474014648bc9c723e14a2fda730adb0a9791", + "sha256:036d8472356e1d5f096c5e0e1a7e0f9182140ada3602f8fff6b7329e9e7cfbcd", + "sha256:05f0de3a1dc3810a776275763764bb0015a02ae0f698a794646ebc5fb06fad33", + "sha256:0990932f7cca97fece8017414f57fdd80db506a045869d7ddf2dda1d7cf69ecc", + "sha256:13e397a9371ecd25573a7b90bd037db604331cf403f5318038c46ee44908c44d", + "sha256:14576238a5f89bcf504c5f0a388d0ca78df61fb42cb2af0efe239dc965d4f5c9", + "sha256:199a73c31ac8ea59937cc0bf3dfc04392e81afe2ec8a74f26f489d268867846c", + "sha256:2082a2d2fca363a3ce21cfa3d068c5a1ce4bf720cf6497fb3a9fc643a8ee4ddd", + "sha256:22ff16cedab5b16a0db79f1bc99e46a6ddececb60c396562e50aab58ddb2871c", + "sha256:2307495d9e0ea00d0c726be97a5b96615035854972cc538f6e7eaed23a35886c", + "sha256:2ad2b727fc41c7f8757098903f85fafb4bf587ca6605f82d9bf5604bd9c7cded", + "sha256:2d6495f84c4fd11584f34e62f9feec81bf373787b3942270487074e35cbe5330", + "sha256:361f6b5e3f659e3c56ea3518cf85fbdae1b9e788ade0219a67eeaaea8a4e4d2a", + "sha256:3e2ef592ac3693c65210f8b53d0edcf9f4405925adcfc031ff495e8d18169682", + "sha256:4676d51c9f6f6226ae8f26dc83ec291c088fe7633269757d333978df78d931ab", + "sha256:4ba7e122510bbc07258dc42be6ed45997efdf38129bde3e3f12649be70683546", + "sha256:5102fb9ee2c258a2218281adcb3e1918b793c51d6c2b4666ce38c35101bb940e", + "sha256:5323252be2bd261e0aa3f33cb3a64c45d76829989fa3ce90652838397d84197d", + "sha256:58bb65b3274b0c8a02cea9f91d6f44d0da79abc993b33bdedbfec98c8440175a", + "sha256:59bdc291165b6119fc6cdbc287c36f7f2859e6051dd923bdf47b4c55fd2f8bd0", + "sha256:5facb7fd6fa8a7353bbe88b95695e555338fb038ad19ceb29c82d94f62775a05", + "sha256:639e1ae8d48b3c86ffe59c0daa9a02e2bfe17ca3d2b41611b30a0073937d4497", + "sha256:8eb8897367a21b578b26f5713833836f886817ee2ffba1177d446fa3f77e67c8", + "sha256:90484a2b00baedad361402c257895b13faa3f01780f18f4a104a2f5c413e4536", + "sha256:9c56e19780cd1344fcd362fd6265a15f48aa8d365996a37fab1495cae8fcd97d", + "sha256:b67fc780cfe2b306180e56daaa411dd3186bf979d50a6a7c2a5b5036575cbdbb", + "sha256:c0dcf127bb99458a9d211e6e1f0f3edb96c874dd12f2503d4d8e4f1fd103790b", + "sha256:c23d64a0b28fc78c96289ffbd0d9d1abd48d267269b27f2d34e430ea73ce4b26", + "sha256:ccfd238f766a5bb5ee5545a62dd03f316ac67966a6a658efb63eeff8158a4bbf", + "sha256:cd767cf5d7252b1c88fcfb58426a32d7bd14a7e4942497e15b68ff5d822b41ad", + "sha256:ce8feaa52c1640de9541eeaaa8b5fb632d9d66249c947bb0d89dd01f87c7c288", + "sha256:d2e054aed4645f9b755db85bc69fc4ed2c9020c19c8027976f66576b906a74f1", + "sha256:e16c2be5cb19e2c08da7bd3a87fed2a0d4e90065ee553a940c4fc1a0fb1ab72b", + "sha256:e4b12e3d88a8fffd0b4ca559f6d4957ed91bd4c0613a4e13846ab8729dc5c251", + "sha256:e570cfc40a29d6ad46c9aeaddbdcee687880940a3a327f2c668dd0e4ef0a441d", + "sha256:eb30cf008850c0a26b72bd1b9be6730830165ce049d239cfdccd906f2685f892", + "sha256:f37fa70d95658763254941ddd30ecb23fc4ec0c5a788a7c21034fc2305dab7cc", + "sha256:f5ebeeec5c14533221eb30bad716bc1fd32f509196318fb9caa7002c4a364e4c", + "sha256:f5fa526d027d804b1f85cdda1eb091f70bde6fb7d87892f6dd5a48925bc88898" ], "index": "pypi", - "version": "==1.4.24" + "version": "==1.4.41" }, "sqlparse": { "hashes": [ @@ -277,10 +324,12 @@ }, "tabulate": { "hashes": [ - "sha256:d7c013fe7abbc5e491394e10fa845f8f32fe54f8dc60c6622c6cf482d25d47e4", - "sha256:eb1d13f25760052e8931f2ef80aaf6045a6cceb47514db8beab24cded16f13a7" + "sha256:0ba055423dbaa164b9e456abe7920c5e8ed33fcc16f6d1b2f2d152c8e1e8b4fc", + "sha256:436f1c768b424654fce8597290d2764def1eea6a77cfa5c33be00b1bc0f4f63d", + "sha256:6c57f3f3dd7ac2782770155f3adb2db0b1a269637e42f27599925e64b114f519" ], - "version": "==0.8.9" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.8.10" }, "trueskill": { "hashes": [ @@ -291,63 +340,92 @@ }, "typing-extensions": { "hashes": [ - "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", - "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", - "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" + "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", + "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" ], - "markers": "python_version < '3.8' and python_version < '3.8'", - "version": "==3.10.0.2" + "markers": "python_version < '3.8'", + "version": "==4.3.0" }, - "tzlocal": { + "tzdata": { "hashes": [ - "sha256:c736f2540713deb5938d789ca7c3fc25391e9a20803f05b60ec64987cf086559", - "sha256:f4e6e36db50499e0d92f79b67361041f048e2609d166e93456b50746dc4aef12" + "sha256:21f4f0d7241572efa7f7a4fdabb052e61b55dc48274e6842697ccdf5253e5451", + "sha256:c3119520447d68ef3eb8187a55a4f44fa455f30eb1b4238fa5691ba094f2b05b" ], "markers": "python_version >= '3.6'", - "version": "==3.0" + "version": "==2022.2" }, - "yarl": { + "tzlocal": { "hashes": [ - "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e", - "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434", - "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366", - "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3", - "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec", - "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959", - "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e", - "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c", - "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6", - "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a", - "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6", - "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424", - "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e", - "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f", - "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50", - "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2", - "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc", - "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4", - "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970", - "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10", - "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0", - "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406", - "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896", - "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643", - "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721", - "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478", - "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724", - "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e", - "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8", - "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96", - "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25", - "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76", - "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2", - "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2", - "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c", - "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a", - "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71" + "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745", + "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7" ], "markers": "python_version >= '3.6'", - "version": "==1.6.3" + "version": "==4.2" + }, + "yarl": { + "hashes": [ + "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb", + "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3", + "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035", + "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453", + "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d", + "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a", + "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231", + "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f", + "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae", + "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b", + "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3", + "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507", + "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd", + "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae", + "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe", + "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c", + "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4", + "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64", + "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357", + "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54", + "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461", + "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4", + "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497", + "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0", + "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1", + "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957", + "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350", + "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780", + "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843", + "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548", + "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6", + "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40", + "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee", + "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b", + "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6", + "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0", + "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e", + "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880", + "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc", + "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e", + "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead", + "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28", + "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf", + "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd", + "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae", + "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0", + "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0", + "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae", + "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda", + "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546", + "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802", + "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be", + "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07", + "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936", + "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272", + "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc", + "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a", + "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28", + "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.8.1" }, "yoyo-migrations": { "hashes": [ @@ -359,11 +437,11 @@ }, "zipp": { "hashes": [ - "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3", - "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4" + "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2", + "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009" ], - "markers": "python_version >= '3.6'", - "version": "==3.5.0" + "markers": "python_version >= '3.7'", + "version": "==3.8.1" } }, "develop": { @@ -377,100 +455,110 @@ }, "attrs": { "hashes": [ - "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", - "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" + "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", + "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==21.2.0" + "markers": "python_version >= '3.5'", + "version": "==22.1.0" }, "certifi": { "hashes": [ - "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", - "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + "sha256:43dadad18a7f168740e66944e4fa82c6611848ff9056ad910f8f7a3e46ab89e0", + "sha256:cffdcd380919da6137f76633531a5817e3a9f268575c128249fb637e4f9e73fb" ], - "version": "==2021.5.30" + "markers": "python_version >= '3.6'", + "version": "==2022.6.15.1" }, "charset-normalizer": { "hashes": [ - "sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6", - "sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f" + "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", + "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" ], - "markers": "python_version >= '3'", - "version": "==2.0.6" + "markers": "python_version >= '3.6'", + "version": "==2.1.1" }, "coverage": { - "hashes": [ - "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c", - "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6", - "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45", - "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a", - "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03", - "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529", - "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a", - "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a", - "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2", - "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6", - "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759", - "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53", - "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a", - "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4", - "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff", - "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502", - "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793", - "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb", - "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905", - "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821", - "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b", - "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81", - "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0", - "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b", - "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3", - "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184", - "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701", - "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a", - "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82", - "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638", - "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5", - "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083", - "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6", - "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90", - "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465", - "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a", - "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3", - "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e", - "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066", - "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf", - "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b", - "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae", - "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669", - "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873", - "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b", - "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6", - "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb", - "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160", - "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", - "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079", - "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d", - "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==5.5" + "extras": [ + "toml" + ], + "hashes": [ + "sha256:01778769097dbd705a24e221f42be885c544bb91251747a8a3efdec6eb4788f2", + "sha256:08002f9251f51afdcc5e3adf5d5d66bb490ae893d9e21359b085f0e03390a820", + "sha256:1238b08f3576201ebf41f7c20bf59baa0d05da941b123c6656e42cdb668e9827", + "sha256:14a32ec68d721c3d714d9b105c7acf8e0f8a4f4734c811eda75ff3718570b5e3", + "sha256:15e38d853ee224e92ccc9a851457fb1e1f12d7a5df5ae44544ce7863691c7a0d", + "sha256:354df19fefd03b9a13132fa6643527ef7905712109d9c1c1903f2133d3a4e145", + "sha256:35ef1f8d8a7a275aa7410d2f2c60fa6443f4a64fae9be671ec0696a68525b875", + "sha256:4179502f210ebed3ccfe2f78bf8e2d59e50b297b598b100d6c6e3341053066a2", + "sha256:42c499c14efd858b98c4e03595bf914089b98400d30789511577aa44607a1b74", + "sha256:4b7101938584d67e6f45f0015b60e24a95bf8dea19836b1709a80342e01b472f", + "sha256:564cd0f5b5470094df06fab676c6d77547abfdcb09b6c29c8a97c41ad03b103c", + "sha256:5f444627b3664b80d078c05fe6a850dd711beeb90d26731f11d492dcbadb6973", + "sha256:6113e4df2fa73b80f77663445be6d567913fb3b82a86ceb64e44ae0e4b695de1", + "sha256:61b993f3998ee384935ee423c3d40894e93277f12482f6e777642a0141f55782", + "sha256:66e6df3ac4659a435677d8cd40e8eb1ac7219345d27c41145991ee9bf4b806a0", + "sha256:67f9346aeebea54e845d29b487eb38ec95f2ecf3558a3cffb26ee3f0dcc3e760", + "sha256:6913dddee2deff8ab2512639c5168c3e80b3ebb0f818fed22048ee46f735351a", + "sha256:6a864733b22d3081749450466ac80698fe39c91cb6849b2ef8752fd7482011f3", + "sha256:7026f5afe0d1a933685d8f2169d7c2d2e624f6255fb584ca99ccca8c0e966fd7", + "sha256:783bc7c4ee524039ca13b6d9b4186a67f8e63d91342c713e88c1865a38d0892a", + "sha256:7a98d6bf6d4ca5c07a600c7b4e0c5350cd483c85c736c522b786be90ea5bac4f", + "sha256:8d032bfc562a52318ae05047a6eb801ff31ccee172dc0d2504614e911d8fa83e", + "sha256:98c0b9e9b572893cdb0a00e66cf961a238f8d870d4e1dc8e679eb8bdc2eb1b86", + "sha256:9c7b9b498eb0c0d48b4c2abc0e10c2d78912203f972e0e63e3c9dc21f15abdaa", + "sha256:9cc4f107009bca5a81caef2fca843dbec4215c05e917a59dec0c8db5cff1d2aa", + "sha256:9d6e1f3185cbfd3d91ac77ea065d85d5215d3dfa45b191d14ddfcd952fa53796", + "sha256:a095aa0a996ea08b10580908e88fbaf81ecf798e923bbe64fb98d1807db3d68a", + "sha256:a3b2752de32c455f2521a51bd3ffb53c5b3ae92736afde67ce83477f5c1dd928", + "sha256:ab066f5ab67059d1f1000b5e1aa8bbd75b6ed1fc0014559aea41a9eb66fc2ce0", + "sha256:c1328d0c2f194ffda30a45f11058c02410e679456276bfa0bbe0b0ee87225fac", + "sha256:c35cca192ba700979d20ac43024a82b9b32a60da2f983bec6c0f5b84aead635c", + "sha256:cbbb0e4cd8ddcd5ef47641cfac97d8473ab6b132dd9a46bacb18872828031685", + "sha256:cdbb0d89923c80dbd435b9cf8bba0ff55585a3cdb28cbec65f376c041472c60d", + "sha256:cf2afe83a53f77aec067033199797832617890e15bed42f4a1a93ea24794ae3e", + "sha256:d5dd4b8e9cd0deb60e6fcc7b0647cbc1da6c33b9e786f9c79721fd303994832f", + "sha256:dfa0b97eb904255e2ab24166071b27408f1f69c8fbda58e9c0972804851e0558", + "sha256:e16c45b726acb780e1e6f88b286d3c10b3914ab03438f32117c4aa52d7f30d58", + "sha256:e1fabd473566fce2cf18ea41171d92814e4ef1495e04471786cbc943b89a3781", + "sha256:e3d3c4cc38b2882f9a15bafd30aec079582b819bec1b8afdbde8f7797008108a", + "sha256:e431e305a1f3126477abe9a184624a85308da8edf8486a863601d58419d26ffa", + "sha256:e7b4da9bafad21ea45a714d3ea6f3e1679099e420c8741c74905b92ee9bfa7cc", + "sha256:ee2b2fb6eb4ace35805f434e0f6409444e1466a47f620d1d5763a22600f0f892", + "sha256:ee6ae6bbcac0786807295e9687169fba80cb0617852b2fa118a99667e8e6815d", + "sha256:ef6f44409ab02e202b31a05dd6666797f9de2aa2b4b3534e9d450e42dea5e817", + "sha256:f67cf9f406cf0d2f08a3515ce2db5b82625a7257f88aad87904674def6ddaec1", + "sha256:f855b39e4f75abd0dfbcf74a82e84ae3fc260d523fcb3532786bcbbcb158322c", + "sha256:fc600f6ec19b273da1d85817eda339fb46ce9eef3e89f220055d8696e0a06908", + "sha256:fcbe3d9a53e013f8ab88734d7e517eb2cd06b7e689bedf22c0eb68db5e4a0a19", + "sha256:fde17bc42e0716c94bf19d92e4c9f5a00c5feb401f5bc01101fdf2a8b7cacf60", + "sha256:ff934ced84054b9018665ca3967fc48e1ac99e811f6cc99ea65978e1d384454b" + ], + "markers": "python_version >= '3.7'", + "version": "==6.4.4" + }, + "freezegun": { + "hashes": [ + "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446", + "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f" + ], + "index": "pypi", + "version": "==1.2.2" }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3.5'", - "version": "==3.2" + "version": "==3.3" }, "importlib-metadata": { "hashes": [ - "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", - "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" + "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670", + "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23" ], "markers": "python_version < '3.8'", - "version": "==4.8.1" + "version": "==4.12.0" }, "iniconfig": { "hashes": [ @@ -489,11 +577,11 @@ }, "packaging": { "hashes": [ - "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", - "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", + "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" ], "markers": "python_version >= '3.6'", - "version": "==21.0" + "version": "==21.3" }, "pluggy": { "hashes": [ @@ -505,27 +593,27 @@ }, "py": { "hashes": [ - "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", - "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" + "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", + "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.10.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.11.0" }, "pyparsing": { "hashes": [ - "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", - "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", + "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.4.7" + "markers": "python_full_version >= '3.6.8'", + "version": "==3.0.9" }, "pytest": { "hashes": [ - "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89", - "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134" + "sha256:1377bda3466d70b55e3f5cecfa55bb7cfcf219c7964629b967c37cf0bda818b7", + "sha256:4f365fec2dff9c1162f834d9f18af1ba13062db0c708bf7b946f8a5c76180c39" ], "index": "pypi", - "version": "==6.2.5" + "version": "==7.1.3" }, "pytest-asyncio": { "hashes": [ @@ -536,19 +624,19 @@ }, "pytest-cov": { "hashes": [ - "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a", - "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7" + "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6", + "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470" ], "index": "pypi", - "version": "==2.12.1" + "version": "==3.0.0" }, "pytest-mock": { "hashes": [ - "sha256:30c2f2cc9759e76eee674b81ea28c9f0b94f8f0445a1b87762cadf774f0df7e3", - "sha256:40217a058c52a63f1042f0784f62009e976ba824c418cced42e88d5f40ab0e62" + "sha256:77f03f4554392558700295e05aed0b1096a20d4a60a4f3ddcde58b0c31c8fca2", + "sha256:8a9e226d6c0ef09fcf20c94eb3405c388af438a90f3e39687f84166da82d5948" ], "index": "pypi", - "version": "==3.6.1" + "version": "==3.8.2" }, "python-coveralls": { "hashes": [ @@ -558,55 +646,67 @@ "index": "pypi", "version": "==2.9.3" }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" + }, "pyyaml": { "hashes": [ - "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", - "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", - "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", - "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", - "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", - "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", - "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", - "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", - "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", - "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", - "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", - "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", - "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", - "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", - "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", - "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", - "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", - "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", - "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", - "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", - "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", - "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", - "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", - "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", - "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", - "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", - "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", - "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", - "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==5.4.1" + "markers": "python_version >= '3.6'", + "version": "==6.0" }, "requests": { "hashes": [ - "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24", - "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7" + "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", + "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==2.26.0" + "markers": "python_version >= '3.7' and python_version < '4'", + "version": "==2.28.1" }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "toml": { @@ -614,41 +714,48 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.1" + }, "typing-extensions": { "hashes": [ - "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", - "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", - "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" + "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", + "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" ], - "markers": "python_version < '3.8' and python_version < '3.8'", - "version": "==3.10.0.2" + "markers": "python_version < '3.8'", + "version": "==4.3.0" }, "urllib3": { "hashes": [ - "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece", - "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844" + "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", + "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.7" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", + "version": "==1.26.12" }, "vulture": { "hashes": [ - "sha256:03d5a62bcbe9ceb9a9b0575f42d71a2d414070229f2e6f95fa6e7c71aaaed967", - "sha256:f39de5e6f1df1f70c3b50da54f1c8d494159e9ca3d01a9b89eac929600591703" + "sha256:2831694055eb2e36a09c3b7680934837102b9b6c0969206e3902d513612177c3", + "sha256:a7c7e7a23b11e78840fdd821509d05a6134aa9fd60418fe39d60b3026fe698d9" ], "index": "pypi", - "version": "==2.3" + "version": "==2.5" }, "zipp": { "hashes": [ - "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3", - "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4" + "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2", + "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009" ], - "markers": "python_version >= '3.6'", - "version": "==3.5.0" + "markers": "python_version >= '3.7'", + "version": "==3.8.1" } } } diff --git a/service.py b/service.py index ffd08e4..0a9bacc 100644 --- a/service.py +++ b/service.py @@ -7,6 +7,7 @@ from service import config, db from service.league_service import LeagueService from service.message_queue_service import MessageQueueService +from service.season_generator import SeasonGenerator async def main(): @@ -41,6 +42,9 @@ def signal_handler(sig: int, _frame): league_service = LeagueService(database, mq_service) await league_service.initialize() + season_generator = SeasonGenerator(database) + season_generator.initialize() + await done # Cleanup diff --git a/service/__init__.py b/service/__init__.py index fa1f428..03a5691 100644 --- a/service/__init__.py +++ b/service/__init__.py @@ -1,4 +1,4 @@ -__author__ = "Askaholic, Clemens Borys" +__author__ = "Askaholic, BlackYps, Clemens Borys" __contact__ = "admin@faforever.com" __license__ = "GPLv3" __copyright__ = "Copyright (c) 2020 " + __author__ diff --git a/service/config.py b/service/config.py index 3842364..2ef3977 100644 --- a/service/config.py +++ b/service/config.py @@ -21,6 +21,7 @@ MQ_VHOST = os.getenv("MQ_VHOST", "/faf-lobby") MQ_PREFETCH_COUNT = int(os.getenv("MQ_PREFETCH_COUNT", 300)) +SEASON_GENERATION_DAYS_BEFORE_SEASON_END = int(os.getenv("SEASON_GENERATION_DAYS_BEFORE_SEASON_END", 14)) EXCHANGE_NAME = os.getenv("EXCHANGE_NAME", "faf-rabbitmq") QUEUE_NAME = os.getenv("QUEUE_NAME", "faf-league-service") diff --git a/service/db/models.py b/service/db/models.py index 6d9744c..c39fe3f 100644 --- a/service/db/models.py +++ b/service/db/models.py @@ -30,6 +30,7 @@ Column("league_id", Integer, ForeignKey("league.id")), Column("leaderboard_id", Integer, ForeignKey("leaderboard.id")), Column("name_key", String), + Column("season_number", Integer), Column("placement_games", Integer), Column("placement_games_returning_player", Integer), Column("start_date", TIMESTAMP), @@ -42,6 +43,8 @@ Column("id", Integer, primary_key=True), Column("league_season_id", Integer, ForeignKey("league_season.id")), Column("division_index", Integer), + Column("description_key", String), + Column("name_key", String), ) league_season_division_subdivision = Table( diff --git a/service/generate_season.sql b/service/generate_season.sql new file mode 100644 index 0000000..0c9c754 --- /dev/null +++ b/service/generate_season.sql @@ -0,0 +1,113 @@ +SET time_zone='+00:00'; + +SELECT @Seasonnumber := MAX(season_number) FROM league_season; +SET @Seasonnumber = @Seasonnumber + 1; + +SET @start_date = ADDDATE(LAST_DAY(CURRENT_DATE), 1); +SET @end_date = LAST_DAY(ADD_MONTHS(CURRENT_DATE, 3)); + +-- season starts and ends at noon, so that all timezones see the same date in the client +INSERT INTO league_season (id, league_id, leaderboard_id, placement_games, season_number, name_key, start_date, end_date) VALUES + (@Seasonnumber * 3, 1, 2, 10, @Seasonnumber, "1v1_season", TIMESTAMP(@start_date, "12:00:00"), TIMESTAMP(@end_date, "12:00:00")), + (@Seasonnumber * 3 + 1, 2, 3, 10, @Seasonnumber, "2v2_season", TIMESTAMP(@start_date, "12:00:00"), TIMESTAMP(@end_date, "12:00:00")), + (@Seasonnumber * 3 + 2, 3, 4, 10, @Seasonnumber, "4v4_fs_season", TIMESTAMP(@start_date, "12:00:00"), TIMESTAMP(@end_date, "12:00:00")); + +INSERT INTO league_season_division (id, league_season_id, division_index, description_key, name_key) VALUES + (@Seasonnumber * 18 - 6 + 1, @Seasonnumber * 3 , 1, CONCAT("1v1_season_", @Seasonnumber, ".division.1"), "bronze"), + (@Seasonnumber * 18 - 6 + 2, @Seasonnumber * 3 , 2, CONCAT("1v1_season_", @Seasonnumber, ".division.2"), "silver"), + (@Seasonnumber * 18 - 6 + 3, @Seasonnumber * 3 , 3, CONCAT("1v1_season_", @Seasonnumber, ".division.3"), "gold"), + (@Seasonnumber * 18 - 6 + 4, @Seasonnumber * 3 , 4, CONCAT("1v1_season_", @Seasonnumber, ".division.4"), "diamond"), + (@Seasonnumber * 18 - 6 + 5, @Seasonnumber * 3 , 5, CONCAT("1v1_season_", @Seasonnumber, ".division.5"), "master"), + (@Seasonnumber * 18 - 6 + 6, @Seasonnumber * 3 , 6, CONCAT("1v1_season_", @Seasonnumber, ".division.6"), "grandmaster"), + (@Seasonnumber * 18 - 6 + 7, @Seasonnumber * 3 + 1, 1, CONCAT("2v2_season_", @Seasonnumber, ".division.1"), "bronze"), + (@Seasonnumber * 18 - 6 + 8, @Seasonnumber * 3 + 1, 2, CONCAT("2v2_season_", @Seasonnumber, ".division.2"), "silver"), + (@Seasonnumber * 18 - 6 + 9, @Seasonnumber * 3 + 1, 3, CONCAT("2v2_season_", @Seasonnumber, ".division.3"), "gold"), + (@Seasonnumber * 18 - 6 + 10, @Seasonnumber * 3 + 1, 4, CONCAT("2v2_season_", @Seasonnumber, ".division.4"), "diamond"), + (@Seasonnumber * 18 - 6 + 11, @Seasonnumber * 3 + 1, 5, CONCAT("2v2_season_", @Seasonnumber, ".division.5"), "master"), + (@Seasonnumber * 18 - 6 + 12, @Seasonnumber * 3 + 1, 6, CONCAT("2v2_season_", @Seasonnumber, ".division.6"), "grandmaster"), + (@Seasonnumber * 18 - 6 + 13, @Seasonnumber * 3 + 2, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".division.1"), "bronze"), + (@Seasonnumber * 18 - 6 + 14, @Seasonnumber * 3 + 2, 2, CONCAT("4v4_fs_season_", @Seasonnumber, ".division.2"), "silver"), + (@Seasonnumber * 18 - 6 + 15, @Seasonnumber * 3 + 2, 3, CONCAT("4v4_fs_season_", @Seasonnumber, ".division.3"), "gold"), + (@Seasonnumber * 18 - 6 + 16, @Seasonnumber * 3 + 2, 4, CONCAT("4v4_fs_season_", @Seasonnumber, ".division.4"), "diamond"), + (@Seasonnumber * 18 - 6 + 17, @Seasonnumber * 3 + 2, 5, CONCAT("4v4_fs_season_", @Seasonnumber, ".division.5"), "master"), + (@Seasonnumber * 18 - 6 + 18, @Seasonnumber * 3 + 2, 6, CONCAT("4v4_fs_season_", @Seasonnumber, ".division.6"), "grandmaster"); + +INSERT INTO league_season_division_subdivision (league_season_division_id, subdivision_index, description_key, min_rating, max_rating, highest_score, name_key) VALUES + (@Seasonnumber * 18 - 6 + 1, 1, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.1.1"), -800, -40, 10, "V"), + (@Seasonnumber * 18 - 6 + 1, 2, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.1.2"), -40, 45, 10, "IV"), + (@Seasonnumber * 18 - 6 + 1, 3, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.1.3"), 45, 130, 10, "III"), + (@Seasonnumber * 18 - 6 + 1, 4, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.1.4"), 130, 215, 10, "II"), + (@Seasonnumber * 18 - 6 + 1, 5, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.1.5"), 215, 300, 10, "I"), + (@Seasonnumber * 18 - 6 + 2, 1, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.2.1"), 300, 385, 10, "V"), + (@Seasonnumber * 18 - 6 + 2, 2, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.2.2"), 385, 470, 10, "IV"), + (@Seasonnumber * 18 - 6 + 2, 3, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.2.3"), 470, 555, 10, "III"), + (@Seasonnumber * 18 - 6 + 2, 4, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.2.4"), 555, 640, 10, "II"), + (@Seasonnumber * 18 - 6 + 2, 5, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.2.5"), 640, 725, 10, "I"), + (@Seasonnumber * 18 - 6 + 3, 1, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.3.1"), 725, 810, 10, "V"), + (@Seasonnumber * 18 - 6 + 3, 2, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.3.2"), 810, 895, 10, "IV"), + (@Seasonnumber * 18 - 6 + 3, 3, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.3.3"), 895, 980, 10, "III"), + (@Seasonnumber * 18 - 6 + 3, 4, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.3.4"), 980, 1065, 10, "II"), + (@Seasonnumber * 18 - 6 + 3, 5, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.3.5"), 1065, 1150, 10, "I"), + (@Seasonnumber * 18 - 6 + 4, 1, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.4.1"), 1150, 1235, 10, "V"), + (@Seasonnumber * 18 - 6 + 4, 2, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.4.2"), 1235, 1320, 10, "IV"), + (@Seasonnumber * 18 - 6 + 4, 3, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.4.3"), 1320, 1405, 10, "III"), + (@Seasonnumber * 18 - 6 + 4, 4, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.4.4"), 1405, 1490, 10, "II"), + (@Seasonnumber * 18 - 6 + 4, 5, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.4.5"), 1490, 1575, 10, "I"), + (@Seasonnumber * 18 - 6 + 5, 1, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.5.1"), 1575, 1660, 10, "V"), + (@Seasonnumber * 18 - 6 + 5, 2, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.5.2"), 1660, 1745, 10, "IV"), + (@Seasonnumber * 18 - 6 + 5, 3, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.5.3"), 1745, 1830, 10, "III"), + (@Seasonnumber * 18 - 6 + 5, 4, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.5.4"), 1830, 1915, 10, "II"), + (@Seasonnumber * 18 - 6 + 5, 5, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.5.5"), 1915, 2000, 10, "I"), + (@Seasonnumber * 18 - 6 + 6, 1, CONCAT("1v1_season_", @Seasonnumber, ".subdivision.6.1"), 2000, 2850, 100, ""), + (@Seasonnumber * 18 - 6 + 7, 1, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.1.1"), -800, -40, 10, "V"), + (@Seasonnumber * 18 - 6 + 7, 2, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.1.2"), -40, 45, 10, "IV"), + (@Seasonnumber * 18 - 6 + 7, 3, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.1.3"), 45, 130, 10, "III"), + (@Seasonnumber * 18 - 6 + 7, 4, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.1.4"), 130, 215, 10, "II"), + (@Seasonnumber * 18 - 6 + 7, 5, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.1.5"), 215, 300, 10, "I"), + (@Seasonnumber * 18 - 6 + 8, 1, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.2.1"), 300, 385, 10, "V"), + (@Seasonnumber * 18 - 6 + 8, 2, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.2.2"), 385, 470, 10, "IV"), + (@Seasonnumber * 18 - 6 + 8, 3, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.2.3"), 470, 555, 10, "III"), + (@Seasonnumber * 18 - 6 + 8, 4, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.2.4"), 555, 640, 10, "II"), + (@Seasonnumber * 18 - 6 + 8, 5, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.2.5"), 640, 725, 10, "I"), + (@Seasonnumber * 18 - 6 + 9, 1, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.3.1"), 725, 810, 10, "V"), + (@Seasonnumber * 18 - 6 + 9, 2, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.3.2"), 810, 895, 10, "IV"), + (@Seasonnumber * 18 - 6 + 9, 3, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.3.3"), 895, 980, 10, "III"), + (@Seasonnumber * 18 - 6 + 9, 4, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.3.4"), 980, 1065, 10, "II"), + (@Seasonnumber * 18 - 6 + 9, 5, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.3.5"), 1065, 1150, 10, "I"), + (@Seasonnumber * 18 - 6 + 10, 1, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.4.1"), 1150, 1235, 10, "V"), + (@Seasonnumber * 18 - 6 + 10, 2, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.4.2"), 1235, 1320, 10, "IV"), + (@Seasonnumber * 18 - 6 + 10, 3, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.4.3"), 1320, 1405, 10, "III"), + (@Seasonnumber * 18 - 6 + 10, 4, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.4.4"), 1405, 1490, 10, "II"), + (@Seasonnumber * 18 - 6 + 10, 5, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.4.5"), 1490, 1575, 10, "I"), + (@Seasonnumber * 18 - 6 + 11, 1, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.5.1"), 1575, 1660, 10, "V"), + (@Seasonnumber * 18 - 6 + 11, 2, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.5.2"), 1660, 1745, 10, "IV"), + (@Seasonnumber * 18 - 6 + 11, 3, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.5.3"), 1745, 1830, 10, "III"), + (@Seasonnumber * 18 - 6 + 11, 4, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.5.4"), 1830, 1915, 10, "II"), + (@Seasonnumber * 18 - 6 + 11, 5, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.5.5"), 1915, 2000, 10, "I"), + (@Seasonnumber * 18 - 6 + 12, 1, CONCAT("2v2_season_", @Seasonnumber, ".subdivision.6.1"), 2000, 2850, 100, ""), + (@Seasonnumber * 18 - 6 + 13, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.1.1"), -800, -40, 10, "V"), + (@Seasonnumber * 18 - 6 + 13, 2, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.1.2"), -40, 45, 10, "IV"), + (@Seasonnumber * 18 - 6 + 13, 3, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.1.3"), 45, 130, 10, "III"), + (@Seasonnumber * 18 - 6 + 13, 4, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.1.4"), 130, 215, 10, "II"), + (@Seasonnumber * 18 - 6 + 13, 5, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.1.5"), 215, 300, 10, "I"), + (@Seasonnumber * 18 - 6 + 14, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.2.1"), 300, 385, 10, "V"), + (@Seasonnumber * 18 - 6 + 14, 2, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.2.2"), 385, 470, 10, "IV"), + (@Seasonnumber * 18 - 6 + 14, 3, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.2.3"), 470, 555, 10, "III"), + (@Seasonnumber * 18 - 6 + 14, 4, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.2.4"), 555, 640, 10, "II"), + (@Seasonnumber * 18 - 6 + 14, 5, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.2.5"), 640, 725, 10, "I"), + (@Seasonnumber * 18 - 6 + 15, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.3.1"), 725, 810, 10, "V"), + (@Seasonnumber * 18 - 6 + 15, 2, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.3.2"), 810, 895, 10, "IV"), + (@Seasonnumber * 18 - 6 + 15, 3, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.3.3"), 895, 980, 10, "III"), + (@Seasonnumber * 18 - 6 + 15, 4, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.3.4"), 980, 1065, 10, "II"), + (@Seasonnumber * 18 - 6 + 15, 5, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.3.5"), 1065, 1150, 10, "I"), + (@Seasonnumber * 18 - 6 + 16, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.4.1"), 1150, 1235, 10, "V"), + (@Seasonnumber * 18 - 6 + 16, 2, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.4.2"), 1235, 1320, 10, "IV"), + (@Seasonnumber * 18 - 6 + 16, 3, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.4.3"), 1320, 1405, 10, "III"), + (@Seasonnumber * 18 - 6 + 16, 4, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.4.4"), 1405, 1490, 10, "II"), + (@Seasonnumber * 18 - 6 + 16, 5, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.4.5"), 1490, 1575, 10, "I"), + (@Seasonnumber * 18 - 6 + 17, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.5.1"), 1575, 1660, 10, "V"), + (@Seasonnumber * 18 - 6 + 17, 2, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.5.2"), 1660, 1745, 10, "IV"), + (@Seasonnumber * 18 - 6 + 17, 3, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.5.3"), 1745, 1830, 10, "III"), + (@Seasonnumber * 18 - 6 + 17, 4, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.5.4"), 1830, 1915, 10, "II"), + (@Seasonnumber * 18 - 6 + 17, 5, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.5.5"), 1915, 2000, 10, "I"), + (@Seasonnumber * 18 - 6 + 18, 1, CONCAT("4v4_fs_season_", @Seasonnumber, ".subdivision.6.1"), 2000, 2850, 100, ""); \ No newline at end of file diff --git a/service/season_generator.py b/service/season_generator.py new file mode 100644 index 0000000..3ae19d3 --- /dev/null +++ b/service/season_generator.py @@ -0,0 +1,45 @@ +from datetime import datetime, timedelta + +import aiocron +from sqlalchemy import select, text + +from service.config import SEASON_GENERATION_DAYS_BEFORE_SEASON_END +from service.db import FAFDatabase +from service.db.models import league_season +from service.decorators import with_logger + + +@with_logger +class SeasonGenerator: + def __init__(self, database: FAFDatabase): + self._logger.info("Season generator created.") + self._db = database + + def initialize(self): + self._update_cron = aiocron.crontab( + "0 0 * * *", func=self.check_season_end + ) + + async def check_season_end(self): + self._logger.debug("Checking if latest season ends soon.") + async with self._db.acquire() as conn: + sql = select([league_season]) + result = await conn.execute(sql) + rows = await result.fetchall() + + max_date = max(row[league_season.c.end_date] for row in rows) + + if max_date < datetime.now() + timedelta(days=SEASON_GENERATION_DAYS_BEFORE_SEASON_END): + try: + await self.generate_season() + except Exception: + self._logger.exception("Failed to generate new season") + else: + self._logger.info("Season successfully created!") + + async def generate_season(self): + self._logger.info("Generating new season...") + async with self._db.acquire() as conn: + with open("service/generate_season.sql") as file: + query = text(file.read()) + await conn.execute(query) diff --git a/tests/data/test-data.sql b/tests/data/test-data.sql index ff97d65..2eab642 100644 --- a/tests/data/test-data.sql +++ b/tests/data/test-data.sql @@ -13,7 +13,9 @@ SET FOREIGN_KEY_CHECKS=1; insert into leaderboard (id, technical_name) values (1, "global"), - (2, "ladder_1v1"); + (2, "ladder_1v1"), + (3, "tmm_2v2"), + (4, "tmm_4v4"); INSERT INTO league (id, technical_name, enabled, image_url, medium_image_url, small_image_url, name_key, description_key) VALUES (1, "test_league", TRUE, "https://faf.com/", "https://faf.com/medium/", "https://faf.com/small/", "L1", "description_key"), @@ -21,10 +23,10 @@ INSERT INTO league (id, technical_name, enabled, image_url, medium_image_url, sm (3, "league_without_seasons", TRUE, "https://faf.com/", "https://faf.com/medium/", "https://faf.com/small/", "L3", "description_key"); INSERT INTO league_season (id, league_id, leaderboard_id, placement_games, placement_games_returning_player, season_number, name_key, start_date, end_date) VALUES - (1, 1, 1, 10, 3, 1, "season.1", NOW() - interval 2 year, NOW() - interval 1 year), - (2, 1, 1, 10, 3, 2, "season.2", NOW() - interval 1 year, NOW() + interval 1 year), - (3, 2, 2, 10, 3, 1, "season.3", NOW() - interval 2 year, NOW() + interval 1 year), - (4, 1, 1, 10, 3, 3, "season.4", NOW() + interval 1 year, NOW() + interval 2 year); + (1, 1, 1, 10, 3, 1, "season.1", NOW() - interval 2 week, NOW() - interval 1 week), + (2, 1, 1, 10, 3, 2, "season.2", NOW() - interval 1 week, NOW() + interval 1 week), + (3, 2, 2, 10, 3, 1, "season.3", NOW() - interval 2 week, NOW() + interval 1 week), + (4, 1, 1, 10, 3, 3, "season.4", NOW() + interval 1 week, NOW() + interval 2 week); INSERT INTO league_season_division (id, league_season_id, division_index, name_key, description_key) VALUES (1, 1, 1, "L1D1", "description_key"), diff --git a/tests/unit_tests/test_league_service.py b/tests/unit_tests/test_league_service.py index f46dbf4..7aba9f1 100644 --- a/tests/unit_tests/test_league_service.py +++ b/tests/unit_tests/test_league_service.py @@ -1,6 +1,3 @@ -import asyncio -from contextlib import asynccontextmanager - import pytest from asynctest import CoroutineMock from sqlalchemy import select @@ -10,48 +7,10 @@ from service.league_service.league_service import ServiceNotReadyError from service.league_service.typedefs import (InvalidScoreError, League, LeagueScore) -from tests.utils import MockDatabase pytestmark = pytest.mark.asyncio -@pytest.fixture -def database_context(): - @asynccontextmanager - async def make_database(request): - def opt(val): - return request.config.getoption(val) - - host, user, pw, name, port = ( - opt("--mysql_host"), - opt("--mysql_username"), - opt("--mysql_password"), - opt("--mysql_database"), - opt("--mysql_port") - ) - db = MockDatabase(asyncio.get_running_loop()) - - await db.connect( - host=host, - user=user, - password=pw or None, - port=port, - db=name - ) - - yield db - - await db.close() - - return make_database - - -@pytest.fixture -async def database(request, database_context): - async with database_context(request) as db: - yield db - - @pytest.fixture async def league_service(database, message_queue_service): service = LeagueService(database, message_queue_service) diff --git a/tests/unit_tests/test_season_generator.py b/tests/unit_tests/test_season_generator.py new file mode 100644 index 0000000..f1ed8ae --- /dev/null +++ b/tests/unit_tests/test_season_generator.py @@ -0,0 +1,64 @@ +from collections import Counter +from datetime import datetime, timedelta + +import mock +import pytest +from freezegun import freeze_time +from sqlalchemy import select + +from service.db.models import league_season, league_season_division +from service.season_generator import SeasonGenerator + +pytestmark = pytest.mark.asyncio + + +@pytest.fixture +def season_generator(database): + season_generator = SeasonGenerator(database) + season_generator.initialize() + return season_generator + + +@freeze_time(datetime.now() - timedelta(days=5)) +async def test_early_season_check(season_generator): + season_generator.generate_season = mock.Mock() + await season_generator.check_season_end() + assert season_generator.generate_season.call_count == 0 + + +@freeze_time(datetime.now() + timedelta(days=5)) +async def test_late_season_check(season_generator): + season_generator.generate_season = mock.Mock() + await season_generator.check_season_end() + assert season_generator.generate_season.call_count == 1 + + +@freeze_time(datetime.now() + timedelta(days=20)) +async def test_season_check_after_season_end(season_generator): + season_generator.generate_season = mock.Mock() + await season_generator.check_season_end() + assert season_generator.generate_season.call_count == 1 + + +async def test_generate_season(season_generator, database): + await season_generator.generate_season() + async with database.acquire() as conn: + seasons = await conn.execute(select([league_season])) + rows = await seasons.fetchall() + assert len(rows) == 7 + assert max(row[league_season.c.season_number] for row in rows) == 4 + + divisions = await conn.execute(select(league_season_division)) + rows = await divisions.fetchall() + counter = Counter(row[league_season_division.c.description_key] for row in rows) + assert counter["1v1_season_4.division.1"] == 1 + + +async def test_generate_season_only_once(season_generator, database): + await season_generator.check_season_end() + await season_generator.check_season_end() + async with database.acquire() as conn: + seasons = await conn.execute(select([league_season])) + rows = await seasons.fetchall() + assert len(rows) == 7 + assert max(row[league_season.c.season_number] for row in rows) == 4