def setUpClass(cls): super().setUpClass() cls.user = User( 2757689, "1-2") # toy, #1=sidetracked day, #2=View of The River Styx cls.user1 = User(2757689, "1-2", cache=False) cls.user2 = User(2757689, "1-2", mods=Mod.HT) cls.user3 = User(2757689, "1") cls.map = Map( 1754777, "1-4") #sidetracked day: umbre, karthy, -duckleader-, toy cls.map1 = Map(1754777, "1-4", cache=False) cls.map2 = Map(1754777, "1-4", mods=Mod.HD) cls.map3 = Map(1754777, "1-2") cls.r = ReplayMap(1754777, 2766034) # umbre +HDHR on sidetracked day cls.r1 = ReplayMap(1754777, 2766034, cache=True) cls.r2 = ReplayMap(1754777, 2766034, mods=Mod.NF) cls.r3 = ReplayPath(RES / "legit" / "legit-1.osr") cls.r4 = ReplayPath(RES / "legit" / "legit-1.osr", cache=True) cls.r5 = ReplayPath(RES / "stolen_replay1.osr") cls.cg.load_info(cls.user) cls.cg.load_info(cls.user1) cls.cg.load_info(cls.user2) cls.cg.load_info(cls.map) cls.cg.load_info(cls.map1) cls.cg.load_info(cls.map2)
def url_scheme_called(self, url): from circleguard import ReplayMap, Circleguard, Mod # url is bytes, so decode back to str url = url.decode() # windows appends an extra slash even if the original url didn't have # it, so remove it url = url.strip("/") # all urls can have any of the following parameters: # * m - the map id # * u - the first user's id # * u2 - the second user's id # * t - the timestamp to start at # * m1 - the mods the first replay was played with # * m2 - the mods the second replay was played with # For example, a url might look like # circleguard://m=221777&u=2757689&m1=HDHRu2=3219026&m2=HDHR map_id = int(re.compile(r"m=(.*?)(&|$)").search(url).group(1)) user_id = int(re.compile(r"u=(.*?)(&|$)").search(url).group(1)) timestamp_match = re.compile(r"t=(.*?)(&|$)").search(url) # start at the beginning if timestamp isn't specified timestamp = int(timestamp_match.group(1)) if timestamp_match else 0 # mods is optional, will take the user's highest play on the map if not # specified mods1_match = re.compile(r"m1=(.*?)(&|$)").search(url) mods1 = None if mods1_match: mods1 = mods1_match.group(1) user_id_2_match = re.compile(r"u2=(.*?)(&|$)").search(url) user_id_2 = None if user_id_2_match: user_id_2 = int(user_id_2_match.group(1)) mods2_match = re.compile(r"m2=(.*?)(&|$)").search(url) mods2 = None if mods2_match: mods2 = mods2_match.group(1) # convert the string into an actual mods object if we received it mods1 = Mod(mods1) if mods1 else None r = ReplayMap(map_id, user_id, mods1) cg = Circleguard(get_setting("api_key")) cg.load(r) replays = [r] if user_id_2: mods2 = Mod(mods2) if mods2 else None r2 = ReplayMap(map_id, user_id_2, mods2) cg.load(r2) replays.append(r2) # open visualizer for the given map and user, and jump to the timestamp result = URLAnalysisResult(replays, timestamp) self.cg_classic.main_tab.url_analysis_q.put(result)
def test_snaps_only_on_hitobjs(self): r = ReplayMap(221777, 39828) snaps = self.cg.snaps(r, only_on_hitobjs=False) self.assertEqual(len(snaps), 6) # beginning self.assertEqual(snaps[0].time, 3410) self.assertAlmostEqual(snaps[0].angle, 0.19259, delta=DELTA) self.assertAlmostEqual(snaps[0].distance, 44.61642, delta=DELTA) # middle self.assertEqual(snaps[2].time, 19622) self.assertAlmostEqual(snaps[2].angle, 1.87673, delta=DELTA) self.assertAlmostEqual(snaps[2].distance, 76.04480, delta=DELTA) # end self.assertEqual(snaps[5].time, 68833) self.assertAlmostEqual(snaps[5].angle, 4.39870, delta=DELTA) self.assertAlmostEqual(snaps[5].distance, 8.14900, delta=DELTA) snaps = self.cg.snaps(r, only_on_hitobjs=True) self.assertEqual(len(snaps), 2) self.assertEqual(snaps[0].time, 68822) self.assertAlmostEqual(snaps[0].angle, 3.92694, delta=DELTA) self.assertAlmostEqual(snaps[0].distance, 8.14900, delta=DELTA) self.assertEqual(snaps[1].time, 68833) self.assertAlmostEqual(snaps[1].angle, 4.39870, delta=DELTA) self.assertAlmostEqual(snaps[1].distance, 8.14900, delta=DELTA)
def test_snaps_only_on_hitobjs_accounts_for_time(self): # checking that a frame that's in the radius of the nearest hitobj, # but isn't within the hitobj's hitwindow and so can't hit the note, # is not counted as a snap. # This replay previously had 1 snap in it. See # https://github.com/circleguard/circleguard/issues/123 r = ReplayMap(2769844, 448316, mods=Mod.HDHR) snaps = self.cg.snaps(r) self.assertEqual(len(snaps), 0)
def test_loading_other_loadables(self): r = ReplayMap(221777, 2757689) m = Map(221777, "1") u = User(12092800, "1") mu = MapUser(221777, 12092800, "1") self.assertRaises(ValueError, lambda: self.kcg.load(r)) self.assertRaises(ValueError, lambda: self.kcg.load(m)) self.assertRaises(ValueError, lambda: self.kcg.load_info(m)) self.assertRaises(ValueError, lambda: self.kcg.load(u)) self.assertRaises(ValueError, lambda: self.kcg.load_info(u)) self.assertRaises(ValueError, lambda: self.kcg.load(mu)) self.assertRaises(ValueError, lambda: self.kcg.load_info(mu))
def test_loading_replaymap(self): # Toy HDHR score on Pretender r = ReplayMap(221777, 2757689) self.assertFalse(r.loaded, "Loaded status was not correct") self.cg.load(r) self.assertEqual(r.map_id, 221777, "Map id was not correct") self.assertEqual(r.user_id, 2757689, "Map id was not correct") self.assertEqual(r.mods, Mod.HD + Mod.HR, "Mods was not correct") self.assertEqual(r.replay_id, 2832574010, "Replay is was not correct") self.assertEqual(r.weight, RatelimitWeight.HEAVY, "RatelimitWeight was not correct") self.assertEqual(r.username, "Toy", "Username was not correct") self.assertTrue(r.loaded, "Loaded status was not correct")
def test_loading_replaymap(self): # Toy HDHR score on Pretender r = ReplayMap(221777, 2757689) self.assertFalse(r.loaded) self.cg.load(r) self.assertEqual(r.map_id, 221777) self.assertEqual(r.user_id, 2757689) self.assertEqual(r.mods, Mod.HD + Mod.HR) self.assertEqual(r.replay_id, 2832574010) self.assertEqual(r.weight, RatelimitWeight.HEAVY) self.assertEqual(r.username, "Toy") self.assertTrue(r.loaded) self.assertEqual(r.count_300, 1449) self.assertEqual(r.count_100, 1) self.assertEqual(r.count_50, 0) self.assertEqual(r.count_geki, 339) self.assertEqual(r.count_katu, 1) self.assertEqual(r.count_miss, 0) self.assertEqual(r.score, 89927731) self.assertEqual(r.max_combo, 2388) self.assertTrue(r.is_perfect_combo) self.assertEqual(r.timestamp, datetime(2019, 6, 19, 3, 22, 44))
def test_no_replay_raises(self): # contrary to loading a Map, where we don't want to raise if the map # exists but no scores with the given mod combo exists, we do want to # raise if a replay is not available. r = ReplayMap(234378, 13947937) self.assertRaises(NoInfoAvailableException, lambda: self.cg.load(r))
def setUpClass(cls): # don't use cache for this test, it changes xy values slightly super().setUpClass(use_cache=False) cls.replay1 = ReplayMap(221777, 2757689)