Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.1.0 release #124

Merged
merged 58 commits into from
Dec 30, 2019
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
a589b19
remove confusing quantifier
tybug Nov 25, 2019
99ceca8
replace user info with replay info in docs
tybug Nov 29, 2019
9b3e4d3
fix replay_id documentation type
tybug Nov 29, 2019
dc3f90a
fix naming
tybug Nov 30, 2019
5a0fa0c
fix check __add__ method
tybug Nov 30, 2019
a634fec
add CHANGELOG
tybug Nov 30, 2019
c69a81b
fix MapUser inheritence
tybug Nov 30, 2019
ed365e9
move CHANGELOG to top dir
tybug Nov 30, 2019
3156ed8
rename Keys to Key
tybug Dec 1, 2019
02ed7ce
pass info when creating ReplayMap in Map
tybug Dec 1, 2019
5a6ba00
remove outdated documentation
tybug Dec 1, 2019
68731c6
fix link
tybug Dec 4, 2019
49016ae
don't show items in sphinx footer
tybug Dec 5, 2019
0bd809f
use circlecore __version__ in sphinx
tybug Dec 5, 2019
bbf9ce6
fix header length
tybug Dec 5, 2019
1c0a8dc
prefer local package over installed one
InvisibleSymbol Dec 5, 2019
f1232ee
Revert "prefer local package over installed one"
InvisibleSymbol Dec 5, 2019
3040034
Merge pull request #116 from circleguard/sphinx-formatting-changes
tybug Dec 5, 2019
2a6e33e
clean up test.py code
tybug Dec 7, 2019
f1c0486
update setup description
tybug Dec 7, 2019
a8698b0
clarify relax cheater comment
tybug Dec 8, 2019
4eb0799
fix get_user_best doc style
tybug Dec 9, 2019
2d6dd0c
Merge branch 'master' into release
InvisibleSymbol Dec 14, 2019
8017c58
fix discord webhook not working
InvisibleSymbol Dec 14, 2019
f216f9c
enable building
InvisibleSymbol Dec 14, 2019
9736698
fix Mod subtraction
tybug Dec 15, 2019
82bbc04
add changelog entry
tybug Dec 15, 2019
45994c1
Merge pull request #120 from circleguard/fix-mod-subtraction
tybug Dec 15, 2019
95fe9f8
fix many broken sphinx links and doc errors
tybug Dec 18, 2019
a985b56
fix documentation tilde placement
tybug Dec 18, 2019
fdafcc0
finish as_list_with_timestamps return type
tybug Dec 18, 2019
1208ea7
shorten Snap doc link
tybug Dec 18, 2019
9769ea6
fix forward doc caching error
tybug Dec 18, 2019
3d9b331
forward doc wording
tybug Dec 18, 2019
8e2ac20
update load_info forward doc
tybug Dec 18, 2019
7c9c214
fix load and info_load doc links
tybug Dec 18, 2019
bc98c55
fix double backticks in replaymap doc
tybug Dec 18, 2019
8eb950e
store beatmap hash
InvisibleSymbol Dec 23, 2019
1735137
correctly check response
InvisibleSymbol Dec 23, 2019
7901001
add Loader tests
InvisibleSymbol Dec 23, 2019
7ecbf45
add more tests
InvisibleSymbol Dec 23, 2019
cf321a3
rename tests
InvisibleSymbol Dec 24, 2019
da5084c
test InvalidKeyException
InvisibleSymbol Dec 24, 2019
dbf2496
remove newline
tybug Dec 24, 2019
ef696a3
clean up tests
InvisibleSymbol Dec 24, 2019
3ff3277
Merge pull request #122 from circleguard/fix_loader
InvisibleSymbol Dec 24, 2019
0ac35ae
add changelog entries for #122
tybug Dec 24, 2019
2009ed2
enforce ratelimit on all Loader functions
InvisibleSymbol Dec 24, 2019
0213203
don't reraise InvalidKeyException
InvisibleSymbol Dec 24, 2019
b02d551
add changelog entry
InvisibleSymbol Dec 24, 2019
2bf1ff1
reformat CHANGELOG file
InvisibleSymbol Dec 24, 2019
6977af5
Merge pull request #123 from circleguard/fix_loader_v2
InvisibleSymbol Dec 24, 2019
fa502ae
fix grammar
tybug Dec 30, 2019
aeb5712
add all previous releases to CHANGELOG
tybug Dec 30, 2019
0ca67f0
bump version
tybug Dec 30, 2019
3c31cc5
add changelog about changelog
tybug Dec 30, 2019
7c5e2cc
add documentation changelog entry
tybug Dec 30, 2019
1183a59
fix investigator doc link
tybug Dec 30, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@

