def distance(self, *, to): """ The distance from this hit to either the center or edge of its hitobject. Parameters ---------- to: {"center", "edge"} If ``center``, the distance from this hit to the center of its hitobject is calculated. If ``edge``, the distance from this hit to the edge of its hitobject is calculated. Returns ------- float The distance from this hit to either the center or edge of its hitobject. """ check_param(to, ["center", "edge"]) hitobj_xy = self.hitobject.xy if to == "edge": dist = np.linalg.norm(self.xy - hitobj_xy) - self.hitobject.radius # value is negative since we're inside the hitobject, so take abs return abs(dist) if to == "center": return np.linalg.norm(self.xy - hitobj_xy)
def frametime(self, replay, cv=True, mods_unknown="raise") -> float: """ The median frametime (in ms) of ``replay``. Parameters ---------- replay: :class:`~circleguard.loadables.Replay` The replay to calculate the median frametime of. cv: bool Whether to return the converted or unconverted frametime. The converted frametime is returned by default. mods_unknown: {"raise", "dt", "nm", "ht"} What to do if ``replay`` does not know what mods it was played with, and ``cv`` is ``True``. |br| If ``raise``, a ValueError will be raised. |br| If ``dt``, the frametime will be converted as if the replay was played with ``Mod.DT``. |br| If ``nm``, the frametime will be converted as if the replay was played with ``Mod.NM`` (that is, not converted at all). |br| If ``ht``, the frametime will be converted as if the replay was played with ``Mod.HT``. Returns ------- float The median frametime (in ms) of the replay. """ check_param(mods_unknown, ["raise", "dt", "nm", "ht"]) self.load(replay) frametime = Investigator.frametime(replay) if cv: if replay.mods: mods = replay.mods elif mods_unknown == "dt": mods = Mod.DT elif mods_unknown == "nm": mods = Mod.NM elif mods_unknown == "ht": mods = Mod.HT else: raise ValueError("The frametime of a replay that does not know " "with what mods it was set with cannot be converted. Pass " "a different option to frametime(..., mods_unknown=) if " "you would like to provide a default mod for conversion.") frametime = convert_statistic(frametime, mods, to="cv") return frametime
def similarity(self, replay1, replay2, method="similarity", \ num_chunks=DEFAULT_CHUNKS, mods_unknown="best") -> \ Union[float, Tuple[float]]: """ The similarity between ``replay1`` and ``replay2``. Parameters ---------- replay1: :class:`~circleguard.loadables.Replay` The replay to compare against ``replay2``. replay2: :class:`~circleguard.loadables.Replay` The replay to compare against ``replay1``. method: {"similarity", "correlation"} What method to use to calculate the similarity between the replays. |br| ``similarity`` is (roughly speaking) the average distance between the two replays in pixels. A replay compared to itself (or an exact copy) has a similarity of 0. See :data:`~circleguard.Circleguard.SIM_LIMIT` for a suggested number where similarities below this number indicate a stolen replay. |br| ``correlation`` is a signal-processing metric which measures how similar two signals (or replays, in our case) are. Correlation also takes into account time shifts, so a replay which is a perfect copy of another replay but consistently lags 10 ms behind will still have a perfect correltion of ``1``. The higher correlation, the more correlated (or similar) the two replays are. See :data:`~circleguard.Circleguard.CORR_LIMIT` for a suggested number where correlations above this number indicate a stolen replay. num_chunks: int How many chunks to split the replay into when comparing. This parameter only has an affect if ``method`` is ``correlation``. Note that runtime increases linearly with the number of chunks. mods_unknown: {"best", "both"} What to do if one or both of ``replay1`` and ``replay2`` do not know what mods they were played with. In this case, the similarity will be computed twice, both with no modifications and with ``Mod.HR`` applied to ``replay1``. |br| If ``best`` is passed, the best (that is, lowest if ``method`` is ``similarity`` and highest if ``method`` is ``correlation``) similarity of these two calculations is returned. |br| If ``both`` is passed, a tuple with two floats is returned. The first element is the similarity with no modifications, and the second element is the similarity with ``Mod.HR`` applied to ``replay1``. Returns ------- float If ``method`` is ``similarity``, this is the similarity of the two replays. If ``method`` is ``correlation``, this is the correlation between the two replays. (float, float) If ``mods_unknown`` is ``both``, a tuple with two floats is returned. The first element is the similarity with no modifications, and the second element is the similarity with ``Mod.HR`` applied to ``replay1``. See the documentation for the ``mods_unknown`` parameter for more information. """ check_param(method, ["similarity", "correlation"]) check_param(mods_unknown, ["best", "both"]) self.load(replay1) self.load(replay2) return Comparer.similarity(replay1, replay2, method, num_chunks, mods_unknown)