Initial commit
This commit is contained in:
104
pp/catch_the_pp/.gitignore
vendored
Normal file
104
pp/catch_the_pp/.gitignore
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
.venv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
|
||||
.idea/
|
||||
*.c
|
674
pp/catch_the_pp/LICENSE
Normal file
674
pp/catch_the_pp/LICENSE
Normal file
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
39
pp/catch_the_pp/README.md
Normal file
39
pp/catch_the_pp/README.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Cythonized catch-the-pp
|
||||
An osu ctb gamemode star/pp calculator made in Cython.
|
||||
Original repo: [catch-the-pp](https://github.com/osufx/catch-the-pp) by [Sunpy](https://github.com/EmilySunpy).
|
||||
*Note: This repo is meant to be used as a Python package, not as a standalone program!*
|
||||
|
||||
## Changes
|
||||
- Cythonized all files, functions, classes and methods (with static typing as well)
|
||||
- Replaced `math.pow` with `**`, this gives _a bit_ of extra speed
|
||||
- Replaced imports
|
||||
- Minor code cleaning
|
||||
|
||||
## Performance
|
||||
These are the execution times after running pp calculation (with beatmap parsing and difficulty calculation as well) on `reanimate.osu` 100 times
|
||||
Pure Python version: `Min: 0.7986021041870117 s, Max: 0.932903528213501 s, Avg: 0.8350819730758667 s`
|
||||
Cythonized version: `Min: 0.22933077812194824 s, Max: 0.25774192810058594 s, Avg: 0.23836223363876344 s`
|
||||
|
||||
|
||||
## Compiling & Usage
|
||||
```
|
||||
$ git clone ... catch_the_pp
|
||||
$ cd catch_the_pp
|
||||
$ python3.6 setup.py build_ext --inplace
|
||||
...
|
||||
$ cd ..
|
||||
$ python3.6 -m catch_the_pp.sample
|
||||
Calculation:
|
||||
Stars: 1.9046727418899536, PP: 42.187660217285156, MaxCombo: 1286
|
||||
$ python3.6
|
||||
>>> from catch_the_pp.osu_parser.beatmap import Beatmap
|
||||
>>> from catch_the_pp.osu.ctb.difficulty import Difficulty
|
||||
>>> from catch_the_pp.ppCalc import calculate_pp
|
||||
>>> beatmap = Beatmap("catch_the_pp/test.osu")
|
||||
>>> difficulty = Difficulty(beatmap=beatmap, mods=0)
|
||||
>>> difficulty.star_rating
|
||||
1.9046727418899536
|
||||
>>> calculate_pp(diff=difficulty, accuracy=1, combo=beatmap.max_combo, miss=0)
|
||||
42.187660217285156
|
||||
```
|
||||
> Note: You must clone the repo in a folder that has no dashes in its name, because Python modules cannot have dashes in their name! In this example, `catch_the_pp` was used.
|
0
pp/catch_the_pp/__init__.py
Normal file
0
pp/catch_the_pp/__init__.py
Normal file
9
pp/catch_the_pp/constants.pyx
Normal file
9
pp/catch_the_pp/constants.pyx
Normal file
@@ -0,0 +1,9 @@
|
||||
STAR_SCALING_FACTOR = 0.145
|
||||
STRAIN_STEP = 750
|
||||
DECAY_WEIGHT = 0.94
|
||||
DECAY_BASE = 0.2
|
||||
ABSOLUTE_PLAYER_POSITIONING_ERROR = 16
|
||||
NORMALIZED_HITOBJECT_RADIUS = 41
|
||||
DIRECTION_CHANGE_BONUS = 12.5
|
||||
|
||||
SLIDER_QUALITY = 50
|
0
pp/catch_the_pp/osu/__init__.py
Normal file
0
pp/catch_the_pp/osu/__init__.py
Normal file
0
pp/catch_the_pp/osu/ctb/__init__.py
Normal file
0
pp/catch_the_pp/osu/ctb/__init__.py
Normal file
268
pp/catch_the_pp/osu/ctb/difficulty.pyx
Normal file
268
pp/catch_the_pp/osu/ctb/difficulty.pyx
Normal file
@@ -0,0 +1,268 @@
|
||||
from ... import constants
|
||||
from ...osu_parser.mathhelper import clamp, sign
|
||||
|
||||
|
||||
cdef class DifficultyObject:
|
||||
"""
|
||||
Object that holds strain value etc.
|
||||
|
||||
Handled in Difficulty.calculate_strainValues & Difficulty.update_hyperdash_distance.
|
||||
Used in Difficulty.calculate_difficulty
|
||||
"""
|
||||
cdef public float strain, last_movement
|
||||
cdef public float offset, player_width, scaled_position, hyperdash_distance
|
||||
cdef public object hitobject
|
||||
cdef public int error_margin, hyperdash
|
||||
|
||||
def __init__(self, hitobject, player_width):
|
||||
"""
|
||||
Hitobject wrapper to do calculation with.
|
||||
|
||||
hitobject -- Hitobject to wrap around (basic)
|
||||
player_width -- Catcher width (after determined by active mods)
|
||||
"""
|
||||
self.strain = 1
|
||||
self.offset = 0
|
||||
self.last_movement = 0
|
||||
self.hitobject = hitobject
|
||||
self.error_margin = constants.ABSOLUTE_PLAYER_POSITIONING_ERROR
|
||||
self.player_width = player_width
|
||||
self.scaled_position = self.hitobject.x * (constants.NORMALIZED_HITOBJECT_RADIUS / self.player_width)
|
||||
self.hyperdash_distance = 0
|
||||
self.hyperdash = False
|
||||
|
||||
cpdef calculate_strain(self, object last, float time_rate):
|
||||
"""
|
||||
Calculate strain value by refering last object.
|
||||
(and sets offset & last_movement info)
|
||||
|
||||
last -- Previous hitobject
|
||||
time_rate -- Timescale from enabled mods
|
||||
"""
|
||||
cdef float time = (self.hitobject.time - last.hitobject.time) / time_rate
|
||||
cdef float decay = constants.DECAY_BASE ** (time / 1000)
|
||||
|
||||
self.offset = clamp(last.scaled_position + last.offset,
|
||||
self.scaled_position - (constants.NORMALIZED_HITOBJECT_RADIUS - self.error_margin),
|
||||
self.scaled_position + (constants.NORMALIZED_HITOBJECT_RADIUS - self.error_margin)
|
||||
) - self.scaled_position
|
||||
|
||||
self.last_movement = abs(self.scaled_position - last.scaled_position + self.offset - last.offset)
|
||||
|
||||
cdef float addition = (self.last_movement ** 1.3) / 500
|
||||
|
||||
if self.scaled_position < last.scaled_position:
|
||||
self.last_movement *= -1
|
||||
|
||||
cdef float addition_bonus = 0
|
||||
cdef float sqrt_time = max(time, 25) ** 0.5
|
||||
|
||||
if abs(self.last_movement) > 0.1:
|
||||
if abs(last.last_movement) > 0.1 and sign(self.last_movement) != sign(last.last_movement):
|
||||
bonus = constants.DIRECTION_CHANGE_BONUS / sqrt_time
|
||||
bonus_factor = min(self.error_margin, abs(self.last_movement)) / self.error_margin
|
||||
|
||||
addition += bonus * bonus_factor
|
||||
|
||||
if last.hyperdash_distance <= 10:
|
||||
addition_bonus += 0.3 * bonus_factor
|
||||
|
||||
addition += 7.5 * min(abs(self.last_movement), constants.NORMALIZED_HITOBJECT_RADIUS * 2) / (constants.NORMALIZED_HITOBJECT_RADIUS * 6) / sqrt_time
|
||||
|
||||
if last.hyperdash_distance <= 10:
|
||||
if not last.hyperdash:
|
||||
addition_bonus += 1
|
||||
else:
|
||||
self.offset = 0
|
||||
|
||||
addition *= 1 + addition_bonus * ((10 - last.hyperdash_distance) / 10)
|
||||
|
||||
addition *= 850 / max(time, 25)
|
||||
self.strain = last.strain * decay + addition
|
||||
|
||||
cdef class Difficulty:
|
||||
"""
|
||||
Difficulty object for calculating star rating.
|
||||
|
||||
Stars: self.star_rating
|
||||
"""
|
||||
cdef public object beatmap
|
||||
cdef public int mods
|
||||
cdef public list hitobjects_with_ticks, difficulty_objects
|
||||
cdef public float time_rate, player_width, star_rating
|
||||
|
||||
|
||||
def __init__(self, beatmap, mods):
|
||||
"""
|
||||
CTB difficulty calculator params.
|
||||
Calculates the star rating for the given beatmap.
|
||||
|
||||
beatmap -- Beatmap object of parsed beatmap
|
||||
mods -- Int representation of mods selected / bitmask
|
||||
"""
|
||||
self.beatmap = beatmap
|
||||
self.mods = mods
|
||||
|
||||
#Difficulty modifier by mod
|
||||
cdef str diff
|
||||
for diff in self.beatmap.difficulty.keys():
|
||||
if diff == "CircleSize":
|
||||
scala = 1.3
|
||||
else:
|
||||
scala = 1.4
|
||||
self.beatmap.difficulty[diff] = self.adjust_difficulty(self.beatmap.difficulty[diff], self.mods, scala)
|
||||
|
||||
cdef object hitobject
|
||||
self.hitobjects_with_ticks = []
|
||||
for hitobject in self.beatmap.hitobjects:
|
||||
self.hitobjects_with_ticks.append(hitobject)
|
||||
if 2 & hitobject.type:
|
||||
for tick in hitobject.ticks:
|
||||
self.hitobjects_with_ticks.append(tick)
|
||||
for end_tick in hitobject.end_ticks:
|
||||
self.hitobjects_with_ticks.append(end_tick)
|
||||
|
||||
self.difficulty_objects = []
|
||||
|
||||
#Do the calculation
|
||||
self.time_rate = self.get_time_rate()
|
||||
self.player_width = 305 / 1.6 * ((102.4 * (1 - 0.7 * (self.beatmap.difficulty["CircleSize"] - 5) / 5)) / 128) * 0.7
|
||||
|
||||
for hitobject in self.hitobjects_with_ticks:
|
||||
self.difficulty_objects.append(DifficultyObject(hitobject, self.player_width * 0.4))
|
||||
|
||||
self.update_hyperdash_distance()
|
||||
|
||||
#Sort the list so its sorted by time (Incase it somehow isnt)
|
||||
self.difficulty_objects.sort(key=lambda o: o.hitobject.time)
|
||||
|
||||
self.calculate_strain_values()
|
||||
|
||||
self.star_rating = (self.calculate_difficulty() ** 0.5) * constants.STAR_SCALING_FACTOR
|
||||
|
||||
|
||||
def adjust_difficulty(self, diff, mods, scala):
|
||||
"""
|
||||
Scale difficulty from selected mods.
|
||||
|
||||
diff -- CircleSize
|
||||
mods -- Int representation of mods selected / bitmask
|
||||
return -- Scaled difficulty
|
||||
"""
|
||||
if mods & 1 << 1 > 0: #EZ
|
||||
diff = max(0, diff / 2)
|
||||
if mods & 1 << 4 > 0: #HR
|
||||
diff = min(10, diff * scala)
|
||||
|
||||
return diff
|
||||
|
||||
def get_time_rate(self):
|
||||
"""
|
||||
Get scaled time_rate from mods. (DT / HT)
|
||||
|
||||
return -- time_rate
|
||||
"""
|
||||
rate = 1
|
||||
|
||||
if self.mods & 1 << 6 > 0: #DT
|
||||
rate += 0.5
|
||||
elif self.mods & 1 << 8 > 0: #HT
|
||||
rate -= 0.25
|
||||
|
||||
return rate
|
||||
|
||||
cpdef update_hyperdash_distance(self):
|
||||
"""
|
||||
Update hyperdash_distance value for every hitobject in the beatmap.
|
||||
"""
|
||||
cdef int last_direction = 0, direction, i
|
||||
cdef float player_width_half = self.player_width / 2
|
||||
cdef float last = player_width_half
|
||||
|
||||
cdef object current_object, next_object
|
||||
|
||||
for i in range(len(self.difficulty_objects) - 1):
|
||||
current_object = self.difficulty_objects[i]
|
||||
next_object = self.difficulty_objects[i + 1]
|
||||
|
||||
if next_object.hitobject.x > current_object.hitobject.x:
|
||||
direction = 1
|
||||
else:
|
||||
direction = -1
|
||||
|
||||
time_to_next = next_object.hitobject.time - current_object.hitobject.time - 4.166667 #ms for 60fps divided by 4
|
||||
distance_to_next = abs(next_object.hitobject.x - current_object.hitobject.x)
|
||||
if last_direction == direction:
|
||||
distance_to_next -= last
|
||||
else:
|
||||
distance_to_next -= player_width_half
|
||||
|
||||
if time_to_next < distance_to_next:
|
||||
current_object.hyperdash = True
|
||||
last = player_width_half
|
||||
else:
|
||||
current_object.hyperdash_distance = time_to_next - distance_to_next
|
||||
last = clamp(current_object.hyperdash_distance, 0, player_width_half)
|
||||
|
||||
last_direction = direction
|
||||
|
||||
cpdef calculate_strain_values(self):
|
||||
"""
|
||||
Calculate strain values for every hitobject.
|
||||
|
||||
It does this by using distance, decay & previous hitobject strain value.
|
||||
Time_rate also effects this.
|
||||
"""
|
||||
cdef object current_object = self.difficulty_objects[0], next_object
|
||||
|
||||
cdef index = 1
|
||||
while index < len(self.difficulty_objects):
|
||||
next_object = self.difficulty_objects[index]
|
||||
next_object.calculate_strain(current_object, self.time_rate)
|
||||
current_object = next_object
|
||||
index += 1
|
||||
|
||||
cpdef float calculate_difficulty(self):
|
||||
"""
|
||||
Calculates the difficulty for this beatmap.
|
||||
This is used in the final function to calculate star rating.
|
||||
DISCLAIMER: This is not the final star rating value.
|
||||
|
||||
return -- difficulty
|
||||
"""
|
||||
cdef float strain_step = constants.STRAIN_STEP * self.time_rate
|
||||
cdef list highest_strains = []
|
||||
cdef float interval = strain_step
|
||||
cdef float max_strain = 0
|
||||
|
||||
cdef object last = None, difficulty_object
|
||||
|
||||
for difficulty_object in self.difficulty_objects:
|
||||
while difficulty_object.hitobject.time > interval:
|
||||
highest_strains.append(max_strain)
|
||||
|
||||
if last is None:
|
||||
max_strain = 0
|
||||
else:
|
||||
decay = (constants.DECAY_BASE ** ((interval - last.hitobject.time) / 1000))
|
||||
max_strain = last.strain * decay
|
||||
|
||||
interval += strain_step
|
||||
|
||||
if difficulty_object.strain > max_strain:
|
||||
max_strain = difficulty_object.strain
|
||||
|
||||
last = difficulty_object
|
||||
|
||||
cdef float difficulty = 0
|
||||
cdef float weight = 1
|
||||
|
||||
#Sort from high to low strain
|
||||
highest_strains.sort(key=int, reverse=True)
|
||||
|
||||
cdef float strain
|
||||
for strain in highest_strains:
|
||||
difficulty += weight * strain
|
||||
weight *= constants.DECAY_WEIGHT
|
||||
|
||||
return difficulty
|
0
pp/catch_the_pp/osu_parser/__init__.py
Normal file
0
pp/catch_the_pp/osu_parser/__init__.py
Normal file
222
pp/catch_the_pp/osu_parser/beatmap.pyx
Normal file
222
pp/catch_the_pp/osu_parser/beatmap.pyx
Normal file
@@ -0,0 +1,222 @@
|
||||
from . import mathhelper
|
||||
from .hitobject import HitObject
|
||||
|
||||
cdef class Beatmap(object):
|
||||
"""
|
||||
Beatmap object for beatmap parsing and handling
|
||||
"""
|
||||
|
||||
cdef public str file_name
|
||||
cdef public int version
|
||||
cdef public int header
|
||||
cdef public dict difficulty
|
||||
cdef public dict timing_points
|
||||
cdef public float slider_point_distance
|
||||
cdef public list hitobjects
|
||||
cdef public int max_combo
|
||||
|
||||
def __init__(self, file_name):
|
||||
"""
|
||||
file_name -- Directory for beatmap file (.osu)
|
||||
"""
|
||||
self.file_name = file_name
|
||||
self.version = -1 #Unknown by default
|
||||
self.header = -1
|
||||
self.difficulty = {}
|
||||
self.timing_points = {
|
||||
"raw_bpm": {}, #Raw bpm modifier code
|
||||
"raw_spm": {}, #Raw speed modifier code
|
||||
"bpm": {}, #Beats pr minute
|
||||
"spm": {} #Speed modifier
|
||||
}
|
||||
self.slider_point_distance = 1 #Changes after [Difficulty] is fully parsed
|
||||
self.hitobjects = []
|
||||
self.max_combo = 0
|
||||
self.parse_beatmap()
|
||||
|
||||
if "ApproachRate" not in self.difficulty.keys(): #Fix old osu version
|
||||
self.difficulty["ApproachRate"] = self.difficulty["OverallDifficulty"]
|
||||
|
||||
cpdef parse_beatmap(self):
|
||||
"""
|
||||
Parses beatmap file line by line by passing each line into parse_line.
|
||||
"""
|
||||
cdef str line
|
||||
with open(self.file_name, encoding="utf8") as file_stream:
|
||||
ver_line = ""
|
||||
while len(ver_line) < 2: #Find the line where beatmap version is spesified (normaly first line)
|
||||
ver_line = file_stream.readline()
|
||||
self.version = int(''.join(list(filter(str.isdigit, ver_line)))) #Set version
|
||||
for line in file_stream:
|
||||
self.parse_line(line.replace("\n", ""))
|
||||
|
||||
cpdef parse_line(self, str line):
|
||||
"""
|
||||
Parse a beatmapfile line.
|
||||
|
||||
Handles lines that are required for our use case (Difficulty, TimingPoints & hitobjects),
|
||||
everything else is skipped.
|
||||
"""
|
||||
if len(line) < 1:
|
||||
return
|
||||
|
||||
if line.startswith("["):
|
||||
if line == "[Difficulty]":
|
||||
self.header = 0
|
||||
elif line == "[TimingPoints]":
|
||||
self.header = 1
|
||||
elif line == "[HitObjects]":
|
||||
self.header = 2
|
||||
self.slider_point_distance = (100 * self.difficulty["SliderMultiplier"]) / self.difficulty["SliderTickRate"]
|
||||
else:
|
||||
self.header = -1
|
||||
return
|
||||
|
||||
if self.header == -1: #We return if we are reading under a header we dont care about
|
||||
return
|
||||
|
||||
if self.header == 0:
|
||||
self.handle_difficulty_propperty(line)
|
||||
elif self.header == 1:
|
||||
self.handle_timing_point(line)
|
||||
elif self.header == 2:
|
||||
self.handle_hitobject(line)
|
||||
|
||||
cpdef handle_difficulty_propperty(self, str propperty):
|
||||
"""
|
||||
Puts the [Difficulty] propperty into the difficulty dict.
|
||||
"""
|
||||
prop = propperty.split(":")
|
||||
self.difficulty[prop[0]] = float(prop[1])
|
||||
|
||||
cpdef handle_timing_point(self, str timing_point):
|
||||
"""
|
||||
Formats timing points used for slider velocity changes,
|
||||
and store them into self.timing_points dict.
|
||||
"""
|
||||
timing_point_split = timing_point.split(",")
|
||||
timing_point_time = int(float(timing_point_split[0])) #Fixes some special mappers special needs
|
||||
timing_point_focus = timing_point_split[1]
|
||||
|
||||
timing_point_type = 1
|
||||
if len(timing_point_split) >= 7: #Fix for old beatmaps that only stores bpm change and timestamp (only BPM change) [v3?]
|
||||
timing_point_type = int(timing_point_split[6])
|
||||
|
||||
if timing_point_type == 0 and not timing_point_focus.startswith("-"):
|
||||
timing_point_focus = "-100"
|
||||
|
||||
if timing_point_focus.startswith("-"): #If not then its not a slider velocity modifier
|
||||
self.timing_points["spm"][timing_point_time] = -100 / float(timing_point_focus) #Convert to normalized value and store
|
||||
self.timing_points["raw_spm"][timing_point_time] = float(timing_point_focus)
|
||||
else:
|
||||
if len(self.timing_points["bpm"]) == 0: #Fixes if hitobjects shows up before bpm is set
|
||||
timing_point_time = 0
|
||||
|
||||
self.timing_points["bpm"][timing_point_time] = 60000 / float(timing_point_focus)#^
|
||||
self.timing_points["raw_bpm"][timing_point_time] = float(timing_point_focus)
|
||||
#This trash of a game resets the spm when bpm change >.>
|
||||
self.timing_points["spm"][timing_point_time] = 1
|
||||
self.timing_points["raw_spm"][timing_point_time] = -100
|
||||
|
||||
cpdef handle_hitobject(self, str line):
|
||||
"""
|
||||
Puts every hitobject into the hitobjects array.
|
||||
|
||||
Creates hitobjects, hitobject_sliders or skip depending on the given data.
|
||||
We skip everything that is not important for us for our use case (Spinners)
|
||||
"""
|
||||
split_object = line.split(",")
|
||||
time = int(split_object[2])
|
||||
object_type = int(split_object[3])
|
||||
|
||||
if not (1 & object_type > 0 or 2 & object_type > 0): #We only want sliders and circles as spinners are random bannanas etc.
|
||||
return
|
||||
|
||||
if 2 & object_type: #Slider
|
||||
repeat = int(split_object[6])
|
||||
pixel_length = float(split_object[7])
|
||||
|
||||
time_point = self.get_timing_point_all(time)
|
||||
|
||||
tick_distance = (100 * self.difficulty["SliderMultiplier"]) / self.difficulty["SliderTickRate"]
|
||||
if self.version >= 8:
|
||||
tick_distance /= (mathhelper.clamp(-time_point["raw_spm"], 10, 1000) / 100)
|
||||
|
||||
curve_split = split_object[5].split("|")
|
||||
curve_points = []
|
||||
for i in range(1, len(curve_split)):
|
||||
vector_split = curve_split[i].split(":")
|
||||
vector = mathhelper.Vec2(int(vector_split[0]), int(vector_split[1]))
|
||||
curve_points.append(vector)
|
||||
|
||||
slider_type = curve_split[0]
|
||||
if self.version <= 6 and len(curve_points) >= 2:
|
||||
if slider_type == "L":
|
||||
slider_type = "B"
|
||||
|
||||
if len(curve_points) == 2:
|
||||
if (int(split_object[0]) == curve_points[0].x and int(split_object[1]) == curve_points[0].y) or (curve_points[0].x == curve_points[1].x and curve_points[0].y == curve_points[1].y):
|
||||
del curve_points[0]
|
||||
slider_type = "L"
|
||||
|
||||
if len(curve_points) == 0: #Incase of ExGon meme (Sliders that acts like hitcircles)
|
||||
hitobject = HitObject(int(split_object[0]), int(split_object[1]), time, 1)
|
||||
else:
|
||||
hitobject = HitObject(int(split_object[0]), int(split_object[1]), time, object_type, slider_type, curve_points, repeat, pixel_length, time_point, self.difficulty, tick_distance)
|
||||
else:
|
||||
hitobject = HitObject(int(split_object[0]), int(split_object[1]), time, object_type)
|
||||
|
||||
self.hitobjects.append(hitobject)
|
||||
self.max_combo += hitobject.get_combo()
|
||||
|
||||
def get_timing_point_all(self, time):
|
||||
"""
|
||||
Returns a object of all current timing types
|
||||
|
||||
time -- timestamp
|
||||
return -- {"raw_bpm": Float, "raw_spm": Float, "bpm": Float, "spm": Float}
|
||||
"""
|
||||
types = {
|
||||
"raw_bpm": 600,
|
||||
"raw_spm": -100,
|
||||
"bpm": 100,
|
||||
"spm": 1
|
||||
} #Will return the default value if timing point were not found
|
||||
for t in types.keys():
|
||||
r = self.get_timing_point(time, t)
|
||||
if r is not None:
|
||||
types[t] = r
|
||||
#else:
|
||||
#print("{} were not found for timestamp {}, using {} instead.".format(t, time, types[t]))
|
||||
|
||||
return types
|
||||
|
||||
def get_timing_point(self, time, timing_type):
|
||||
"""
|
||||
Returns latest timing point by timestamp (Current)
|
||||
|
||||
time -- timestamp
|
||||
timing_type -- mpb, bmp or spm
|
||||
return -- self.timing_points object
|
||||
"""
|
||||
r = None
|
||||
try:
|
||||
for key in sorted(self.timing_points[timing_type].keys(), key=lambda k: k):
|
||||
if key <= time:
|
||||
r = self.timing_points[timing_type][key]
|
||||
else:
|
||||
break
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return r
|
||||
|
||||
def get_object_count(self):
|
||||
"""
|
||||
Get the total hitobject count for the parsed beatmap (Normal hitobjects, sliders & sliderticks)
|
||||
|
||||
return -- total hitobjects for parsed beatmap
|
||||
"""
|
||||
cdef int count = 0
|
||||
for hitobject in self.hitobjects:
|
||||
count += hitobject.get_points()
|
||||
return count
|
166
pp/catch_the_pp/osu_parser/curves.pyx
Normal file
166
pp/catch_the_pp/osu_parser/curves.pyx
Normal file
@@ -0,0 +1,166 @@
|
||||
import math
|
||||
from .. import constants
|
||||
from . import mathhelper
|
||||
|
||||
class Linear(object): #Because it made sense at the time...
|
||||
def __init__(self, points):
|
||||
self.pos = points
|
||||
|
||||
cdef class Bezier(object):
|
||||
cdef public list points, pos
|
||||
cdef public int order
|
||||
|
||||
def __init__(self, points):
|
||||
self.points = points
|
||||
self.order = len(self.points)
|
||||
self.pos = []
|
||||
self.calc_points()
|
||||
|
||||
cpdef calc_points(self):
|
||||
if len(self.pos) != 0: #This should never happen but since im working on this I want to warn myself if I fuck up
|
||||
raise Exception("Bezier was calculated twice!")
|
||||
|
||||
cdef list sub_points = []
|
||||
for i in range(len(self.points)):
|
||||
if i == len(self.points) - 1:
|
||||
sub_points.append(self.points[i])
|
||||
self.bezier(sub_points)
|
||||
sub_points.clear()
|
||||
elif len(sub_points) > 1 and self.points[i] == sub_points[-1]:
|
||||
self.bezier(sub_points)
|
||||
sub_points.clear()
|
||||
|
||||
sub_points.append(self.points[i])
|
||||
|
||||
cpdef bezier(self, list points):
|
||||
cdef int order = len(points)
|
||||
cdef float step = 0.25 / constants.SLIDER_QUALITY / order #Normaly 0.0025
|
||||
cdef float i = 0
|
||||
cdef int n = order - 1
|
||||
|
||||
cdef float x, y
|
||||
cdef int p
|
||||
|
||||
while i < 1 + step:
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
for p in range(n + 1):
|
||||
a = mathhelper.cpn(p, n) * ((1 - i) ** (n - p)) * (i ** p)
|
||||
x += a * points[p].x
|
||||
y += a * points[p].y
|
||||
|
||||
point = mathhelper.Vec2(x, y)
|
||||
self.pos.append(point)
|
||||
i += step
|
||||
|
||||
def point_at_distance(self, length):
|
||||
return {
|
||||
0: False,
|
||||
1: self.points[0],
|
||||
}.get(self.order, self.rec(length))
|
||||
|
||||
def rec(self, length):
|
||||
return mathhelper.point_at_distance(self.pos, length)
|
||||
|
||||
cdef class Catmull(object): #Yes... I cry deep down on the inside aswell
|
||||
cdef public list points, pos
|
||||
cdef public int order
|
||||
cdef public float step
|
||||
|
||||
def __init__(self, points):
|
||||
self.points = points
|
||||
self.order = len(points)
|
||||
self.step = 2.5 / constants.SLIDER_QUALITY #Normaly 0.025
|
||||
self.pos = []
|
||||
self.calc_points()
|
||||
|
||||
cpdef calc_points(self):
|
||||
if len(self.pos) != 0: #This should never happen but since im working on this I want to warn myself if I fuck up
|
||||
raise Exception("Catmull was calculated twice!")
|
||||
|
||||
cdef int x
|
||||
cdef float t
|
||||
cdef object v1, v2, v3
|
||||
for x in range(self.order - 1):
|
||||
t = 0
|
||||
while t < self.step + 1:
|
||||
if x >= 1:
|
||||
v1 = self.points[x - 1]
|
||||
else:
|
||||
v1 = self.points[x]
|
||||
|
||||
v2 = self.points[x]
|
||||
|
||||
if x + 1 < self.order:
|
||||
v3 = self.points[x + 1]
|
||||
else:
|
||||
v3 = v2.calc(1, v2.calc(-1, v1))
|
||||
|
||||
if x + 2 < self.order:
|
||||
v4 = self.points[x + 2]
|
||||
else:
|
||||
v4 = v3.calc(1, v3.calc(-1, v2))
|
||||
|
||||
point = get_point([v1, v2, v3, v4], t)
|
||||
self.pos.append(point)
|
||||
t += self.step
|
||||
|
||||
def point_at_distance(self, length):
|
||||
return {
|
||||
0: False,
|
||||
1: self.points[0],
|
||||
}.get(self.order, self.rec(length))
|
||||
|
||||
def rec(self, length):
|
||||
return mathhelper.point_at_distance(self.pos, length)
|
||||
|
||||
cdef class Perfect(object):
|
||||
cdef public list points
|
||||
cdef float cx, cy
|
||||
cdef float radius
|
||||
|
||||
def __init__(self, points):
|
||||
self.points = points
|
||||
self.cx = 0
|
||||
self.cy = 0
|
||||
self.radius = 0
|
||||
self.setup_path()
|
||||
|
||||
def setup_path(self):
|
||||
self.cx, self.cy, self.radius = get_circum_circle(self.points)
|
||||
if is_left(self.points):
|
||||
self.radius *= -1
|
||||
|
||||
cpdef point_at_distance(self, float length):
|
||||
cdef float radians = length / self.radius
|
||||
return rotate(self.cx, self.cy, self.points[0], radians)
|
||||
|
||||
cpdef object get_point(object p, float length):
|
||||
cdef float x = mathhelper.catmull([o.x for o in p], length)
|
||||
cdef float y = mathhelper.catmull([o.y for o in p], length)
|
||||
return mathhelper.Vec2(x, y)
|
||||
|
||||
cpdef tuple get_circum_circle(list p):
|
||||
cdef float d = 2 * (p[0].x * (p[1].y - p[2].y) + p[1].x * (p[2].y - p[0].y) + p[2].x * (p[0].y - p[1].y))
|
||||
|
||||
if d == 0:
|
||||
raise Exception("Invalid circle! Unable to chose angle.")
|
||||
|
||||
cdef float ux = ((pow(p[0].x, 2) + pow(p[0].y, 2)) * (p[1].y - p[2].y) + (pow(p[1].x, 2) + pow(p[1].y, 2)) * (p[2].y - p[0].y) + (pow(p[2].x, 2) + pow(p[2].y, 2)) * (p[0].y - p[1].y)) / d
|
||||
cdef float uy = ((pow(p[0].x, 2) + pow(p[0].y, 2)) * (p[2].x - p[1].x) + (pow(p[1].x, 2) + pow(p[1].y, 2)) * (p[0].x - p[2].x) + (pow(p[2].x, 2) + pow(p[2].y, 2)) * (p[1].x - p[0].x)) / d
|
||||
|
||||
cdef float px = ux - p[0].x
|
||||
cdef float py = uy - p[0].y
|
||||
cdef float r = pow(pow(px, 2) + pow(py, 2), 0.5)
|
||||
|
||||
return ux, uy, r
|
||||
|
||||
cpdef float is_left(object p):
|
||||
return ((p[1].x - p[0].x) * (p[2].y - p[0].y) - (p[1].y - p[0].y) * (p[2].x - p[0].x)) < 0
|
||||
|
||||
cpdef object rotate(float cx, float cy, object p, float radians):
|
||||
cdef float cos = math.cos(radians)
|
||||
cdef float sin = math.sin(radians)
|
||||
|
||||
return mathhelper.Vec2((cos * (p.x - cx)) - (sin * (p.y - cy)) + cx, (sin * (p.x - cx)) + (cos * (p.y - cy)) + cy)
|
169
pp/catch_the_pp/osu_parser/hitobject.pyx
Normal file
169
pp/catch_the_pp/osu_parser/hitobject.pyx
Normal file
@@ -0,0 +1,169 @@
|
||||
import copy
|
||||
from . import mathhelper
|
||||
from . import curves
|
||||
|
||||
cdef class SliderTick:
|
||||
cdef public float x, y, time
|
||||
|
||||
def __init__(self, x, y, time):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.time = time
|
||||
|
||||
cdef class HitObject(object):
|
||||
cdef public float x, y, time, end_time, pixel_length, tick_distance, duration
|
||||
cdef public int type, repeat
|
||||
cdef public str slider_type
|
||||
cdef public list curve_points, ticks, end_ticks, path
|
||||
cdef public dict timing_point
|
||||
cdef public object difficulty, end
|
||||
|
||||
def __init__(self, x, y, time, object_type, slider_type = None, curve_points = None, repeat = 1, pixel_length = 0, timing_point = None, difficulty = None, tick_distance = 1):
|
||||
"""
|
||||
HitObject params for normal hitobject and sliders
|
||||
|
||||
x -- x position
|
||||
y -- y position
|
||||
time -- timestamp
|
||||
object_type -- type of object (bitmask)
|
||||
|
||||
[+] IF SLIDER
|
||||
slider_type -- type of slider (L, P, B, C)
|
||||
curve_points -- points in the curve path
|
||||
repeat -- amount of repeats for the slider (+1)
|
||||
pixel_length -- length of the slider
|
||||
timing_point -- ref of current timing point for the timestamp
|
||||
difficulty -- ref of beatmap difficulty
|
||||
tick_distance -- distance betwin each slidertick
|
||||
"""
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.time = time
|
||||
self.end_time = 0
|
||||
self.type = object_type
|
||||
|
||||
#isSlider?
|
||||
if 2 & self.type:
|
||||
self.slider_type = slider_type
|
||||
self.curve_points = [mathhelper.Vec2(self.x, self.y)] + curve_points
|
||||
self.repeat = repeat
|
||||
self.pixel_length = pixel_length
|
||||
|
||||
#For slider tick calculations
|
||||
self.timing_point = timing_point
|
||||
self.difficulty = difficulty
|
||||
self.tick_distance = tick_distance
|
||||
self.duration = (int(self.timing_point["raw_bpm"]) * (pixel_length / (self.difficulty["SliderMultiplier"] * self.timing_point["spm"])) / 100) * self.repeat
|
||||
|
||||
self.ticks = []
|
||||
self.end_ticks = []
|
||||
self.path = []
|
||||
self.end = None
|
||||
|
||||
self.calc_slider()
|
||||
|
||||
def calc_slider(self, calc_path = False):
|
||||
#Fix broken objects
|
||||
if self.slider_type == "P" and len(self.curve_points) > 3:
|
||||
self.slider_type = "B"
|
||||
elif len(self.curve_points) == 2:
|
||||
self.slider_type = "L"
|
||||
|
||||
#Make curve
|
||||
if self.slider_type == "P": #Perfect
|
||||
try:
|
||||
curve = curves.Perfect(self.curve_points)
|
||||
except:
|
||||
curve = curves.Bezier(self.curve_points)
|
||||
self.slider_type = "B"
|
||||
elif self.slider_type == "B": #Bezier
|
||||
curve = curves.Bezier(self.curve_points)
|
||||
elif self.slider_type == "C": #Catmull
|
||||
curve = curves.Catmull(self.curve_points)
|
||||
|
||||
#Quickest to skip this
|
||||
if calc_path: #Make path if requested (For drawing visual for testing)
|
||||
if self.slider_type == "L": #Linear
|
||||
self.path = curves.Linear(self.curve_points).pos
|
||||
elif self.slider_type == "P": #Perfect
|
||||
self.path = []
|
||||
l = 0
|
||||
step = 5
|
||||
while l <= self.pixel_length:
|
||||
self.path.append(curve.point_at_distance(l))
|
||||
l += step
|
||||
elif self.slider_type == "B": #Bezier
|
||||
self.path = curve.pos
|
||||
elif self.slider_type == "C": #Catmull
|
||||
self.path = curve.pos
|
||||
else:
|
||||
raise Exception("Slidertype not supported! ({})".format(self.slider_type))
|
||||
|
||||
#Set slider ticks
|
||||
current_distance = self.tick_distance
|
||||
time_add = self.duration * (self.tick_distance / (self.pixel_length * self.repeat))
|
||||
|
||||
while current_distance < self.pixel_length - self.tick_distance / 8:
|
||||
if self.slider_type == "L": #Linear
|
||||
point = mathhelper.point_on_line(self.curve_points[0], self.curve_points[1], current_distance)
|
||||
else: #Perfect, Bezier & Catmull uses the same function
|
||||
point = curve.point_at_distance(current_distance)
|
||||
|
||||
self.ticks.append(SliderTick(point.x, point.y, self.time + time_add * (len(self.ticks) + 1)))
|
||||
current_distance += self.tick_distance
|
||||
|
||||
#Adds slider_ends / repeat_points
|
||||
repeat_id = 1
|
||||
repeat_bonus_ticks = []
|
||||
while repeat_id < self.repeat:
|
||||
dist = (1 & repeat_id) * self.pixel_length
|
||||
time_offset = (self.duration / self.repeat) * repeat_id
|
||||
|
||||
if self.slider_type == "L": #Linear
|
||||
point = mathhelper.point_on_line(self.curve_points[0], self.curve_points[1], dist)
|
||||
else: #Perfect, Bezier & Catmull uses the same function
|
||||
point = curve.point_at_distance(dist)
|
||||
|
||||
self.end_ticks.append(SliderTick(point.x, point.y, self.time + time_offset))
|
||||
|
||||
#Adds the ticks that already exists on the slider back (but reversed)
|
||||
repeat_ticks = copy.deepcopy(self.ticks)
|
||||
|
||||
if 1 & repeat_id: #We have to reverse the timing normalizer
|
||||
repeat_ticks = list(reversed(repeat_ticks))
|
||||
normalize_time_value = self.time + (self.duration / self.repeat)
|
||||
else:
|
||||
normalize_time_value = self.time
|
||||
|
||||
#Correct timing
|
||||
for tick in repeat_ticks:
|
||||
tick.time = self.time + time_offset + abs(tick.time - normalize_time_value)
|
||||
|
||||
repeat_bonus_ticks += repeat_ticks
|
||||
|
||||
repeat_id += 1
|
||||
|
||||
self.ticks += repeat_bonus_ticks
|
||||
|
||||
#Add endpoint for slider
|
||||
dist_end = (1 & self.repeat) * self.pixel_length
|
||||
if self.slider_type == "L": #Linear
|
||||
point = mathhelper.point_on_line(self.curve_points[0], self.curve_points[1], dist_end)
|
||||
else: #Perfect, Bezier & Catmull uses the same function
|
||||
point = curve.point_at_distance(dist_end)
|
||||
|
||||
self.end_ticks.append(SliderTick(point.x, point.y, self.time + self.duration))
|
||||
|
||||
def get_combo(self):
|
||||
"""
|
||||
Returns the combo given by this object
|
||||
1 if normal hitobject, 2+ if slider (adds sliderticks)
|
||||
"""
|
||||
if 2 & self.type: #Slider
|
||||
val = 1 #Start of the slider
|
||||
val += len(self.ticks) #The amount of sliderticks
|
||||
val += self.repeat #Reverse slider
|
||||
else: #Normal
|
||||
val = 1 #Itself...
|
||||
|
||||
return val
|
124
pp/catch_the_pp/osu_parser/mathhelper.pyx
Normal file
124
pp/catch_the_pp/osu_parser/mathhelper.pyx
Normal file
@@ -0,0 +1,124 @@
|
||||
import math
|
||||
|
||||
cpdef float clamp(float value, float mn, float mx):
|
||||
return min(max(mn, value), mx)
|
||||
|
||||
cpdef sign(float value):
|
||||
if value == 0:
|
||||
return 0
|
||||
elif value > 0:
|
||||
return 1
|
||||
else:
|
||||
return -1
|
||||
|
||||
cpdef cpn(int p, int n):
|
||||
if p < 0 or p > n:
|
||||
return 0
|
||||
p = min(p, n - p)
|
||||
out = 1
|
||||
for i in range(1, p + 1):
|
||||
out = out * (n - p + i) / i
|
||||
|
||||
return out
|
||||
|
||||
cpdef float catmull(p, t): # WARNING: Worst math formula incomming
|
||||
return 0.5 * (
|
||||
(2 * p[1]) +
|
||||
(-p[0] + p[2]) * t +
|
||||
(2 * p[0] - 5 * p[1] + 4 * p[2] - p[3]) * (t ** 2) +
|
||||
(-p[0] + 3 * p[1] - 3 * p[2] + p[3]) * (t ** 3))
|
||||
|
||||
cpdef Vec2 point_on_line(Vec2 p0, Vec2 p1, float length):
|
||||
cdef float full_length = (((p1.x - p0.x) ** 2) + ((p1.y - p0.y) ** 2)) ** 0.5
|
||||
cdef float n = full_length - length
|
||||
|
||||
if full_length == 0: #Fix for something that seems unknown... (We warn if this happens)
|
||||
full_length = 1
|
||||
|
||||
cdef float x = (n * p0.x + length * p1.x) / full_length
|
||||
cdef float y = (n * p0.y + length * p1.y) / full_length
|
||||
|
||||
return Vec2(x, y)
|
||||
|
||||
cpdef float angle_from_points(Vec2 p0, Vec2 p1):
|
||||
return math.atan2(p1.y - p0.y, p1.x - p0.x)
|
||||
|
||||
cpdef float distance_from_points(array):
|
||||
cdef float distance = 0
|
||||
cdef int i
|
||||
|
||||
for i in range(1, len(array)):
|
||||
distance += array[i].distance(array[i - 1])
|
||||
|
||||
return distance
|
||||
|
||||
cpdef Vec2 cart_from_pol(r, t):
|
||||
cdef float x = (r * math.cos(t))
|
||||
cdef float y = (r * math.sin(t))
|
||||
|
||||
return Vec2(x, y)
|
||||
|
||||
cpdef point_at_distance(array, float distance): #TODO: Optimize...
|
||||
cdef int i = 0
|
||||
cdef float x, y, current_distance = 0, new_distance = 0, angle
|
||||
cdef Vec2 coord, cart
|
||||
|
||||
if len(array) < 2:
|
||||
return Vec2(0, 0)
|
||||
|
||||
if distance == 0:
|
||||
return array[0]
|
||||
|
||||
if distance_from_points(array) <= distance:
|
||||
return array[len(array) - 1]
|
||||
|
||||
for i in range(len(array) - 2):
|
||||
x = (array[i].x - array[i + 1].x)
|
||||
y = (array[i].y - array[i + 1].y)
|
||||
|
||||
new_distance = math.sqrt(x * x + y * y)
|
||||
current_distance += new_distance
|
||||
|
||||
if distance <= current_distance:
|
||||
break
|
||||
|
||||
current_distance -= new_distance
|
||||
|
||||
if distance == current_distance:
|
||||
return array[i]
|
||||
else:
|
||||
angle = angle_from_points(array[i], array[i + 1])
|
||||
cart = cart_from_pol((distance - current_distance), angle)
|
||||
|
||||
if array[i].x > array[i + 1].x:
|
||||
coord = Vec2((array[i].x - cart.x), (array[i].y - cart.y))
|
||||
else:
|
||||
coord = Vec2((array[i].x + cart.y), (array[i].y + cart.y))
|
||||
return coord
|
||||
|
||||
cdef class Vec2(object):
|
||||
cdef public float x
|
||||
cdef public float y
|
||||
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def __richcmp__(x, y, op):
|
||||
if op == 2:#Py_EQ
|
||||
return x.__is_equal(y)
|
||||
else:#Py_NE
|
||||
return not x.__is_equal(y)
|
||||
|
||||
def __is_equal(self, other):
|
||||
return self.x == other.x and self.y == other.y
|
||||
|
||||
cpdef float distance(Vec2 self, Vec2 other):
|
||||
cdef float x = self.x - other.x
|
||||
cdef float y = self.y - other.y
|
||||
return (x*x + y*y) ** 0.5 #sqrt, lol
|
||||
|
||||
cpdef Vec2 calc(Vec2 self, float value, Vec2 other): #I dont know what to call this function yet
|
||||
cdef float x = self.x + value * other.x
|
||||
cdef float y = self.y + value * other.y
|
||||
return Vec2(x, y)
|
41
pp/catch_the_pp/ppCalc.pyx
Normal file
41
pp/catch_the_pp/ppCalc.pyx
Normal file
@@ -0,0 +1,41 @@
|
||||
import math
|
||||
|
||||
cpdef calculate_pp(diff, accuracy, combo, miss):
|
||||
"""
|
||||
Calculate pp for gameplay
|
||||
|
||||
diff -- Difficulty object
|
||||
accuracy -- Accuracy of the play (Float 0-1)
|
||||
combo -- MaxCombo achived during the play (Int)
|
||||
miss -- Amount of misses during the play (Int)
|
||||
return -- Total pp for gameplay
|
||||
"""
|
||||
cdef float pp = (((5 * diff.star_rating / 0.0049) - 4) ** 2) / 100000
|
||||
cdef float length_bonus = 0.95 + 0.4 * min(1, combo / 3000)
|
||||
if combo > 3000:
|
||||
length_bonus += math.log10(combo / 3000) * 0.5
|
||||
|
||||
pp *= length_bonus
|
||||
pp *= (0.97 ** miss)
|
||||
pp *= min((combo ** 0.8) / (diff.beatmap.max_combo ** 0.8), 1)
|
||||
|
||||
if diff.beatmap.difficulty["ApproachRate"] > 9:
|
||||
pp *= 1 + 0.1 * (diff.beatmap.difficulty["ApproachRate"] - 9)
|
||||
if diff.beatmap.difficulty["ApproachRate"] < 8:
|
||||
pp *= 1 + 0.025 * (8 - diff.beatmap.difficulty["ApproachRate"])
|
||||
|
||||
if diff.mods & 1 << 3 > 0: #HD
|
||||
pp *= 1.05 + 0.075 * (10 - min(10, diff.beatmap.difficulty["ApproachRate"]))
|
||||
|
||||
if diff.mods & 1 << 10 > 0: #FL
|
||||
pp *= 1.35 * length_bonus
|
||||
|
||||
pp *= (accuracy ** 5.5)
|
||||
|
||||
if diff.mods & 1 << 0 > 0: #NF
|
||||
pp *= 0.9
|
||||
|
||||
if diff.mods & 1 << 12 > 0: #SO
|
||||
pp *= 0.95
|
||||
|
||||
return pp
|
899
pp/catch_the_pp/reanimate.osu
Normal file
899
pp/catch_the_pp/reanimate.osu
Normal file
@@ -0,0 +1,899 @@
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
AudioFilename: REANIMATE.mp3
|
||||
AudioLeadIn: 0
|
||||
PreviewTime: 57263
|
||||
Countdown: 0
|
||||
SampleSet: Soft
|
||||
StackLeniency: 0.5
|
||||
Mode: 2
|
||||
LetterboxInBreaks: 0
|
||||
WidescreenStoryboard: 0
|
||||
|
||||
[Editor]
|
||||
Bookmarks: 13470,24504,35539,41056,46573,50711,57608,68642,79677,90711,101746,112780,118298,119677,129246,140367,145884
|
||||
DistanceSpacing: 0.6
|
||||
BeatDivisor: 8
|
||||
GridSize: 8
|
||||
TimelineZoom: 2.372001
|
||||
|
||||
[Metadata]
|
||||
Title:REANIMATE
|
||||
TitleUnicode:REANIMATE
|
||||
Artist:Warak
|
||||
ArtistUnicode:Warak
|
||||
Creator:- Magic Bomb -
|
||||
Version:Imagination
|
||||
Source:节奏大师
|
||||
Tags:MBomb rhythm master symphonic drumstep JBHyperion Zirox JBH
|
||||
BeatmapID:1042702
|
||||
BeatmapSetID:489190
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:6
|
||||
CircleSize:4
|
||||
OverallDifficulty:9.4
|
||||
ApproachRate:9.4
|
||||
SliderMultiplier:2.1
|
||||
SliderTickRate:2
|
||||
|
||||
[Events]
|
||||
//Background and Video events
|
||||
0,0,"REVIVE.png",0,0
|
||||
//Break Periods
|
||||
//Storyboard Layer 0 (Background)
|
||||
//Storyboard Layer 1 (Fail)
|
||||
//Storyboard Layer 2 (Pass)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
||||
|
||||
[TimingPoints]
|
||||
2436,344.827586206897,4,2,77,100,1,0
|
||||
13470,-100,4,2,80,100,0,0
|
||||
13556,-100,4,2,78,85,0,0
|
||||
24160,-100,4,2,77,80,0,0
|
||||
24504,-100,4,2,78,80,0,0
|
||||
24677,-100,4,2,77,80,0,0
|
||||
27263,-100,4,2,78,80,0,0
|
||||
27436,-100,4,2,77,80,0,0
|
||||
30022,-100,4,2,78,80,0,0
|
||||
30194,-100,4,2,77,80,0,0
|
||||
32780,-100,4,2,78,80,0,0
|
||||
32953,-100,4,2,77,80,0,0
|
||||
35539,-100,4,2,78,90,0,0
|
||||
35711,-100,4,2,77,90,0,0
|
||||
38298,-100,4,2,78,90,0,0
|
||||
38470,-100,4,2,77,90,0,0
|
||||
41056,-100,4,2,78,90,0,0
|
||||
41229,-100,4,2,77,90,0,0
|
||||
43815,-100,4,2,78,90,0,0
|
||||
45194,-100,4,2,77,90,0,0
|
||||
46573,-100,4,2,78,90,0,1
|
||||
46746,-100,4,2,78,90,0,1
|
||||
48642,-66.6666666666667,4,2,78,90,0,1
|
||||
48987,-100,4,2,78,90,0,1
|
||||
49677,-66.6666666666667,4,2,78,90,0,1
|
||||
49849,-100,4,2,78,90,0,1
|
||||
56229,-66.6666666666667,4,2,78,90,0,1
|
||||
57263,-66.6666666666667,4,2,78,80,0,0
|
||||
57608,-100,4,2,78,90,0,1
|
||||
57780,-100,4,2,78,90,0,1
|
||||
63125,-100,4,2,78,90,0,1
|
||||
63470,-66.6666666666667,4,2,78,90,0,1
|
||||
63815,-100,4,2,78,90,0,1
|
||||
64332,-66.6666666666667,4,2,78,90,0,1
|
||||
64504,-100,4,2,78,90,0,1
|
||||
65539,-66.6666666666667,4,2,78,90,0,1
|
||||
65711,-100,4,2,78,90,0,1
|
||||
65884,-66.6666666666667,4,2,78,90,0,1
|
||||
66573,-100,4,2,78,90,0,1
|
||||
66918,-83.3333333333333,4,2,78,90,0,1
|
||||
67263,-100,4,2,77,80,0,1
|
||||
68642,-100,4,2,78,80,0,0
|
||||
78298,-100,4,2,77,80,0,0
|
||||
79677,-100,4,2,79,70,0,0
|
||||
90711,-100,4,2,78,70,0,0
|
||||
99073,-100,4,2,77,90,0,0
|
||||
100367,-100,4,2,77,80,0,0
|
||||
101056,-100,4,2,77,70,0,0
|
||||
101746,-100,4,2,77,80,0,0
|
||||
111573,-100,4,2,77,50,0,0
|
||||
113125,-100,4,2,77,80,0,0
|
||||
118298,-66.6666666666667,4,2,78,90,0,1
|
||||
118642,-100,4,2,78,90,0,1
|
||||
120711,-83.3333333333333,4,2,78,90,0,1
|
||||
121056,-100,4,2,78,90,0,1
|
||||
124849,-66.6666666666667,4,2,78,90,0,1
|
||||
125022,-100,4,2,78,90,0,1
|
||||
125539,-66.6666666666667,4,2,78,90,0,1
|
||||
125711,-100,4,2,78,90,0,1
|
||||
125884,-66.6666666666667,4,2,78,90,0,1
|
||||
126056,-100,4,2,78,90,0,1
|
||||
126229,-66.6666666666667,4,2,78,90,0,1
|
||||
126401,-100,4,2,78,90,0,1
|
||||
128987,-100,4,2,78,90,0,0
|
||||
129332,-100,4,2,78,90,0,1
|
||||
130194,-66.6666666666667,4,2,78,90,0,1
|
||||
130367,-100,4,2,78,90,0,1
|
||||
130884,-66.6666666666667,4,2,78,90,0,1
|
||||
131056,-100,4,2,78,90,0,1
|
||||
133470,-66.6666666666667,4,2,78,90,0,1
|
||||
133815,-100,4,2,78,90,0,1
|
||||
134158,-66.6666666666667,4,2,78,90,0,1
|
||||
134418,-100,4,2,78,90,0,1
|
||||
138987,-66.6666666666667,4,2,77,100,0,1
|
||||
139677,-83.3333333333333,4,2,77,100,0,1
|
||||
140022,-100,4,2,77,100,0,1
|
||||
140367,-100,4,2,79,80,0,0
|
||||
144504,-100,4,2,77,80,0,0
|
||||
145194,-100,4,2,77,100,0,1
|
||||
145280,-100,4,2,77,40,0,0
|
||||
|
||||
|
||||
[Colours]
|
||||
Combo1 : 183,47,49
|
||||
Combo2 : 223,170,70
|
||||
Combo3 : 84,114,98
|
||||
Combo4 : 92,107,131
|
||||
|
||||
[HitObjects]
|
||||
192,192,2436,5,4,0:0:0:0:
|
||||
141,200,2522,1,0,0:0:0:0:
|
||||
102,168,2608,1,0,0:0:0:0:
|
||||
101,117,2694,1,0,0:0:0:0:
|
||||
256,192,2780,1,0,0:0:0:0:
|
||||
144,192,2953,1,0,0:0:0:0:
|
||||
392,192,3125,2,0,P|504:112|488:64,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
432,48,3556,1,0,0:0:0:0:
|
||||
376,56,3642,1,0,0:0:0:0:
|
||||
344,95,3728,1,0,0:0:0:0:
|
||||
496,192,3815,6,0,L|400:152,2,105,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
16,192,4504,2,0,L|112:152,2,105,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
448,192,5194,5,4,0:0:0:0:
|
||||
422,146,5280,1,0,0:0:0:0:
|
||||
379,117,5366,1,0,0:0:0:0:
|
||||
327,110,5452,1,0,0:0:0:0:
|
||||
224,192,5539,1,0,0:0:0:0:
|
||||
496,192,5711,1,0,0:0:0:0:
|
||||
160,192,5884,2,0,P|88:80|120:56,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
392,192,6401,1,0,0:0:0:0:
|
||||
96,192,6573,5,2,0:0:0:0:
|
||||
96,192,6832,1,0,0:0:0:0:
|
||||
256,192,6918,2,0,B|184:120|184:120|128:120,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
416,192,7263,1,2,0:0:0:0:
|
||||
416,192,7522,1,0,0:0:0:0:
|
||||
256,192,7608,2,0,B|328:120|328:120|384:120,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,7953,5,4,0:0:0:0:
|
||||
112,192,8039,1,0,0:0:0:0:
|
||||
112,192,8125,1,0,0:0:0:0:
|
||||
176,192,8211,1,0,0:0:0:0:
|
||||
272,192,8298,1,0,0:0:0:0:
|
||||
16,192,8470,1,0,0:0:0:0:
|
||||
272,192,8642,2,0,L|496:192,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
320,192,9160,1,0,0:0:0:0:
|
||||
482,192,9332,5,2,0:0:0:0:
|
||||
308,192,9504,2,0,L|244:192,1,52.5
|
||||
164,192,9677,2,0,L|220:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
372,192,9849,2,0,L|308:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
116,192,10022,2,0,P|52:88|108:56,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
448,192,10539,1,2,0:0:0:0:
|
||||
256,192,10625,1,0,0:0:0:0:
|
||||
64,192,10711,5,4,0:0:0:0:
|
||||
256,192,10970,1,0,0:0:0:0:
|
||||
448,192,11056,1,2,0:0:0:0:
|
||||
256,192,11315,1,0,0:0:0:0:
|
||||
96,192,11401,1,2,0:0:0:0:
|
||||
256,192,11660,1,0,0:0:0:0:
|
||||
400,192,11746,1,2,0:0:0:0:
|
||||
224,192,12004,1,2,0:0:0:0:
|
||||
224,192,12091,5,0,0:0:0:0:
|
||||
464,192,12263,2,0,L|411:192,1,52.5
|
||||
176,192,12436,2,0,P|96:120|160:88,1,210,2|2,0:0|0:0,0:0:0:0:
|
||||
208,192,12867,2,0,L|272:192,2,52.5
|
||||
144,192,13125,2,0,P|40:128|40:112,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,13470,5,4,0:0:0:0:
|
||||
235,192,13556,1,0,0:0:0:0:
|
||||
182,192,13642,1,0,0:0:0:0:
|
||||
130,192,13728,1,0,0:0:0:0:
|
||||
288,192,13815,2,0,L|392:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
120,192,14160,2,0,P|47:144|96:80,1,157.5,8|0,0:0|0:0,0:0:0:0:
|
||||
256,192,14504,2,0,L|320:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,14677,2,0,L|192:192,1,52.5
|
||||
32,192,14849,5,2,0:0:0:0:
|
||||
176,192,15022,1,2,0:0:0:0:
|
||||
32,192,15194,2,0,L|192:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
480,192,15539,1,8,0:0:0:0:
|
||||
368,192,15712,1,0,0:0:0:0:
|
||||
480,192,15884,2,0,L|320:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
136,192,16229,5,2,0:0:0:0:
|
||||
186,185,16315,1,0,0:0:0:0:
|
||||
215,143,16401,1,0,0:0:0:0:
|
||||
204,93,16487,1,0,0:0:0:0:
|
||||
128,192,16573,1,2,0:0:0:0:
|
||||
384,192,16746,1,0,0:0:0:0:
|
||||
64,192,16918,2,0,P|120:96|216:80,1,210,8|2,0:0|0:0,0:0:0:0:
|
||||
488,192,17436,1,0,0:0:0:0:
|
||||
199,192,17608,6,0,L|272:112,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
184,192,17867,1,0,0:0:0:0:
|
||||
16,192,17953,2,0,L|184:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
320,192,18298,1,8,0:0:0:0:
|
||||
224,192,18557,1,0,0:0:0:0:
|
||||
392,192,18642,2,0,L|224:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
88,192,18987,5,2,0:0:0:0:
|
||||
16,192,19073,1,0,0:0:0:0:
|
||||
16,192,19160,1,0,0:0:0:0:
|
||||
64,192,19246,1,0,0:0:0:0:
|
||||
136,192,19332,1,2,0:0:0:0:
|
||||
408,192,19504,1,0,0:0:0:0:
|
||||
136,192,19677,2,0,P|224:136|272:184,1,157.5,8|0,0:0|0:0,0:0:0:0:
|
||||
64,192,20022,2,0,P|32:128|56:120,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
320,192,20367,5,2,0:0:0:0:
|
||||
448,192,20539,2,0,L|392:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
240,192,20711,2,0,L|184:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
344,192,20884,2,0,L|280:192,1,52.5
|
||||
128,192,21056,2,0,P|48:112|104:64,1,210,8|2,0:0|0:0,0:0:0:0:
|
||||
416,192,21573,2,0,L|456:152,1,52.5
|
||||
256,192,21746,6,0,L|144:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
216,192,22004,1,0,0:0:0:0:
|
||||
368,192,22091,1,0,0:0:0:0:
|
||||
417,179,22177,1,0,0:0:0:0:
|
||||
441,134,22263,1,0,0:0:0:0:
|
||||
425,86,22349,1,0,0:0:0:0:
|
||||
160,192,22436,2,0,P|72:112|208:48,1,315,8|0,0:0|0:0,0:0:0:0:
|
||||
352,192,23039,1,0,0:0:0:0:
|
||||
496,192,23125,5,2,0:0:0:0:
|
||||
400,192,23298,2,0,L|512:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
48,192,23814,1,8,0:0:0:0:
|
||||
176,192,24160,2,0,L|88:136,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,24504,5,2,0:0:0:0:
|
||||
192,192,24849,2,0,L|416:192,1,210,0|2,0:0|0:0,0:0:0:0:
|
||||
64,192,25539,2,0,L|288:192,1,210,0|2,0:0|0:0,0:0:0:0:
|
||||
496,192,26229,2,0,L|272:192,2,210,2|0|2,0:0|0:0|0:0,0:0:0:0:
|
||||
32,192,27263,6,0,L|120:136,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
304,192,27608,2,0,P|384:120|360:88,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,27953,2,0,B|384:168|384:168|272:168,1,315,2|0,0:0|0:0,0:0:0:0:
|
||||
16,192,28642,1,2,0:0:0:0:
|
||||
176,192,28987,2,0,L|392:192,2,210,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
496,192,30022,6,0,L|384:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
112,192,30367,2,0,P|40:104|80:64,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
168,192,30711,2,0,L|328:192,1,157.5
|
||||
168,192,31056,2,0,L|8:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
168,192,31401,2,0,B|464:168|424:72|352:72,1,315,2|0,0:0|0:0,0:0:0:0:
|
||||
72,72,32091,2,0,B|16:70|-23:166|272:190,1,315,2|0,0:0|0:0,0:0:0:0:
|
||||
16,192,32780,5,2,0:0:0:0:
|
||||
256,192,33125,2,0,L|40:192,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,33815,2,0,P|400:112|352:72,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,34160,6,0,L|392:192,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,34677,1,0,0:0:0:0:
|
||||
496,192,34849,2,0,L|280:192,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
16,192,35539,6,0,L|128:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,35884,2,0,L|184:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,36229,2,0,L|384:192,1,105
|
||||
224,192,36573,2,0,L|112:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
384,192,36918,6,0,L|272:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
24,192,37263,2,0,L|240:192,2,210,0|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
176,192,38125,1,0,0:0:0:0:
|
||||
432,192,38298,6,0,L|328:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,38642,2,0,L|384:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
128,192,38987,2,0,L|8:192,1,105
|
||||
192,192,39332,2,0,L|304:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
23,192,39677,6,0,L|135:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
383,192,40022,2,0,L|167:192,2,210,0|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
480,192,40884,1,0,0:0:0:0:
|
||||
176,192,41056,5,2,0:0:0:0:
|
||||
304,192,41229,1,0,0:0:0:0:
|
||||
24,192,41401,2,0,L|128:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
400,192,41746,2,0,L|505:192,1,105
|
||||
129,192,42091,2,0,L|24:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
383,192,42436,6,0,L|488:192,2,105,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
88,192,42953,1,0,0:0:0:0:
|
||||
344,192,43125,2,0,L|239:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,43470,2,0,L|336:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
160,192,43815,6,0,L|48:192,3,105,2|0|2|0,0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
352,192,44504,2,0,L|464:192,3,105,2|0|2|0,0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
192,192,45194,5,2,0:0:0:0:
|
||||
456,192,45539,1,0,0:0:0:0:
|
||||
32,192,45884,2,0,P|104:96|328:120,1,367.5,2|0,0:0|0:0,0:0:0:0:
|
||||
184,192,46573,6,0,L|24:192,1,157.5,6|0,0:0|0:0,0:0:0:0:
|
||||
184,192,46918,1,8,0:0:0:0:
|
||||
64,192,47091,1,0,0:0:0:0:
|
||||
344,192,47263,2,0,L|400:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
192,192,47436,2,0,L|136:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
400,192,47608,1,8,0:0:0:0:
|
||||
128,192,47780,2,0,L|176:168,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,47953,6,0,P|404:184|452:160,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
180,192,48298,1,8,0:0:0:0:
|
||||
452,192,48470,2,0,L|396:192,1,52.5
|
||||
96,192,48642,1,0,0:0:0:0:
|
||||
110,155,48685,1,0,0:0:0:0:
|
||||
137,127,48728,1,0,0:0:0:0:
|
||||
174,113,48771,1,0,0:0:0:0:
|
||||
213,114,48814,1,0,0:0:0:0:
|
||||
248,130,48857,1,0,0:0:0:0:
|
||||
274,159,48900,1,0,0:0:0:0:
|
||||
287,196,48943,1,0,0:0:0:0:
|
||||
128,192,48987,2,0,L|24:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
320,192,49332,6,0,L|496:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
320,192,49677,2,0,L|224:192,1,78.7500030040742,8|0,0:0|0:0,0:0:0:0:
|
||||
80,192,49849,2,0,L|136:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,50022,2,0,L|232:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
64,192,50194,2,0,L|120:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
312,192,50367,2,0,L|272:152,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
120,192,50539,2,0,L|176:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
336,192,50711,6,0,L|224:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,51056,2,0,L|384:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
224,192,51401,2,0,L|352:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
272,192,51660,1,2,0:0:0:0:
|
||||
120,192,51746,2,0,L|8:192,1,105,8|2,0:0|0:0,0:0:0:0:
|
||||
360,192,52091,6,0,L|464:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
192,192,52436,1,8,0:0:0:0:
|
||||
464,192,52608,1,0,0:0:0:0:
|
||||
484,176,52651,1,0,0:0:0:0:
|
||||
497,153,52694,1,0,0:0:0:0:
|
||||
497,127,52737,1,0,0:0:0:0:
|
||||
360,192,52780,1,2,0:0:0:0:
|
||||
200,192,52867,1,2,0:0:0:0:
|
||||
40,192,52953,1,2,0:0:0:0:
|
||||
360,192,53125,1,8,0:0:0:0:
|
||||
40,192,53298,2,0,L|88:168,1,52.5
|
||||
240,192,53470,5,2,0:0:0:0:
|
||||
490,192,53642,2,0,L|418:192,1,52.5
|
||||
256,192,53815,1,8,0:0:0:0:
|
||||
112,192,53987,2,0,L|168:192,1,52.5
|
||||
328,192,54160,5,0,0:0:0:0:
|
||||
353,196,54203,1,0,0:0:0:0:
|
||||
378,188,54246,1,0,0:0:0:0:
|
||||
395,169,54289,1,0,0:0:0:0:
|
||||
400,144,54332,1,0,0:0:0:0:
|
||||
393,119,54375,1,0,0:0:0:0:
|
||||
374,101,54418,1,0,0:0:0:0:
|
||||
348,95,54461,1,0,0:0:0:0:
|
||||
216,192,54504,5,8,0:0:0:0:
|
||||
190,196,54547,1,0,0:0:0:0:
|
||||
165,188,54590,1,0,0:0:0:0:
|
||||
148,169,54633,1,0,0:0:0:0:
|
||||
143,144,54676,1,0,0:0:0:0:
|
||||
150,119,54719,1,0,0:0:0:0:
|
||||
169,101,54762,1,0,0:0:0:0:
|
||||
195,95,54805,1,0,0:0:0:0:
|
||||
72,192,54849,6,0,P|24:128|80:64,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,55194,1,8,0:0:0:0:
|
||||
448,192,55280,1,2,0:0:0:0:
|
||||
256,192,55367,1,2,0:0:0:0:
|
||||
64,192,55453,1,2,0:0:0:0:
|
||||
256,192,55539,2,0,L|320:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
116,192,55711,2,0,L|60:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,55884,2,0,L|320:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
116,192,56056,2,0,L|60:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
336,192,56229,6,0,L|496:192,1,157.500006008148,8|0,0:0|0:0,0:0:0:0:
|
||||
176,192,56573,2,0,L|16:192,1,157.500006008148,8|0,0:0|0:0,0:0:0:0:
|
||||
336,192,56918,5,8,0:0:0:0:
|
||||
410,190,57004,1,2,0:0:0:0:
|
||||
440,122,57090,1,2,0:0:0:0:
|
||||
390,66,57176,1,2,0:0:0:0:
|
||||
176,192,57263,2,0,P|96:112|168:48,1,236.250009012223,8|0,0:0|0:0,0:0:0:0:
|
||||
352,192,57608,6,0,L|456:192,1,105,6|0,0:0|0:0,0:0:0:0:
|
||||
192,192,57953,1,8,0:0:0:0:
|
||||
456,192,58125,2,0,L|400:192,1,52.5
|
||||
192,192,58298,2,0,L|192:136,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,58470,2,0,L|328:144,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
128,192,58642,1,8,0:0:0:0:
|
||||
72,192,58729,2,0,L|176:192,1,105
|
||||
328,192,58987,5,2,0:0:0:0:
|
||||
64,192,59160,2,0,L|8:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
177,192,59332,2,0,L|241:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
64,192,59504,2,0,L|8:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,59677,2,0,L|232:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
64,192,59849,2,0,L|8:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
192,192,60022,1,8,0:0:0:0:
|
||||
480,192,60194,2,0,L|432:168,1,52.5
|
||||
256,192,60367,6,0,L|368:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
71,192,60711,2,0,L|175:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
256,192,60970,1,0,0:0:0:0:
|
||||
441,192,61056,2,0,L|337:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
48,192,61401,1,8,0:0:0:0:
|
||||
30,172,61444,1,0,0:0:0:0:
|
||||
24,147,61487,1,0,0:0:0:0:
|
||||
30,122,61530,1,0,0:0:0:0:
|
||||
48,103,61573,1,0,0:0:0:0:
|
||||
320,192,61746,5,2,0:0:0:0:
|
||||
456,192,61918,1,2,0:0:0:0:
|
||||
192,192,62091,1,8,0:0:0:0:
|
||||
56,192,62263,1,2,0:0:0:0:
|
||||
320,192,62436,2,0,L|216:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
288,192,62694,1,2,0:0:0:0:
|
||||
448,192,62780,1,8,0:0:0:0:
|
||||
96,192,62953,1,2,0:0:0:0:
|
||||
384,192,63125,6,0,L|496:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
424,192,63384,1,0,0:0:0:0:
|
||||
176,192,63470,2,0,B|32:192|32:192|51:144|96:120,1,236.250009012223,8|0,0:0|0:0,0:0:0:0:
|
||||
240,192,63815,1,2,0:0:0:0:
|
||||
384,192,63901,1,2,0:0:0:0:
|
||||
240,192,63987,1,2,0:0:0:0:
|
||||
96,192,64073,1,2,0:0:0:0:
|
||||
288,192,64160,2,0,L|368:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
192,192,64332,2,0,L|96:192,1,78.7500030040742,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,64504,6,0,P|384:136|384:88,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
224,192,64849,2,0,L|160:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
328,192,65022,2,0,L|392:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
224,192,65194,2,0,L|160:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
344,192,65367,2,0,L|408:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
240,192,65539,2,0,L|160:192,1,78.7500030040742,8|0,0:0|0:0,0:0:0:0:
|
||||
16,192,65711,2,0,L|80:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,65884,6,0,B|416:192|416:192|384:144|320:120,1,236.250009012223,2|0,0:0|0:0,0:0:0:0:
|
||||
128,192,66229,1,8,0:0:0:0:
|
||||
48,192,66315,2,0,L|208:192,1,157.500006008148
|
||||
376,192,66573,1,8,0:0:0:0:
|
||||
205,192,66660,1,2,0:0:0:0:
|
||||
120,192,66746,2,0,L|176:192,1,52.5,2|2,0:0|0:0,0:0:0:0:
|
||||
336,192,66918,2,0,L|208:192,1,125.999996154785,8|2,0:0|0:0,0:0:0:0:
|
||||
480,192,67263,6,0,B|488:112|480:48|432:24|336:16|232:48,1,367.5,2|0,0:0|0:0,0:0:0:0:
|
||||
32,192,67953,2,0,B|24:112|32:48|80:24|176:16|280:48,1,367.5,2|0,0:0|0:0,0:0:0:0:
|
||||
120,192,68642,6,0,P|48:168|48:88,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
120,192,68987,2,0,P|248:120|248:96,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
96,192,69332,1,8,0:0:0:0:
|
||||
352,192,69504,2,0,L|408:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
248,192,69677,2,0,L|192:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,69849,2,0,L|408:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
232,192,70022,6,0,L|176:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
128,192,70194,1,2,0:0:0:0:
|
||||
264,192,70367,1,2,0:0:0:0:
|
||||
392,192,70539,2,0,L|328:192,1,52.5
|
||||
168,192,70711,5,8,0:0:0:0:
|
||||
142,199,70754,1,0,0:0:0:0:
|
||||
116,199,70797,1,0,0:0:0:0:
|
||||
91,193,70840,1,0,0:0:0:0:
|
||||
68,180,70883,1,0,0:0:0:0:
|
||||
50,162,70926,1,0,0:0:0:0:
|
||||
36,139,70969,1,0,0:0:0:0:
|
||||
30,114,71012,1,0,0:0:0:0:
|
||||
30,87,71055,1,0,0:0:0:0:
|
||||
37,62,71098,1,0,0:0:0:0:
|
||||
51,40,71142,1,0,0:0:0:0:
|
||||
70,22,71185,1,0,0:0:0:0:
|
||||
93,9,71228,1,0,0:0:0:0:
|
||||
118,4,71271,1,0,0:0:0:0:
|
||||
144,5,71314,1,0,0:0:0:0:
|
||||
169,12,71357,1,0,0:0:0:0:
|
||||
280,192,71401,6,0,P|392:120|368:72,1,210,2|2,0:0|0:0,0:0:0:0:
|
||||
160,192,72004,1,0,0:0:0:0:
|
||||
336,192,72091,1,8,0:0:0:0:
|
||||
283,192,72177,1,2,0:0:0:0:
|
||||
230,192,72263,1,2,0:0:0:0:
|
||||
177,192,72349,1,2,0:0:0:0:
|
||||
124,192,72435,1,2,0:0:0:0:
|
||||
88,192,72522,1,2,0:0:0:0:
|
||||
144,192,72608,1,2,0:0:0:0:
|
||||
224,192,72694,1,2,0:0:0:0:
|
||||
400,192,72780,6,0,L|504:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
416,192,73125,1,0,0:0:0:0:
|
||||
8,192,73470,2,0,L|120:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
32,192,73815,2,0,L|192:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
344,192,74160,6,0,L|456:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,74504,2,0,L|176:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
464,192,74849,2,0,L|408:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
256,192,75022,2,0,L|192:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,75194,2,0,L|296:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
144,192,75367,2,0,L|80:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
240,192,75539,6,0,L|176:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
40,192,75711,1,2,0:0:0:0:
|
||||
299,192,75884,2,0,L|352:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,76056,2,0,L|440:192,1,52.5
|
||||
280,192,76229,1,8,0:0:0:0:
|
||||
254,186,76272,1,0,0:0:0:0:
|
||||
235,168,76315,1,0,0:0:0:0:
|
||||
227,144,76358,1,0,0:0:0:0:
|
||||
232,118,76401,1,0,0:0:0:0:
|
||||
249,99,76444,1,0,0:0:0:0:
|
||||
274,90,76487,1,0,0:0:0:0:
|
||||
299,95,76530,1,0,0:0:0:0:
|
||||
408,192,76573,2,0,P|488:112|464:80,1,157.5
|
||||
288,192,76918,6,0,P|176:112|200:64,1,210,2|2,0:0|0:0,0:0:0:0:
|
||||
352,192,77522,1,0,0:0:0:0:
|
||||
208,192,77608,1,8,0:0:0:0:
|
||||
157,199,77694,1,2,0:0:0:0:
|
||||
112,173,77780,1,2,0:0:0:0:
|
||||
95,124,77866,1,2,0:0:0:0:
|
||||
111,76,77952,1,2,0:0:0:0:
|
||||
155,48,78039,1,2,0:0:0:0:
|
||||
240,192,78125,1,2,0:0:0:0:
|
||||
292,192,78211,1,2,0:0:0:0:
|
||||
144,192,78298,6,0,L|32:192,3,105,2|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
368,192,78987,2,0,L|480:192,3,105,2|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
136,192,79677,6,0,P|24:96|152:64,1,341.25,4|0,0:0|0:0,0:0:0:0:
|
||||
376,192,80367,2,0,P|488:96|360:64,1,341.25,8|0,0:0|0:0,0:0:0:0:
|
||||
96,192,81056,6,0,L|0:144,2,105,2|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
504,192,81746,1,8,0:0:0:0:
|
||||
336,192,82091,2,0,L|448:192,1,105
|
||||
160,192,82436,6,0,B|8:192|8:192|56:96|152:80,1,341.25,4|0,0:0|0:0,0:0:0:0:
|
||||
352,192,83125,2,0,B|504:192|504:192|456:96|360:80,1,341.25,8|0,0:0|0:0,0:0:0:0:
|
||||
224,192,83815,6,0,L|112:192,2,105,2|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
464,192,84504,1,8,0:0:0:0:
|
||||
336,192,84677,1,0,0:0:0:0:
|
||||
496,192,84849,1,0,0:0:0:0:
|
||||
336,192,85022,1,0,0:0:0:0:
|
||||
48,192,85194,6,0,L|272:192,2,210,4|0|8,0:0|0:0|0:0,0:0:0:0:
|
||||
464,192,86229,2,0,L|240:192,2,210,0|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
248,192,87263,2,0,L|136:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
264,192,87608,2,0,L|376:192,1,105
|
||||
104,192,87953,5,4,0:0:0:0:
|
||||
8,192,88125,2,0,L|64:192,1,52.5
|
||||
120,192,88298,2,0,L|32:136,1,105
|
||||
320,192,88642,1,8,0:0:0:0:
|
||||
424,192,88987,1,0,0:0:0:0:
|
||||
394,192,89101,1,0,0:0:0:0:
|
||||
324,192,89216,1,0,0:0:0:0:
|
||||
112,192,89332,6,0,L|224:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
384,192,89677,2,0,L|288:192,1,70,2|0,0:0|0:0,0:0:0:0:
|
||||
224,192,89907,1,0,0:0:0:0:
|
||||
48,192,90022,2,0,L|128:192,1,70,8|0,0:0|0:0,0:0:0:0:
|
||||
208,192,90252,1,0,0:0:0:0:
|
||||
280,192,90367,2,0,L|176:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,90625,1,0,0:0:0:0:
|
||||
416,192,90711,6,0,L|488:192,2,70,6|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
208,192,91056,1,0,0:0:0:0:
|
||||
181,192,91099,1,0,0:0:0:0:
|
||||
157,184,91142,1,0,0:0:0:0:
|
||||
136,168,91185,1,0,0:0:0:0:
|
||||
123,146,91228,1,0,0:0:0:0:
|
||||
118,120,91271,1,0,0:0:0:0:
|
||||
122,94,91314,1,0,0:0:0:0:
|
||||
135,72,91357,1,0,0:0:0:0:
|
||||
256,192,91401,6,0,L|336:192,2,70,8|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
168,192,91746,2,0,L|88:192,2,70
|
||||
384,192,92091,5,2,0:0:0:0:
|
||||
410,191,92134,1,0,0:0:0:0:
|
||||
434,181,92177,1,0,0:0:0:0:
|
||||
452,163,92220,1,0,0:0:0:0:
|
||||
424,192,92263,1,2,0:0:0:0:
|
||||
397,192,92306,1,0,0:0:0:0:
|
||||
373,182,92349,1,0,0:0:0:0:
|
||||
355,164,92392,1,0,0:0:0:0:
|
||||
232,192,92436,2,0,L|152:192,2,70,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
432,192,92780,6,0,L|504:192,2,70,8|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
337,192,93125,2,0,L|225:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,93470,6,0,L|408:192,2,70,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
320,192,93815,1,0,0:0:0:0:
|
||||
294,196,93858,1,0,0:0:0:0:
|
||||
268,191,93901,1,0,0:0:0:0:
|
||||
246,177,93944,1,0,0:0:0:0:
|
||||
231,156,93987,1,0,0:0:0:0:
|
||||
224,131,94030,1,0,0:0:0:0:
|
||||
226,105,94073,1,0,0:0:0:0:
|
||||
238,82,94116,1,0,0:0:0:0:
|
||||
352,192,94160,6,0,L|464:192,2,70,8|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
160,192,94504,2,0,L|48:192,2,70
|
||||
352,192,94849,5,2,0:0:0:0:
|
||||
325,192,94892,1,0,0:0:0:0:
|
||||
299,192,94935,1,0,0:0:0:0:
|
||||
288,192,94978,1,0,0:0:0:0:
|
||||
299,192,95022,1,2,0:0:0:0:
|
||||
325,192,95065,1,0,0:0:0:0:
|
||||
351,192,95108,1,0,0:0:0:0:
|
||||
377,192,95151,1,0,0:0:0:0:
|
||||
272,192,95194,2,0,L|217:144,2,70,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
72,192,95539,6,0,L|16:144,2,70,8|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
280,192,95884,2,0,L|392:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
96,192,96229,5,2,0:0:0:0:
|
||||
288,192,96344,1,0,0:0:0:0:
|
||||
488,192,96458,1,0,0:0:0:0:
|
||||
256,192,96573,1,0,0:0:0:0:
|
||||
229,193,96616,1,0,0:0:0:0:
|
||||
204,185,96659,1,0,0:0:0:0:
|
||||
183,170,96702,1,0,0:0:0:0:
|
||||
168,149,96745,1,0,0:0:0:0:
|
||||
160,124,96788,1,0,0:0:0:0:
|
||||
160,98,96831,1,0,0:0:0:0:
|
||||
169,74,96874,1,0,0:0:0:0:
|
||||
288,192,96918,5,8,0:0:0:0:
|
||||
480,192,97033,1,0,0:0:0:0:
|
||||
288,192,97147,1,0,0:0:0:0:
|
||||
80,192,97263,1,0,0:0:0:0:
|
||||
272,192,97378,1,0,0:0:0:0:
|
||||
464,192,97492,1,0,0:0:0:0:
|
||||
256,192,97608,5,2,0:0:0:0:
|
||||
232,183,97651,1,0,0:0:0:0:
|
||||
217,162,97694,1,0,0:0:0:0:
|
||||
224,136,97737,1,0,0:0:0:0:
|
||||
256,192,97780,1,2,0:0:0:0:
|
||||
281,183,97823,1,0,0:0:0:0:
|
||||
296,162,97866,1,0,0:0:0:0:
|
||||
297,136,97909,1,0,0:0:0:0:
|
||||
160,192,97953,2,0,L|80:192,2,70,2|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
352,192,98298,6,0,L|432:192,2,70,8|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
160,192,98642,2,0,L|40:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
296,192,98987,5,6,0:0:0:0:
|
||||
488,192,99102,1,0,0:0:0:0:
|
||||
296,192,99217,1,0,0:0:0:0:
|
||||
72,192,99332,1,0,0:0:0:0:
|
||||
46,189,99375,1,0,0:0:0:0:
|
||||
24,175,99418,1,0,0:0:0:0:
|
||||
10,153,99461,1,0,0:0:0:0:
|
||||
7,127,99504,1,0,0:0:0:0:
|
||||
17,103,99547,1,0,0:0:0:0:
|
||||
32,80,99590,1,0,0:0:0:0:
|
||||
48,72,99633,1,0,0:0:0:0:
|
||||
152,192,99677,5,2,0:0:0:0:
|
||||
328,192,99792,1,0,0:0:0:0:
|
||||
152,192,99907,1,0,0:0:0:0:
|
||||
440,192,100022,1,0,0:0:0:0:
|
||||
264,192,100137,1,0,0:0:0:0:
|
||||
88,192,100252,1,0,0:0:0:0:
|
||||
264,192,100367,5,4,0:0:0:0:
|
||||
296,192,100410,1,0,0:0:0:0:
|
||||
296,192,100453,1,0,0:0:0:0:
|
||||
264,192,100496,1,0,0:0:0:0:
|
||||
232,192,100539,1,0,0:0:0:0:
|
||||
208,192,100582,1,0,0:0:0:0:
|
||||
208,192,100625,1,0,0:0:0:0:
|
||||
232,192,100668,1,0,0:0:0:0:
|
||||
344,192,100711,1,2,0:0:0:0:
|
||||
152,192,101056,1,2,0:0:0:0:
|
||||
408,192,101401,1,2,0:0:0:0:
|
||||
64,192,101746,5,4,0:0:0:0:
|
||||
20,168,101832,1,0,0:0:0:0:
|
||||
24,119,101918,1,0,0:0:0:0:
|
||||
72,104,102004,1,0,0:0:0:0:
|
||||
160,192,102091,2,0,L|296:192,1,105
|
||||
416,192,102436,2,0,L|256:192,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
336,192,102780,2,0,L|400:192,1,52.5
|
||||
288,192,102953,2,0,L|224:192,1,52.5
|
||||
80,192,103125,6,0,L|184:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
464,192,103470,1,2,0:0:0:0:
|
||||
436,147,103556,1,0,0:0:0:0:
|
||||
396,113,103642,1,0,0:0:0:0:
|
||||
350,89,103728,1,0,0:0:0:0:
|
||||
300,73,103815,1,2,0:0:0:0:
|
||||
248,66,103901,1,0,0:0:0:0:
|
||||
195,67,103987,1,0,0:0:0:0:
|
||||
145,81,104073,1,0,0:0:0:0:
|
||||
110,118,104159,1,2,0:0:0:0:
|
||||
124,167,104245,1,0,0:0:0:0:
|
||||
158,207,104332,1,0,0:0:0:0:
|
||||
198,241,104418,1,0,0:0:0:0:
|
||||
360,192,104504,5,4,0:0:0:0:
|
||||
407,174,104590,1,0,0:0:0:0:
|
||||
426,127,104676,1,0,0:0:0:0:
|
||||
403,82,104762,1,0,0:0:0:0:
|
||||
208,192,104849,2,0,L|104:192,1,105
|
||||
384,192,105194,2,0,P|476:146|432:56,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
160,192,105711,1,0,0:0:0:0:
|
||||
456,192,105884,5,2,0:0:0:0:
|
||||
456,192,106142,1,0,0:0:0:0:
|
||||
272,192,106229,1,2,0:0:0:0:
|
||||
220,180,106315,1,0,0:0:0:0:
|
||||
170,164,106401,1,0,0:0:0:0:
|
||||
123,141,106487,1,0,0:0:0:0:
|
||||
91,101,106573,1,2,0:0:0:0:
|
||||
125,65,106660,1,0,0:0:0:0:
|
||||
175,51,106746,1,0,0:0:0:0:
|
||||
227,45,106832,1,0,0:0:0:0:
|
||||
280,42,106918,1,2,0:0:0:0:
|
||||
332,42,107004,1,0,0:0:0:0:
|
||||
385,44,107091,1,0,0:0:0:0:
|
||||
437,47,107177,1,0,0:0:0:0:
|
||||
240,192,107263,5,4,0:0:0:0:
|
||||
168,192,107349,1,0,0:0:0:0:
|
||||
216,192,107436,1,0,0:0:0:0:
|
||||
280,192,107522,1,0,0:0:0:0:
|
||||
440,192,107608,2,0,L|336:192,1,105
|
||||
32,192,107953,2,0,P|64:112|176:64,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
112,192,108470,1,0,0:0:0:0:
|
||||
384,192,108642,5,2,0:0:0:0:
|
||||
480,192,108815,2,0,L|424:192,1,52.5
|
||||
256,192,108987,1,2,0:0:0:0:
|
||||
200,192,109073,1,0,0:0:0:0:
|
||||
144,192,109159,1,0,0:0:0:0:
|
||||
98,192,109245,1,0,0:0:0:0:
|
||||
256,192,109332,1,2,0:0:0:0:
|
||||
308,192,109418,1,0,0:0:0:0:
|
||||
361,192,109504,1,0,0:0:0:0:
|
||||
413,192,109590,1,0,0:0:0:0:
|
||||
256,192,109677,1,2,0:0:0:0:
|
||||
16,192,109849,2,0,L|80:192,1,52.5
|
||||
256,192,110022,6,0,L|144:192,1,105,4|0,0:0|0:0,0:0:0:0:
|
||||
100,185,110280,1,0,0:0:0:0:
|
||||
67,146,110366,1,2,0:0:0:0:
|
||||
70,95,110452,1,0,0:0:0:0:
|
||||
107,59,110538,1,0,0:0:0:0:
|
||||
159,59,110625,1,0,0:0:0:0:
|
||||
328,192,110711,1,2,0:0:0:0:
|
||||
373,169,110797,1,0,0:0:0:0:
|
||||
382,119,110883,1,0,0:0:0:0:
|
||||
347,82,110969,1,0,0:0:0:0:
|
||||
256,192,111056,1,2,0:0:0:0:
|
||||
203,192,111142,1,0,0:0:0:0:
|
||||
151,192,111228,1,0,0:0:0:0:
|
||||
304,192,111315,1,0,0:0:0:0:
|
||||
464,192,111401,5,4,0:0:0:0:
|
||||
256,192,111573,12,0,112780,0:0:0:0:
|
||||
224,192,113125,6,0,L|448:192,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
16,192,113815,1,2,0:0:0:0:
|
||||
480,192,114160,6,0,L|152:192,1,315,2|0,0:0|0:0,0:0:0:0:
|
||||
32,192,114849,2,0,L|256:192,1,210,2|0,0:0|0:0,0:0:0:0:
|
||||
480,192,115539,2,0,B|360:96|136:104|152:200|112:288|112:288,2,420,2|2|2,0:0|0:0|0:0,0:0:0:0:
|
||||
400,192,117091,5,0,0:0:0:0:
|
||||
347,192,117177,1,0,0:0:0:0:
|
||||
295,192,117263,1,2,0:0:0:0:
|
||||
224,192,117349,1,0,0:0:0:0:
|
||||
62,192,117436,2,0,L|126:192,1,52.5
|
||||
277,192,117608,1,4,0:0:0:0:
|
||||
96,192,117953,2,0,P|16:120|32:96,1,157.5
|
||||
256,192,118298,6,0,P|360:80|328:48,1,236.250009012223,4|0,0:0|0:0,0:0:0:0:
|
||||
176,192,118642,1,8,0:0:0:0:
|
||||
440,192,118815,2,0,L|496:192,1,52.5
|
||||
336,192,118987,2,0,L|280:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
440,192,119160,2,0,L|496:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,119332,1,8,0:0:0:0:
|
||||
192,192,119418,2,0,L|280:128,1,105
|
||||
128,192,119677,5,2,0:0:0:0:
|
||||
416,192,119849,2,0,L|468:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
264,192,120022,2,0,L|320:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
464,192,120194,2,0,L|408:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
264,192,120367,2,0,L|320:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
488,192,120539,2,0,L|432:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,120711,2,0,L|216:192,1,62.9999980773926,8|0,0:0|0:0,0:0:0:0:
|
||||
65,192,120884,2,0,L|16:152,1,62.9999980773926,2|0,0:0|0:0,0:0:0:0:
|
||||
264,192,121056,6,0,P|344:120|336:80,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,121401,1,8,0:0:0:0:
|
||||
56,192,121573,1,0,0:0:0:0:
|
||||
328,192,121746,2,0,L|448:192,1,105,2|2,0:0|0:0,0:0:0:0:
|
||||
160,192,122091,1,8,0:0:0:0:
|
||||
186,192,122134,1,0,0:0:0:0:
|
||||
212,192,122177,1,0,0:0:0:0:
|
||||
238,192,122220,1,0,0:0:0:0:
|
||||
265,192,122263,1,0,0:0:0:0:
|
||||
16,192,122436,6,0,L|128:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
384,192,122780,2,0,L|272:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
16,192,123125,1,2,0:0:0:0:
|
||||
160,192,123298,1,2,0:0:0:0:
|
||||
160,192,123384,1,2,0:0:0:0:
|
||||
16,192,123470,1,8,0:0:0:0:
|
||||
288,192,123642,1,2,0:0:0:0:
|
||||
16,192,123815,6,0,L|128:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
384,192,124160,1,8,0:0:0:0:
|
||||
240,192,124332,1,0,0:0:0:0:
|
||||
496,192,124504,1,2,0:0:0:0:
|
||||
344,192,124591,1,2,0:0:0:0:
|
||||
192,192,124677,1,2,0:0:0:0:
|
||||
40,192,124763,1,2,0:0:0:0:
|
||||
344,192,124849,2,0,L|424:192,1,78.7500030040742,8|0,0:0|0:0,0:0:0:0:
|
||||
192,192,125022,2,0,L|136:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
336,192,125194,6,0,P|432:152|432:96,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
280,192,125539,2,0,L|200:192,1,78.7500030040742,8|0,0:0|0:0,0:0:0:0:
|
||||
56,192,125711,2,0,L|0:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,125884,2,0,L|257:192,1,78.7500030040742,2|0,0:0|0:0,0:0:0:0:
|
||||
400,192,126056,2,0,L|456:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,126229,2,0,L|208:192,1,78.7500030040742,8|0,0:0|0:0,0:0:0:0:
|
||||
56,192,126401,2,0,L|56:136,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,126573,6,0,P|208:136|136:176,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
288,192,126918,1,8,0:0:0:0:
|
||||
32,192,127091,2,0,L|32:128,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
176,192,127263,1,2,0:0:0:0:
|
||||
320,192,127349,1,2,0:0:0:0:
|
||||
176,192,127436,1,2,0:0:0:0:
|
||||
424,192,127608,2,0,L|424:88,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
152,192,127953,6,0,L|40:192,1,105,8|2,0:0|0:0,0:0:0:0:
|
||||
360,192,128298,2,0,L|472:192,1,105,8|2,0:0|0:0,0:0:0:0:
|
||||
128,192,128642,1,2,0:0:0:0:
|
||||
280,192,128729,1,2,0:0:0:0:
|
||||
424,192,128815,1,2,0:0:0:0:
|
||||
368,192,128901,1,2,0:0:0:0:
|
||||
192,192,128987,2,0,P|104:112|120:72,1,157.5,8|0,0:0|0:0,0:0:0:0:
|
||||
320,192,129332,6,0,P|408:112|392:72,1,157.5,6|0,0:0|0:0,0:0:0:0:
|
||||
216,192,129677,2,0,L|80:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
400,192,130022,2,0,L|456:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
304,192,130194,2,0,L|224:192,1,78.7500030040742,2|0,0:0|0:0,0:0:0:0:
|
||||
64,192,130367,2,0,L|112:160,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
272,192,130539,2,0,L|208:192,1,52.5
|
||||
64,192,130711,6,0,L|120:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
272,192,130884,2,0,L|352:192,1,78.7500030040742,2|0,0:0|0:0,0:0:0:0:
|
||||
496,192,131056,2,0,P|453:151|352:144,1,157.5,8|0,0:0|0:0,0:0:0:0:
|
||||
128,192,131401,1,0,0:0:0:0:
|
||||
102,192,131444,1,0,0:0:0:0:
|
||||
79,180,131487,1,0,0:0:0:0:
|
||||
65,158,131530,1,0,0:0:0:0:
|
||||
64,132,131573,1,0,0:0:0:0:
|
||||
77,109,131616,1,0,0:0:0:0:
|
||||
99,96,131659,1,0,0:0:0:0:
|
||||
125,95,131702,1,0,0:0:0:0:
|
||||
232,192,131746,1,8,0:0:0:0:
|
||||
328,192,131918,1,2,0:0:0:0:
|
||||
48,192,132091,6,0,P|112:112|176:104,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
328,192,132436,1,8,0:0:0:0:
|
||||
64,192,132608,1,2,0:0:0:0:
|
||||
480,192,132780,1,2,0:0:0:0:
|
||||
328,192,132867,1,0,0:0:0:0:
|
||||
176,192,132953,1,2,0:0:0:0:
|
||||
24,192,133039,1,0,0:0:0:0:
|
||||
176,192,133125,1,8,0:0:0:0:
|
||||
328,192,133212,1,0,0:0:0:0:
|
||||
176,192,133298,1,2,0:0:0:0:
|
||||
24,192,133384,1,0,0:0:0:0:
|
||||
256,192,133470,5,0,0:0:0:0:
|
||||
292,206,133513,1,0,0:0:0:0:
|
||||
330,200,133556,1,0,0:0:0:0:
|
||||
361,176,133599,1,0,0:0:0:0:
|
||||
375,140,133642,1,0,0:0:0:0:
|
||||
370,101,133685,1,0,0:0:0:0:
|
||||
346,70,133728,1,0,0:0:0:0:
|
||||
192,192,133815,2,0,L|88:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
368,192,134160,1,0,0:0:0:0:
|
||||
405,183,134203,1,0,0:0:0:0:
|
||||
434,157,134246,1,0,0:0:0:0:
|
||||
448,120,134289,1,0,0:0:0:0:
|
||||
442,82,134332,1,0,0:0:0:0:
|
||||
288,192,134418,1,0,0:0:0:0:
|
||||
136,192,134504,2,0,P|144:136|192:112,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
448,192,134849,6,0,P|480:120|416:80,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
208,192,135194,1,8,0:0:0:0:
|
||||
80,192,135367,1,2,0:0:0:0:
|
||||
352,192,135539,2,0,L|296:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
155,192,135711,2,0,L|211:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
384,192,135884,2,0,L|328:192,1,52.5,8|0,0:0|0:0,0:0:0:0:
|
||||
187,192,136056,2,0,L|243:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
384,192,136229,6,0,P|440:136|424:112,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
144,192,136573,1,8,0:0:0:0:
|
||||
48,192,136746,2,0,L|104:192,1,52.5
|
||||
256,192,136918,2,0,L|296:192,7,26.25,2|0|0|0|0|0|0|0,0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
160,192,137263,2,0,L|48:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
368,192,137608,6,0,P|448:112|432:88,1,157.5,2|0,0:0|0:0,0:0:0:0:
|
||||
256,192,137953,2,0,L|144:192,1,105,8|0,0:0|0:0,0:0:0:0:
|
||||
480,192,138298,1,2,0:0:0:0:
|
||||
328,192,138384,1,2,0:0:0:0:
|
||||
176,192,138470,1,2,0:0:0:0:
|
||||
96,192,138556,1,2,0:0:0:0:
|
||||
256,192,138642,1,8,0:0:0:0:
|
||||
400,192,138729,1,0,0:0:0:0:
|
||||
216,192,138815,2,0,L|152:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
352,192,138987,6,0,L|496:120,3,157.500006008148,2|0|0|0,0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
192,192,139677,2,0,L|56:192,1,125.999996154785,2|0,0:0|0:0,0:0:0:0:
|
||||
368,192,140022,2,0,L|256:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
16,192,140367,5,2,0:0:0:0:
|
||||
48,151,140453,1,0,0:0:0:0:
|
||||
94,125,140539,1,0,0:0:0:0:
|
||||
145,118,140625,1,0,0:0:0:0:
|
||||
304,192,140711,2,0,L|416:192,1,105
|
||||
120,192,141056,2,0,P|48:112|104:64,1,157.5,4|0,0:0|0:0,0:0:0:0:
|
||||
160,192,141401,1,0,0:0:0:0:
|
||||
212,192,141487,1,0,0:0:0:0:
|
||||
265,192,141573,1,0,0:0:0:0:
|
||||
317,192,141659,1,0,0:0:0:0:
|
||||
160,192,141746,5,2,0:0:0:0:
|
||||
212,192,141832,1,0,0:0:0:0:
|
||||
265,192,141918,1,0,0:0:0:0:
|
||||
317,192,142004,1,0,0:0:0:0:
|
||||
160,192,142091,2,0,L|56:192,1,105
|
||||
317,192,142436,2,0,P|432:128|432:80,1,157.5,4|0,0:0|0:0,0:0:0:0:
|
||||
256,192,142780,2,0,L|179:192,1,52.5
|
||||
152,192,142953,2,0,L|216:192,1,52.5
|
||||
376,192,143125,5,2,0:0:0:0:
|
||||
425,182,143211,1,0,0:0:0:0:
|
||||
448,137,143297,1,0,0:0:0:0:
|
||||
426,91,143383,1,0,0:0:0:0:
|
||||
256,192,143470,2,0,L|360:192,1,105,2|0,0:0|0:0,0:0:0:0:
|
||||
88,192,143815,2,0,P|32:112|72:72,1,157.5,4|0,0:0|0:0,0:0:0:0:
|
||||
216,192,144160,2,0,L|280:192,1,52.5,2|0,0:0|0:0,0:0:0:0:
|
||||
112,192,144332,2,0,L|48:192,1,52.5
|
||||
288,192,144504,5,2,0:0:0:0:
|
||||
448,192,144677,1,0,0:0:0:0:
|
||||
471,146,144763,1,0,0:0:0:0:
|
||||
464,94,144849,1,2,0:0:0:0:
|
||||
428,57,144935,1,2,0:0:0:0:
|
||||
377,47,145022,1,2,0:0:0:0:
|
||||
330,69,145108,1,2,0:0:0:0:
|
||||
64,192,145194,1,4,0:0:0:0:
|
||||
296,192,145884,5,0,0:0:0:0:
|
||||
128,192,146229,1,2,0:0:0:0:
|
||||
280,192,146573,1,0,0:0:0:0:
|
||||
56,192,146918,1,2,0:0:0:0:
|
||||
480,192,147263,5,2,0:0:0:0:
|
||||
288,192,147780,1,0,0:0:0:0:
|
||||
432,192,147953,1,2,0:0:0:0:
|
||||
160,192,148298,1,0,0:0:0:0:
|
||||
472,192,148642,5,2,0:0:0:0:
|
||||
128,192,149332,1,2,0:0:0:0:
|
||||
488,192,150022,1,2,0:0:0:0:
|
||||
16,192,150367,5,2,0:0:0:0:
|
||||
488,192,150711,1,4,0:0:0:0:
|
31
pp/catch_the_pp/sample.py
Normal file
31
pp/catch_the_pp/sample.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from .osu_parser.beatmap import Beatmap
|
||||
from .osu.ctb.difficulty import Difficulty
|
||||
from .ppCalc import calculate_pp
|
||||
|
||||
if len(sys.argv) <= 1:
|
||||
beatmap = Beatmap(os.path.dirname(os.path.realpath(__file__)) + "/test.osu") # Yes... this be my test file (Will remove when project is done)
|
||||
else:
|
||||
beatmap = Beatmap(sys.argv[1])
|
||||
|
||||
if len(sys.argv) >= 3:
|
||||
mods = int(sys.argv[2])
|
||||
else:
|
||||
mods = 0
|
||||
|
||||
difficulty = Difficulty(beatmap, mods)
|
||||
print("Calculation:")
|
||||
print("Stars: {}, PP: {}, MaxCombo: {}\n".format(
|
||||
difficulty.star_rating, calculate_pp(difficulty, 1, beatmap.max_combo, 0), beatmap.max_combo
|
||||
))
|
||||
|
||||
"""
|
||||
m = {"NOMOD": 0, "EASY": 2, "HIDDEN": 8, "HARDROCK": 16, "DOUBLETIME": 64, "HALFTIME": 256, "FLASHLIGHT": 1024}
|
||||
for key in m.keys():
|
||||
difficulty = Difficulty(beatmap, m[key])
|
||||
print("Mods: {}".format(key))
|
||||
print("Stars: {}".format(difficulty.star_rating))
|
||||
print("PP: {}\n".format(calculate_pp(difficulty, 1, beatmap.max_combo, 0)))
|
||||
"""
|
16
pp/catch_the_pp/setup.py
Normal file
16
pp/catch_the_pp/setup.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from distutils.core import setup
|
||||
from distutils.extension import Extension
|
||||
from Cython.Build import cythonize
|
||||
import os
|
||||
|
||||
extensions = []
|
||||
for root, dirs, files in os.walk(os.getcwd()):
|
||||
for file in files:
|
||||
if file.endswith(".pyx"):
|
||||
file_path = os.path.relpath(os.path.join(root, file))
|
||||
extensions.append(Extension(file_path.replace("/", ".")[:-4], [file_path]))
|
||||
|
||||
setup(
|
||||
name="catch-the-pp",
|
||||
ext_modules=cythonize(extensions, nthreads=4),
|
||||
)
|
1219
pp/catch_the_pp/test.osu
Normal file
1219
pp/catch_the_pp/test.osu
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user