# v3.1.0

* fix `MapUser` inheritence (now properly inherits from `ReplayContainer`)
* fix incorrect `__add__` method for `Check`
* rename `Keys` to `Key` (`Keys` left available as deprecated)
* don't double load `ReplayInfo` when using `Map`
* fix mod subtraction not being commutative (eg `Mod.HDHR - Mod.HR` has a different meaning from `Mod.HR - Mod.HDHR`)
* store beatmap hash in `ReplayPath`
* properly check response for `map_id`, `user_id`, and `username` functions
* enforce ratelimit to all Loader functions
* don't reraise `InvalidKeyException` as a `CircleguardException`
* add CHANGELOG file to both track unreleased changes and past changes
* various documentation links and wording fixes

# v3.0.0

## Important

* add aim correction detection
* new forward-facing documentation built with sphinx, including a comprehensive introduction on how to use circlecore (<https://docs.circleguard.dev/>)
* new `User` class which represents a user's top plays
* new `MapUser` class which represents all of a user's plays on a map
* new `Mod` and `ModCombination` class which represent mods
* restructure `replay.py` and inheritance of `loadables`. `Container` is (roughly) replaced with `InfoLoadable`, and `Check` is the only entry point for `Detect`.
* major `Detect` restructure; split into subclasses per cheat type. A `Detect` is instantiated with its respective thresholds(steal, ur, etc) instead of thresholds being global settings
* `Map` and `User` are now iterable and indexable, referencing `Replay`s in the `Map` or `User`
* rewrite and update all internal documentation
* `Circleguard` now takes a `cache` argument, which can make the database effectively read-only

## Not so Important

* switch documentation style from google to numpy (<https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard>)
* new method `cg.load_info` that loads the info for `ReplayContainer`s
* global settings almost entirely removed, save for `loglevel`
* instance settings almost entirely removed, save for `cache`
* rename `replay.py` to `loadable.py`
* rename `UserInfo` to `ReplayInfo`
* `Options` class removed
* add a `loader#username` function which retrieves a username from a user id. See also <https://github.com/ppy/osu-api/issues/281>
* add an `lru_cache` to `loader#map_id`, `#user_id`, and `#username` functions
* `loader#get_user_best` now returns a list of `UserInfo`, and accepts a `mods` argument.
* `cg.run` now only accepts a `Check`
* replace int mods with `ModCombination` in most places
* add ScoreV2 mod. Fixes not being able to process ScoreV2 replays.
* create a slider `Library` every time `#run` is called if `slider_dir` is not passed. Fixes `PermissionError`s on windows.
* remove convenience methods (`user_check`, `map_check`, etc). These have been replaced by `Map` and `User` (new)
* update STYLE document
* all Circleguard instances now use the same logger
* `filter` argument removed throughout the codebase
* `RatelimitWeight` and `ResultType` enum string values capitalized
* `ResultType.AIM_CORRECTION` renamed to `CORRECTION`
* `#ur` is now a staticmethod in `Investigator`

# v2.4.0

* new Map class for conveniently specifying a range of replays on a map that can be ran directly with cg.run()
* new span argument to loadables and map_check and user_check which specify exactly which of the top replays to check
* restructure of Replays and Checks. Both now inherit from Loadable, and Check and Map inherit from Container. Containers can hold other Containers, to an arbitrary depth. cg.run() now accepts any Container.
* use Slider to download beatmaps for relax detection
* fix user_check not using the same args as create_user_check
* check.filter() now requires a Loader
* add test cases for different replay types
* REPLAY_STEALING and REMODDING ResultType renamed to STEAL and REMOD respectively
* optimize ur calculation
* fix RelaxResult returning timestamped data in `result.replay` instead of the replay
* keys enum is now an IntFlag instead of an Enum
* update test cases for cookiezi's new name (chocomint)
* comparer decides mode on its own and does not need a mode in Comparer#compare
* clean up ColoredFormatter code

# v2.3.1

* fix error when running local check with both u and map id
* throw NoInfoAvailableException on empty api response

# v2.3.0

* cg.load now accepts either a Check object or a Replay object. Passing a check will result in all replays stored in the check being loaded.
* cg.load no longer requires a Check to load a replay.
* settings overhaul - settings now cascade properly and at different times than before.
* test suite added (not covering everything, yet)
* fix error when setting an Option class value (infinite recursion)

# v2.2.0

* add relax cheat detection (and consequently UR calculation)
* allow circleguard to be used without a database
* add mods argument to map_check
* add Detect settings to global/cg/check/replay
* retry requests if JSONDecodeError response is returned by ossapi
* avoids fatal error while replay loading if api returns invalid response
* fix `pip install circleguard` failing if requirements were not installed
* minor readme example updates
* remove load progress tracking from Loader

## Now Using ossapi 1.2.2

* return custom response for JSONDecodeError when api returns invalid json

## Now using circleparse 6.1.0

* replay_id now parses to an int instead of a tuple
* add <https://github.com/osufx/osu-parser> files for more complicated parsing
* switch license to GPL3 to comply with osu-parser license

# v2.1.0

* fix convenience options not having effect when passing falsy values
* load map id and user id for local osrs
* fix fatal error when ratelimit is barely hit and proceeded by light api calls
* require map_id, user_id, and timestamp in Replay
* provide earlier_replay and later_replay in Result class that reference either replay1 or replay2 depending on timestamp order (and remove later_name) (#78)

# v2.0.2

* fix false positive when the user being checked was on the map leaderboard being checked with map check
* fix false positive with user screen when user was on leaderboard of their top plays
* fix error when trying to load only a single replay from a map

# v2.0.1

* differentiate loggers between circleguard instances
* add missing cache option to convenience methods
* add map and user options to create_local_check

# v2.0.0

This release splits `Circleguard` into `circlecore` (pip module) and `circleguard` (gui with `pyqt` as the frontend, using `circlecore` as the backend).

Changes:

* replays can be loaded from arbitrary locations (db, osu website, mirror website, osr file)
* convenience methods for common use cases added (checking a map or user)
* support for comparing two arbitrary replays (from two different maps, if you so choose)
* logging overhaul, any important action is logged
* major code cleanup
* removal of command line interface
* code standardized for pip upload (`setup.py`, `__init__.py`, etc)

# v1.3.3

* fix non-osr files being loaded as osr

# v1.3.2

* fix replay being compared against itself with -m -u

# v1.3.1

* fix fatal error when using both -l and -m flags

# v1.3.0

* new profile screener that checks a user's top n plays for replay stealing and remodding when -u flag only is passed
* ability to restrict what replays are downloaded (and compared) with the --mods flag
* major internal cleanup with the addition of the user_info class
* fix names starting with an underscore not being displayed on graphs

## Now using circleparse v4.0.1

* don't fatal error when rng seed is not present when we expect it to be
* fix wrong name to int mappings
* add scorev2 (fixes fatal error on attempting to parse a replay with the scorev2 mod)

## Now using ossapi v1.1.1

* filter out None values, not None keys, in kwargs parameters

# v1.2.0

* now detect steals which either have hr added or hr removed from the replay it was stolen from
* print progress every 10% when comparing replays
* print loading progress every time there is a pause for ratelimits while loading beatmaps
* move api wrapper to separate repo; formalize api calls
* catch and retry Request related exceptions
* potentially fix matplotlib printing "invalid command name" (#43)
* fix error when redownloading outdated replays

## Now using circleparse v3.2.1

* parse rng seed value from last frame of lzma (previously, nonsensical values such as -12345|0|0|10186099 were stored in the replay data)

## Now using ossapi v1.0.0

* move api wrapper to separate repo

# v1.1.0

* new --verify flag designed for staff use that checks if replays by two users on a given map are copies
* add --version flag that prints program version
* program renamed to circleguard (thanks to InvisibleSymbol for the name)
* print usernames instead of user ids for OnlineReplay comparisons
* use a single replay folder for local comparisons instead of two
* change default threshold to 18
* highlight the later replay instead of the first replay in printout
* remove --single flag (this is now default behavior when -l is set)
* load local replays per circleguard instance (fixes incosistent gui behavior)
* handle "Replay retrieval failed." api response
* fix None replays being compared after handling api error response
* force gui comparisons to not visualize replays (avoid multithreading crashes)
* raise properly sublclassed exceptions instead of base Exception
* only revalidate users that are actually stored in local cache
* properly compress replays that use smoke key (see v1.1.1 wtc-lzma-compression)

## Now using wtc-lzma-compression v1.1.1

* treat z stream as a signed byte instead of unsigned

# v1.0.0

* original release
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Circlecore can be installed from pip:
pip install circleguard
```

This documentation refers to the project as `circlecore` to differentiate it from our organization [Circleguard](https://github.com/circleguard) and the gui application [Circleguard](https://github.com/circleguard/circlegaurd). However, `circlecore` is installed from pypi with the name `circleguard`, and is imported as such in python (`import circleguard`).
This documentation refers to the project as `circlecore` to differentiate it from our organization [Circleguard](https://github.com/circleguard) and the gui application [Circleguard](https://github.com/circleguard/circleguard). However, `circlecore` is installed from pypi with the name `circleguard`, and is imported as such in python (`import circleguard`).

## Links

Expand Down
3 changes: 1 addition & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
image: Visual Studio 2017
build: off

environment:
python_37: C:/Python37/python.exe
Expand All @@ -8,7 +7,7 @@ install:
- "%python_37% -V"
- "%python_37% -m pip install -e ."

test_script:
build_script:
- "%python_37% -m unittest"

on_failure:
Expand Down
4 changes: 2 additions & 2 deletions circleguard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from circleguard.circleguard import Circleguard, set_options
from circleguard.loadable import Check, Replay, ReplayMap, ReplayPath, Map, User, MapUser
from circleguard.enums import Detect, RatelimitWeight, Keys, StealDetect, RelaxDetect, Mod, CorrectionDetect
from circleguard.enums import Detect, RatelimitWeight, Keys, Key, StealDetect, RelaxDetect, Mod, CorrectionDetect
from circleguard.utils import TRACE, ColoredFormatter
from circleguard.loader import Loader
from circleguard.replay_info import ReplayInfo
Expand All @@ -25,5 +25,5 @@
"ComparisonResult", "RelaxResult", "ReplayStealingResult", "ResultType",
"CircleguardException", "InvalidArgumentsException", "Map", "User",
"APIException", "NoInfoAvailableException", "UnknownAPIException", "InternalAPIException",
"InvalidKeyException", "RatelimitException", "InvalidJSONException", "ReplayUnavailableException", "Keys",
"InvalidKeyException", "RatelimitException", "InvalidJSONException", "ReplayUnavailableException", "Keys", "Key",
"Mod", "CorrectionResult", "MapUser"]
10 changes: 5 additions & 5 deletions circleguard/cacher.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, cache, path):
def cache(self, lzma_bytes, replay_info):
"""
Caches a replay in the form of a (compressed) lzma stream to the
database, linking it to the given user info.
database, linking it to the given replay info.

Parameters
----------
Expand All @@ -49,11 +49,11 @@ def cache(self, lzma_bytes, replay_info):

Notes
-----
If an entry with the given user info already exists, it is overwritten
If an entry with the given replay info already exists, it is overwritten
by the passed lzma.

The lzma string is compressed with wtc compression. See
:func:`~circleguard.Cacher.compress` and :func:`~wtc.compress` for more.
:func:`~Cacher._compress` and :func:`wtc.compress` for more.

A call to this method has no effect if the Cacher's ``should_cache``
is ``False``.
Expand Down Expand Up @@ -84,7 +84,7 @@ def revalidate(self, loader, replay_info):
Checks entries in ``replay_info`` against their entries in the database
(if any) to look for score id mismatches, indicating an outdated replay.
If there are mismatches, the replay is redownloaded and cached from the
given user info.
given replay info.

Parameters
----------
Expand Down Expand Up @@ -150,7 +150,7 @@ def check_cache(self, map_id, user_id, mods):
The id of the map the replay was played on.
user_id: int
The id of the user that played the replay.
mods: :class:`circleguard.enums.ModCombination`
mods: :class:`~circleguard.enums.ModCombination`
The mods this replay was played with.

Returns
Expand Down
18 changes: 9 additions & 9 deletions circleguard/circleguard.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ class Circleguard:
given path does not exist, a fresh database will be created there.
If `None`, no replays will be cached or loaded from cache.
slider_dir: str or :class:`os.PathLike`
The path to the directory used by :mod:`slider` to store beatmaps.
If `None`, a temporary directory will be created for :mod:`slider`,
and subdsequently destroyed when this :class:`~.circleguard`
object is garbage collected.
loader: :class:`~.Loader`
A :class:`~.Loader` class or subclass, which will be used in place of
instantiating a new :class:`~.Loader` if passed. This must be the
The path to the directory used by :class:`slider.library.Library` to
store beatmaps. If `None`, a temporary directory will be created for
:class:`slider.library.Library` and subsequently destroyed when this
:class:`~Circleguard` object is garbage collected.
loader: :class:`~circleguard.loader.Loader`
A loader class or subclass, which will be used in place of
instantiating a new loader if passed. This must be the
class itself, *not* an instantiation of it. It will be instantiated
upon circleguard instantiation, with two args - a key and a cacher.
"""
Expand Down Expand Up @@ -127,7 +127,7 @@ def load(self, loadable):

Parameters
----------
loadable: :class:`~.replay.Loadable`
loadable: :class:`~circleguard.loadable.Loadable`
The loadable to load.

Notes
Expand All @@ -142,7 +142,7 @@ def load_info(self, info_loadable):

Parameters
----------
loadable: :class:`~.replay.InfoLoadable`
loadable: :class:`~circleguard.loadable.InfoLoadable`
The info loadable to load.

Notes
Expand Down
6 changes: 3 additions & 3 deletions circleguard/comparer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ class Comparer:
threshold: int
If a comparison scores below this value, one of the
:class:`~.replay.Replay` in the comparison is considered cheated.
replays1: list[:class:`~.replay.Replay`]
replays1: list[:class:`~circleguard.loadable.Replay`]
The replays to compare against either ``replays2`` if ``replays`` is
not ``None``, or against other replays in ``replays1``.
replays2: list[:class:`~.replay.Replay`]
replays2: list[:class:`~circleguard.loadable.Replay`]
The replays to compare against ``replays1``.

Notes
Expand All @@ -45,7 +45,7 @@ def __init__(self, threshold, replays1, replays2=None):
self.log = logging.getLogger(__name__)
self.threshold = threshold

# filter beatmaps we had no data for - see Loader.replay_data and OnlineReplay.from_map
# filter beatmaps we had no data for
self.replays1 = [replay for replay in replays1 if replay.replay_data is not None]
self.replays2 = [replay for replay in replays2 if replay.replay_data is not None] if replays2 else None
self.mode = "double" if self.replays2 else "single"
Expand Down
8 changes: 6 additions & 2 deletions circleguard/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def __add__(self, other):
return ModCombination(self.value | other.value)

def __sub__(self, other):
return ModCombination(self.value ^ other.value)
return ModCombination(self.value & ~other.value)

def __hash__(self):
return self.value
Expand Down Expand Up @@ -404,9 +404,13 @@ class ResultType(Enum):
CORRECTION = "Aim Correction"
TIMEWARP = "Timewarp"

class Keys(IntFlag):
class Key(IntFlag):
M1 = 1
M2 = 2
K1 = 4
K2 = 8
SMOKE = 16

# TODO remove in 4.x
# @deprecated
Keys = Key
Loading