Initial commit

This commit is contained in:
Josh
2018-12-09 00:15:56 -05:00
commit aad3c9bb54
125 changed files with 18177 additions and 0 deletions

11
pp/oppai-ng/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
tags
*.log
*.tar.xz
*.zip
/oppai
*.json
*.obj
*.exe
*.swp
/test/test_suite
/test/oppai_test

22
pp/oppai-ng/.travis.yml Normal file
View File

@@ -0,0 +1,22 @@
language: c
matrix:
include:
- os: linux
dist: precise
- os: linux
dist: trusty
- os: osx
install: true
cache:
directories:
- test/test_suite
script:
- ./build
- cd test
- ./download_suite
- ./build
- ./oppai_test

349
pp/oppai-ng/README.md Normal file
View File

@@ -0,0 +1,349 @@
[![Build Status](https://travis-ci.org/Francesco149/oppai-ng.svg?branch=master)](https://travis-ci.org/Francesco149/oppai-ng)
difficulty and pp calculator for osu!
this is a pure C89 rewrite of
[oppai](https://github.com/Francesco149/oppai) with much lower
memory usage, smaller and easier to read codebase
executable size and better performance.
experimental taiko support is now available and appears to give
correct values for actual taiko maps. converted maps are still
unreliable due to incorrect slider conversion and might be
completely off (use ```-m1``` or ```-taiko``` to convert a std map
to taiko).
- [installing (linux)](#installing-linux)
- [installing (windows)](#installing-windows)
- [installing (osx)](#installing-osx)
- [usage](#usage)
- [implementations for other programming languages](#implementations-for-other-programming-languages)
- [oppai-ng vs old oppai](#oppai-ng-vs-old-oppai)
- [compile from source (windows)](#compile-from-source-windows)
- [using oppai as a library or making bindings](#using-oppai-as-a-library-or-making-bindings)
- [other build parameters](#other-build-parameters)
# installing (linux)
```sh
wget https://github.com/Francesco149/oppai-ng/archive/HEAD.tar.gz
tar xf HEAD.tar.gz
cd oppai-*
./build
sudo install -Dm 755 oppai /usr/bin/oppai
oppai
```
you can also grab pre-compiled standalone binaries (statically
linked against musl libc) from
[here](https://github.com/Francesco149/oppai-ng/releases) if you
are somehow too scared to run those 5 commands.
# installing (windows)
download and unzip binaries from
[here](https://github.com/Francesco149/oppai-ng/releases) and
optionally add oppai's folder to your ```PATH``` environment
variable for easy access. you can find a guide
[here](https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/)
if you don't know how.
# installing (osx)
## via homebrew
```sh
brew install --HEAD pmrowla/homebrew-tap/oppai-ng
```
Note that installing with ```--HEAD``` is recommended but not required.
Installing from homebrew will place the ```oppai``` executable in your homebrew path.
## manually
Follow the same steps as for linux but substitute ```curl -O``` for ```wget``` since wget is not distributed by default in osx.
The same caveat applies if you want to run the test suite - you will need to edit the ```download_suite``` script to use curl.
# usage
you can run oppai with no arguments to check the documentation.
here's some example usages:
```sh
oppai path/to/map.osu +HDHR 98% 500x 1xmiss
oppai path/to/map.osu 3x100
oppai path/to/map.osu 3x100 OD10
oppai path/to/map.osu -ojson
```
you can also pipe maps from standard input by setting the filename
to ```-```.
for example on linux you can do:
```sh
curl https://osu.ppy.sh/osu/774965 | oppai - +HDDT
curl https://osu.ppy.sh/osu/774965 | oppai - +HDDT 1200x 1m
```
while on windows it's a bit more verbose (powershell):
```powershell
(New-Object System.Net.WebClient).DownloadString("https://osu.ppy.sh/osu/37658") | ./oppai -
(New-Object System.Net.WebClient).DownloadString("https://osu.ppy.sh/osu/37658") | ./oppai - +HDHR
(New-Object System.Net.WebClient).DownloadString("https://osu.ppy.sh/osu/37658") | ./oppai - +HDHR 99% 600x 1m
```
I got the .osu file url from "Grab latest .osu file" on the
beatmap's page.
# implementations for other programming languages
oppai has been implemented for many other programming languages.
If you feel like making your own implementation and want it listed
here, open an issue or pull request. the requirement is that it
should pass the same test suite that oppai-ng passes.
note: these aren't just native bindings unless stated otherwise.
* [ojsama (javascript)](https://github.com/Francesco149/ojsama)
* [koohii (java)](https://github.com/Francesco149/koohii) . this
is currently being used in tillerino.
* [pyttanko (python)](https://github.com/Francesco149/pyttanko)
* [oppai5 (golang)](https://github.com/flesnuk/oppai5) (by flesnuk)
* [OppaiSharp (C#)](https://github.com/HoLLy-HaCKeR/OppaiSharp)
(by HoLLy)
# oppai-ng vs old oppai
executable size is around 7 times smaller:
```sh
$ cd ~/src/oppai
$ ./build.sh -static
$ wc -c oppai
574648 oppai
$ cd ~/src/oppai-ng
$ ./build -static
$ wc -c oppai
75512 oppai
```
oppai-ng has proper error output in whatever format you select,
while legacy oppai either gives empty output or just dies with
a plaintext error.
oppai-ng has well-defined errno style error codes that you can
check for when using it as a library or reading its output.
the same test suite runs about 45% faster on oppai-ng compared
to old oppai, also the peak resident memory size is 4 to 6 times
smaller according to various ```time -v``` runs.
```sh
$ cd ~/src/oppai
$ ./build_test.sh
$ time -v ./oppai_test
...
Command being timed: "./oppai_test"
User time (seconds): 13.89
System time (seconds): 0.10
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0m 13.99s
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 45184
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 2143
Voluntary context switches: 1
Involuntary context switches: 41
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
$ cd ~/src/oppai-ng/test/
$ ./build
$ time -v ./oppai_test
...
Command being timed: "./oppai_test"
User time (seconds): 9.09
System time (seconds): 0.06
Percent of CPU this job got: 99%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0m 9.15s
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 11840
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 304
Voluntary context switches: 1
Involuntary context switches: 39
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
```
note that when the test suite is compiled without libcurl, the
resident memory usage drops by a flat 4mb, so almost half of that
is curl.
you can expect oppai memory usage to be under 4 mb most of the time
with the raw parsed beatmap data not taking more than ~800k even
for a 15 minute marathon.
the codebase has ~3-4x less lines than legacy oppai, making it easy
to read and use as a single header library. not only it is smaller,
but it now also implements both taiko and osu, so more features
than legacy oppai.
the osu! pp and diff calc alone would be around ~3k LOC including
the cli, which would be 5x less lines than legacy oppai for the
same functionality.
```sh
$ cd ~/src/oppai
$ sloc *.cc
---------- Result ------------
Physical : 15310
Source : 14406
Comment : 301
Single-line comment : 289
Block comment : 12
Mixed : 23
Empty : 626
To Do : 11
Number of files read : 10
------------------------------
$ cd ~/src/oppai-ng
$ sloc *.c
---------- Result ------------
Physical : 4123
Source : 2906
Comment : 492
Single-line comment : 1
Block comment : 491
Mixed : 64
Empty : 811
To Do : 9
Number of files read : 2
------------------------------
```
not to mention it's C89, which will be compatible with many more
platforms and old compilers than c++98
```oppai.c``` alone is only ~2200 LOC (~1500 without comments), and
you can compile piece of it out when you don't need them.
of course, it's not as heavily tested as legacy oppai (which runs
24/7 on Tillerino's back-end), however the test suite is a very
good test that runs through ~12000 unique scores and I'm confident
this rewrite is already very stable.
# compile from source (windows)
oppai should compile even on old versions of msvc dating back to
2005, although it was only tested on msvc 2010 and higher.
have at least [microsoft c++ build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)
installed. visual studio with c/c++ support also works.
open a visual studio prompt:
```bat
cd path\to\oppai\source
build.bat
oppai
```
you can also probably set up mingw and cygwin and follow the linux
instructions instead, I'm not sure. I don't use windows.
# using oppai as a library or making bindings
the new codebase is much easier to isolate and include in your
projects.
just copy oppai.c into your project, it acts as a single-header
library.
```c
#define OPPAI_IMPLEMENTATION
#include "../oppai.c"
int main()
{
struct parser pstate;
struct beatmap map;
uint32_t mods;
struct diff_calc stars;
struct pp_calc pp;
p_init(&pstate);
p_map(&pstate, &map, stdin);
mods = MODS_HD | MODS_DT;
d_init(&stars);
d_calc(&stars, &map, mods);
printf("%g stars\n", stars.total);
b_ppv2(&map, &pp, stars.aim, stars.speed, mods);
printf("%gpp\n", pp.total);
return 0;
}
```
```sh
gcc test.c
cat /path/to/file.osu | ./a.out
```
read oppai.c, there's documentation for each function at the top.
see examples directory for detailed examples. you can also read
main.c to see how the CLI uses it.
oppai is also modular, you can define out parts of the code
that you don't use by defining any of:
```
OPPAI_NOPARSER
OPPAI_NOPP
OPPAI_NODIFFCALC
```
if you don't feel comfortable writing bindings or using oppai
from c code, you can use the -o parameter to output in json or
other parsable formats. ```examples/binary.c``` shows how to parse
the binary output.
# other build parameters
when you build the oppai cli, you can pass any of these parameters
to the build script to disable features:
* ```-DOPPAI_NOTEXT``` disables text output module
* ```-DOPPAI_NOJSON``` disables json output module
* ```-DOPPAI_NOCSV``` disables CSV output module
* ```-DOPPAI_NOBINARY``` disables binary output module
* ```-DOPPAI_DEBUG``` enables debug output module and memory usage
statistics
* ```-DOPPAI_NOSTDINT``` doesn't use ```stdint.h```, as some
machines or old compilers don't have it

24
pp/oppai-ng/UNLICENSE Normal file
View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>

11
pp/oppai-ng/build.bat Normal file
View File

@@ -0,0 +1,11 @@
@echo off
del oppai.exe >nul 2>&1
del oppai.obj >nul 2>&1
cl -D_CRT_SECURE_NO_WARNINGS=1 ^
-DNOMINMAX=1 ^
-O2 ^
-nologo -MT -Gm- -GR- -EHsc -W4 ^
main.c ^
-Feoppai.exe ^
|| EXIT /B 1

View File

@@ -0,0 +1,10 @@
#!/bin/sh
dir=$(dirname $0)
for d in $dir/docker/*
do
bn=$(basename $d)
cp $d/Dockerfile .
docker build -t "oppai-ng:$bn" .
rm Dockerfile
done

View File

@@ -0,0 +1,7 @@
$dir = Split-Path -Parent $MyInvocation.MyCommand.Definition
Push-Location "$dir"
$d = "docker/windows"
Copy-Item $d/Dockerfile .
docker build -t "oppai-ng:windows" .
Remove-Item Dockerfile
Pop-Location

34
pp/oppai-ng/cflags Normal file
View File

@@ -0,0 +1,34 @@
#!/bin/sh
cflags="-std=c89 -pedantic"
cflags="$cflags -O3"
cflags="$cflags -fno-strict-aliasing"
cflags="$cflags -Wno-variadic-macros -Wno-long-long -Wall"
cflags="$cflags -ffunction-sections -fdata-sections"
cflags="$cflags -g0 -fno-unwind-tables -s"
cflags="$cflags -fno-asynchronous-unwind-tables"
ldflags="-lm"
cflags="$cflags $CFLAGS"
ldflags="$ldflags $LDFLAGS"
cc="$CC"
if [ $(uname) = "Darwin" ]; then
cc=${cc:-clang}
else
cc=${cc:-gcc}
fi
uname -a > flags.log
echo $cc >> flags.log
echo $cflags >> flags.log
echo $ldflags >> flags.log
$cc --version >> flags.log
$cc -dumpmachine >> flags.log
export cflags="$cflags"
export ldflags="$ldflags"
export cc="$cc"

View File

@@ -0,0 +1,5 @@
FROM multiarch/alpine:x86-latest-stable
RUN apk add --no-cache musl-dev gcc git xz
WORKDIR /tmp
CMD [ "sh", "./release" ]

View File

@@ -0,0 +1,5 @@
FROM multiarch/alpine:x86_64-latest-stable
RUN apk add --no-cache musl-dev gcc git xz
WORKDIR /tmp
CMD [ "sh", "./release" ]

View File

@@ -0,0 +1,26 @@
# escape=`
# I wanted to use nanoserver but I couldn't get visual c++ build
# tools to install. the nuget visual c++ build tools package isn't
# enough to get a working compiler and manually copying msvc
# defeats the purpose of using the container to automatically
# install deps.
# unfortunately windowsservercore is a 4GB image
FROM microsoft/windowsservercore
RUN @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
# wait for vs_installer.exe, vs_installerservice.exe
# or vs_installershell.exe because choco doesn't
RUN powershell -NoProfile -InputFormat None -Command `
choco install git 7zip -y; `
choco install visualcpp-build-tools `
--version 15.0.26228.20170424 -y; `
Write-Host 'Waiting for Visual C++ Build Tools to finish'; `
Wait-Process -Name vs_installer
WORKDIR C:\oppai-ng
CMD powershell -ExecutionPolicy Bypass -Command `
Get-Location; Get-ChildItem; `
. .\vcvarsall17.ps1 x64; .\release.ps1; `
. .\vcvarsall17.ps1 x86; .\release.ps1

10
pp/oppai-ng/package Normal file
View File

@@ -0,0 +1,10 @@
#!/bin/sh
dir=$(dirname $0)
dir=$(readlink -f $dir)
prevdir=$(pwd)
cd $dir
for d in $dir/docker/*; do
docker run --rm -v $dir:/tmp oppai-ng:$(basename $d)
done
cd $prevdir

4
pp/oppai-ng/package.ps1 Normal file
View File

@@ -0,0 +1,4 @@
$dir = Split-Path -Parent $MyInvocation.MyCommand.Definition
Push-Location $dir
docker run --rm -v ${dir}:c:\oppai-ng oppai-ng:windows
Pop-Location

36
pp/oppai-ng/release Normal file
View File

@@ -0,0 +1,36 @@
#!/bin/sh
dir=$(dirname $0)
olddir=$(pwd)
cd $dir
git pull origin master
echo -e "\nCompiling and Stripping"
./build -static -no-pie || exit 1
echo -e "\nPackaging"
folder="oppai-$(./oppai -version)-"
folder="${folder}$(gcc -dumpmachine)"
mkdir -p "$folder"
mv ./oppai $folder/oppai
git archive HEAD --prefix=src/ -o "$folder"/src.tar
cd "$folder"
tar xf src.tar
cd ..
rm "$folder".tar.xz
tar -cvJf "$folder".tar.xz \
"$folder"/oppai \
"$folder"/src
echo -e "\nResult:"
tar tf "$folder".tar.xz
readelf --dynamic "$folder"/oppai
ldd "$folder"/oppai
rm -rf "$folder"
cd $olddir

42
pp/oppai-ng/release.ps1 Normal file
View File

@@ -0,0 +1,42 @@
# you must allow script execution by running
# 'Set-ExecutionPolicy RemoteSigned' in an admin powershell
# this requires vcvars to be already set (see vcvarsall17.ps1)
# 7zip is also required (choco install 7zip and add it to path)
$dir = Split-Path -Parent $MyInvocation.MyCommand.Definition
Push-Location "$dir"
git pull origin master -q
Write-Host ""
Write-Host "########################" -Foreground Yellow -Background Black
Write-Host "> Compiling and stripping" -Foreground Yellow -Background Black
cmd /c "build.bat"
Write-Host ""
Write-Host "########################" -Foreground Yellow -Background Black
Write-Host "> Packaging" -Foreground Yellow -Background Black
$folder = "oppai-" + $(.\oppai.exe -version) + "-windows-"
$clout = & cl 2>&1 | %{ "$_" }
"$clout" -match "(Microsoft.*for )([a-z0-9\-_]+)" | Out-Null
$folder = $folder + $Matches[2]
mkdir $folder
Copy-Item oppai.exe $folder
git archive HEAD --prefix=src\ -o $folder\src.zip
Set-Location $folder
&7z x src.zip
Set-Location ..
if (Test-Path "$folder.zip") {
Remove-Item "$folder.zip"
}
&7z a "$folder.zip" $folder\oppai.exe $folder\src
Write-Host ""
Write-Host "########################" -Foreground Yellow -Background Black
Write-Host "> Result:" -Foreground Yellow -Background Black
&7z l "$folder.zip"
Remove-Item $folder -Force -Recurse
Pop-Location

View File

@@ -0,0 +1,10 @@
#!/bin/sh
if [ $(find test_suite 2>/dev/null | tail -n +2 | wc -l) = "0" ]
then
wget http://www.hnng.moe/stuff/test_suite_20180515.tar.xz \
|| exit 1
tar xf test_suite_20180515.tar.xz || exit 1
else
echo "using existing test_suite"
fi

254
pp/oppai-ng/test/gentest.py Normal file
View File

@@ -0,0 +1,254 @@
#!/usr/bin/env python
import sys
import os
import time
import json
import traceback
import argparse
import hashlib
if sys.version_info[0] < 3:
# hack to force utf-8
reload(sys)
sys.setdefaultencoding('utf-8')
try:
import httplib
except ImportError:
import http.client as httplib
try:
import urllib
except ImportError:
import urllib.parse as urllib
# -------------------------------------------------------------------------
parser = argparse.ArgumentParser(
description = (
'generates the oppai test suite. outputs c++ code to ' +
'stdout and the json dump to a file.'
)
)
parser.add_argument(
'-key',
default = None,
help = (
'osu! api key. required if -input-file is not present. ' +
'can also be specified through the OSU_API_KEY ' +
'environment variable'
)
)
parser.add_argument(
'-output-file',
default = 'test_suite.json',
help = 'dumps json to this file'
)
parser.add_argument(
'-input-file',
default = None,
help = (
'loads test suite from this json file instead of '
'fetching it from osu api. if set to "-", json will be '
'read from standard input'
)
)
args = parser.parse_args()
if args.key == None and 'OSU_API_KEY' in os.environ:
args.key = os.environ['OSU_API_KEY']
# -------------------------------------------------------------------------
osu_treset = time.time() + 60
osu_ncalls = 0
def osu_get(conn, endpoint, paramsdict=None):
# GETs /api/endpoint?paramsdict&k=args.key from conn
# return json object, exits process on api errors
global osu_treset, osu_ncalls, args
sys.stderr.write('%s %s\n' % (endpoint, str(paramsdict)))
paramsdict['k'] = args.key
path = '/api/%s?%s' % (endpoint, urllib.urlencode(paramsdict))
while True:
while True:
if time.time() >= osu_treset:
osu_ncalls = 0
osu_treset = time.time() + 60
sys.stderr.write('\napi ready\n')
if osu_ncalls < 60:
break
else:
sys.stderr.write('waiting for api cooldown...\r')
time.sleep(1)
try:
conn.request('GET', path)
osu_ncalls += 1
r = conn.getresponse()
raw = ''
while True:
try:
raw += r.read()
break
except httplib.IncompleteRead as e:
raw += e.partial
j = json.loads(raw)
if 'error' in j:
sys.stderr.write('%s\n' % j['error'])
sys.exit(1)
return j
except (httplib.HTTPException, ValueError) as e:
sys.stderr.write('%s\n' % (traceback.format_exc()))
try:
# prevents exceptions on next request if the
# response wasn't previously read due to errors
conn.getresponse().read()
except httplib.HTTPException:
pass
time.sleep(5)
def gen_modstr(bitmask):
# generates c++ code for a mod combination's bitmask
mods = []
allmods = {
(1<< 0, 'nf'), (1<< 1, 'ez'), (1<< 2, 'td'), (1<< 3, 'hd'),
(1<< 4, 'hr'), (1<< 6, 'dt'), (1<< 8, 'ht'),
(1<< 9, 'nc'), (1<<10, 'fl'), (1<<12, 'so')
}
for bit, string in allmods:
if bitmask & bit != 0:
mods.append(string)
if len(mods) == 0:
return 'nomod'
return ' | '.join(mods)
# -------------------------------------------------------------------------
if args.key == None:
sys.stderr.write(
'please set OSU_API_KEY or pass it as a parameter\n'
)
sys.exit(1)
scores = []
if args.input_file == None:
# fetch a fresh test suite from osu api
top_players = [
124493, 4787150, 2558286, 1777162, 2831793, 50265
]
osu = httplib.HTTPSConnection('osu.ppy.sh')
for u in top_players:
params = { 'u': u, 'limit': 100, 'type': 'id' }
scores += osu_get(osu, 'get_user_best', params)
params = { 'm': 0, 'since': '2015-11-26' }
maps = osu_get(osu, 'get_beatmaps', params)
for m in maps:
params = { 'b': m['beatmap_id'] }
map_scores = osu_get(osu, 'get_scores', params)
if len(map_scores) == 0:
sys.stderr.write('W: map has no scores???\n')
continue
# note: api also returns qualified and loved, so ignore
# maps that don't have pp in rankings
if not 'pp' in map_scores[0]:
sys.stderr.write('W: ignoring loved/qualified map\n')
continue
for s in map_scores:
s['beatmap_id'] = m['beatmap_id']
scores += map_scores
with open(args.output_file, 'w+') as f:
f.write(json.dumps(scores))
else:
# load existing test suite from json file
with open(args.input_file, 'r') as f:
scores = json.loads(f.read())
print('/* this code was automatically generated by gentest.py */')
print('')
# make code a little nicer by shortening mods
allmods = {
'nf', 'ez', 'td', 'hd', 'hr', 'dt', 'ht', 'nc', 'fl', 'so', 'nomod'
}
for mod in allmods:
print('#define %s MODS_%s' % (mod, mod.upper()))
print('''
struct score
{
uint32_t id;
uint16_t max_combo;
uint16_t n300, n100, n50, nmiss;
uint32_t mods;
double pp;
};
struct score const suite[] =
{''')
seen_hashes = []
for s in scores:
# why is every value returned by osu api a string?
line = (
' { %s, %s, %s, %s, %s, %s, %s, %s },' %
(
s['beatmap_id'], s['maxcombo'], s['count300'],
s['count100'], s['count50'], s['countmiss'],
gen_modstr(int(s['enabled_mods'])), s['pp']
)
)
# don't include identical scores by different people
s = hashlib.sha1(line).digest()
if s in seen_hashes:
continue
print(line)
seen_hashes.append(s)
print('};\n')
for mod in allmods:
print('#undef %s' % (mod))

View File

@@ -0,0 +1,15 @@
# https://stackoverflow.com/questions/2124753/how-can-i-use-powershell-with-the-visual-studio-command-prompt
param (
[string]$arch = "amd64"
)
Push-Location "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
cmd /c "VsDevCmd.bat -arch=$arch&set" |
ForEach-Object {
if ($_ -match "=") {
$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
}
}
Pop-Location
Write-Host "`nVisual Studio 2017 Command Prompt variables set." -ForegroundColor Yellow