Fix line-endings; Increase portability; Add speedtyper.py

This commit is contained in:
olari
2019-05-26 23:05:28 +03:00
parent 661a5984a3
commit 63a1b4f501
33 changed files with 1447 additions and 1341 deletions

View File

@@ -1,25 +1,22 @@
#!/bin/bash #!/usr/bin/env bash
# Discard on use # Increase nice and rtprio limits.
rm $0 local user=$(cut -d' ' -f1 <<< $(who))
echo "$user - nice -20
# Increase nice and rtprio limits. $user - rtprio 99" | sudo tee --append /etc/security/limits.conf
local user=$(cut -d' ' -f1 <<< $(who))
echo "$user - nice -20 # Create pulseaudio config.
$user - rtprio 99" | sudo tee --append /etc/security/limits.conf sudo mkdir -p /etc/pulse/daemon.conf.d/
echo "high-priority = yes
# Create pulseaudio config. nice-level = -15
sudo mkdir -p /etc/pulse/daemon.conf.d/
echo "high-priority = yes realtime-scheduling = yes
nice-level = -15 realtime-priority = 50
realtime-scheduling = yes resample-method = speex-float-0
realtime-priority = 50
default-fragments = 5
resample-method = speex-float-0 default-fragment-size-msec = 2" | sudo tee --append /etc/pulse/daemon.conf.d/10-lower-latency.conf
default-fragments = 5 # Disable timer-based scheduling.
default-fragment-size-msec = 2" | sudo tee --append /etc/pulse/daemon.conf.d/10-lower-latency.conf sudo sed -i 's/load-module module-udev-det*/load-module module-udev-detect tsched=0/g' /etc/pulse/default.pa
# Disable timer-based scheduling.
sudo sed -i 's/load-module module-udev-det*/load-module module-udev-detect tsched=0/g' /etc/pulse/default.pa

View File

@@ -1,12 +1,9 @@
#!/bin/bash #!/usr/bin/env bash
# Discard on use sudo mkdir -p /etc/X11/xorg.conf.d/
rm $0 echo 'Section "InputClass"
Identifier "My Mouse"
sudo mkdir -p /etc/X11/xorg.conf.d/ Driver "libinput"
echo 'Section "InputClass" MatchIsPointer "yes"
Identifier "My Mouse" Option "AccelProfile" "flat"
Driver "libinput" EndSection' | sudo tee --append /etc/X11/xorg.conf.d/50-mouse-acceleration.conf
MatchIsPointer "yes"
Option "AccelProfile" "flat"
EndSection' | sudo tee --append /etc/X11/xorg.conf.d/50-mouse-acceleration.conf

View File

@@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
USERNAME="" USERNAME=""
PASSWORD="" PASSWORD=""

View File

@@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
KEYMAP="dvorak-programmer" KEYMAP="dvorak-programmer"
DEVICE="/dev/sda" DEVICE="/dev/sda"

View File

@@ -1,43 +1,40 @@
#!/bin/bash #!/usr/bin/env bash
# Discard on use # https://blog.thepoon.fr/osuLinuxAudioLatency/
rm $0 sudo pacman-key --keyserver hkps://hkps.pool.sks-keyservers.net -r C0E7D0CDB72FBE95
sudo pacman-key --keyserver hkps://hkps.pool.sks-keyservers.net --lsign-key C0E7D0CDB72FBE95
# https://blog.thepoon.fr/osuLinuxAudioLatency/
sudo pacman-key --keyserver hkps://hkps.pool.sks-keyservers.net -r C0E7D0CDB72FBE95 echo "[thepoon]
sudo pacman-key --keyserver hkps://hkps.pool.sks-keyservers.net --lsign-key C0E7D0CDB72FBE95 Server = https://archrepo.thepoon.fr
Server = https://mirrors.celianvdb.fr/archlinux/thepoon
echo "[thepoon] " | sudo tee --append /etc/pacman.conf
Server = https://archrepo.thepoon.fr
Server = https://mirrors.celianvdb.fr/archlinux/thepoon sudo pacman -S wine-osu winetricks
" | sudo tee --append /etc/pacman.conf
mkdir ~/osu!
sudo pacman -S wine-osu winetricks cd ~/osu!
wget https://m1.ppy.sh/r/osu\!install.exe
mkdir ~/osu!
cd ~/osu! export WINEPREFIX="$HOME/.wine_osu"
wget https://m1.ppy.sh/r/osu\!install.exe export WINEARCH=win32
export WINEPREFIX="$HOME/.wine_osu" winetricks dotnet40 &
export WINEARCH=win32
cat <<EOF > ~/osu!/start.sh
winetricks dotnet40 & #!/bin/sh
cat <<EOF > ~/osu!/start.sh export WINEPREFIX="$HOME/.wine_osu"
#!/bin/sh export STAGING_AUDIO_DURATION=8000
export PATH=/opt/wine-osu/bin:$PATH
export WINEPREFIX="$HOME/.wine_osu"
export STAGING_AUDIO_DURATION=8000 cd ~/osu!
export PATH=/opt/wine-osu/bin:$PATH wine osu!.exe "$@"
EOF
cd ~/osu!
wine osu!.exe "$@" cat <<EOF > ~/osu!/kill.sh
EOF #!/bin/sh
cat <<EOF > ~/osu!/kill.sh export WINEPREFIX="$HOME/.wine_osu"
#!/bin/sh
wineserver -k
export WINEPREFIX="$HOME/.wine_osu" EOF
wineserver -k
EOF

View File

@@ -1,10 +1,7 @@
#!/bin/bash #!/usr/bin/env bash
# Discard on use echo "[multilib]
rm $0 Include = /etc/pacman.d/mirrorlist
" | sudo tee --append /etc/pacman.conf
echo "[multilib]
Include = /etc/pacman.d/mirrorlist sudo pacman -S steam steam-native-runtime
" | sudo tee --append /etc/pacman.conf
sudo pacman -S steam steam-native-runtime

View File

@@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
#yay -S yaru-gtk-theme yaru-sound-theme gnome-shell-extension-ubuntu-dock #yay -S yaru-gtk-theme yaru-sound-theme gnome-shell-extension-ubuntu-dock
#yay -S yaru-icon-theme # needs to be installed seperately for some reason #yay -S yaru-icon-theme # needs to be installed seperately for some reason

View File

@@ -1,43 +1,43 @@
#include <Windows.h> #include <Windows.h>
#include <cstdio> #include <cstdio>
#include <cmath> #include <cmath>
#include <tuple> #include <tuple>
constexpr auto num_points = 10; constexpr auto num_points = 10;
constexpr auto sleep_msec = 1; constexpr auto sleep_msec = 1;
constexpr auto radius = 100.0f; constexpr auto radius = 100.0f;
int main() { int main() {
const auto window_handle = FindWindow(nullptr, "osu!"); const auto window_handle = FindWindow(nullptr, "osu!");
if (!window_handle) { if (!window_handle) {
printf("FATAL: Could not find osu!. (0x%X)\n", GetLastError()); printf("FATAL: Could not find osu!. (0x%X)\n", GetLastError());
return -1; return -1;
} }
auto get_desired_pos = [&]() -> std::tuple<int, int> { auto get_desired_pos = [&]() -> std::tuple<int, int> {
static auto counter = 0; static auto counter = 0;
counter++; counter++;
RECT rect; RECT rect;
GetWindowRect(window_handle, &rect); GetWindowRect(window_handle, &rect);
const auto center_x = rect.left + (rect.right - rect.left) / 2; const auto center_x = rect.left + (rect.right - rect.left) / 2;
const auto center_y = rect.top + (rect.bottom - rect.top) / 2; const auto center_y = rect.top + (rect.bottom - rect.top) / 2;
const auto angle = 3.1415926f * 2.0f * (float)counter / (float)num_points; const auto angle = 3.1415926f * 2.0f * (float)counter / (float)num_points;
if (counter > num_points) { if (counter > num_points) {
counter = 0; counter = 0;
} }
return { center_x + radius * sin(angle), center_y + radius * cos(angle) }; return { center_x + radius * sin(angle), center_y + radius * cos(angle) };
}; };
while (!GetAsyncKeyState(VK_DELETE)) { while (!GetAsyncKeyState(VK_DELETE)) {
if (GetAsyncKeyState('P')) { if (GetAsyncKeyState('P')) {
std::apply(SetCursorPos, get_desired_pos()); std::apply(SetCursorPos, get_desired_pos());
} }
Sleep(sleep_msec); Sleep(sleep_msec);
} }
} }

View File

@@ -1,33 +1,34 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# bulk file renamer that you interface with using intermediary text file.
# bulk file renamer that you interface with using intermediary text file.
import os
import os
def setup_file():
files = open('files.txt', 'w') def setup_file():
files = open('files.txt', 'w')
for file in os.listdir('.'):
files.write(file + '\n') for file in os.listdir('.'):
files.write(file + '\n')
def rename_files():
new_names = open('files.txt', 'r') def rename_files():
new_names = open('files.txt', 'r')
for file in os.listdir('.'):
new_name = str(new_names.readline()).rstrip('\n') for file in os.listdir('.'):
new_name = str(new_names.readline()).rstrip('\n')
if (new_name == file) or new_name == "files.txt":
continue if (new_name == file) or new_name == "files.txt":
continue
os.rename(file, new_name)
os.rename(file, new_name)
print("bulk renamer by Olari.\n")
print("bulk renamer by Olari.\n")
print("Generating files.txt")
print("Modify it to rename files\n") print("Generating files.txt")
setup_file() print("Modify it to rename files\n")
setup_file()
input("Waiting for input...\n")
input("Waiting for input...\n")
print("Renaming files")
rename_files() print("Renaming files")
rename_files()

View File

@@ -1,26 +1,27 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# deadsimple discord bot
# deadsimple discord bot
import discord
import asyncio import discord
import asyncio
client = discord.Client()
client = discord.Client()
async def task():
await client.wait_until_ready() async def task():
await client.wait_until_ready()
while not client.is_closed:
server = client.get_channel('channel id') while not client.is_closed:
await client.send_message(server, 'message') server = client.get_channel('channel id')
await asyncio.sleep(60) # time to sleep await client.send_message(server, 'message')
await asyncio.sleep(60) # time to sleep
@client.event
async def on_ready(): @client.event
print('Logged in as') async def on_ready():
print(client.user.name) print('Logged in as')
print(client.user.id) print(client.user.name)
print('------') print(client.user.id)
print('------')
client.loop.create_task(task())
client.run('username', 'password') client.loop.create_task(task())
client.run('username', 'password')

View File

@@ -1,257 +1,257 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# overly complicated flac reencoder originally written for the big touhou music torrent on nyaa.si # overly complicated flac reencoder originally written for the big touhou music torrent on nyaa.si
# contains example of process calling and multithreading # contains example of process calling and multithreading
# not recommended to use (probably destructive) # not recommended to use (probably destructive)
import os, re, time import os, re, time
import subprocess import subprocess
import wave import wave
from queue import Queue from queue import Queue
from threading import Thread from threading import Thread
f = open("errlog", "w", encoding="UTF-8") f = open("errlog", "w", encoding="UTF-8")
def remove_if_exists(filename): def remove_if_exists(filename):
if os.path.exists(filename): if os.path.exists(filename):
os.remove(filename) os.remove(filename)
def opus_enc(queue, split_track_filename, track, quality=140.0): def opus_enc(queue, split_track_filename, track, quality=140.0):
subprocess.call([ subprocess.call([
'opusenc', 'opusenc',
'--vbr', '--vbr',
'--bitrate', str(quality), '--bitrate', str(quality),
#'--comp', 10, #default #'--comp', 10, #default
#'--framesize', '60', # default 20 #'--framesize', '60', # default 20
'--artist', track.performer, '--artist', track.performer,
'--comment', 'tracknumber={}'.format(track.index), '--comment', 'tracknumber={}'.format(track.index),
'--title', track.title, '--title', track.title,
'--date', track.cd_date, '--date', track.cd_date,
'--genre', track.cd_genre, '--genre', track.cd_genre,
'--album', track.cd_title, '--album', track.cd_title,
split_track_filename, split_track_filename,
'{}.opus'.format(os.path.splitext(split_track_filename)[0]), '{}.opus'.format(os.path.splitext(split_track_filename)[0]),
]) ])
queue.get() queue.get()
class Track(): class Track():
def __init__(self, track_index, filename, parent): def __init__(self, track_index, filename, parent):
for member in ('cd_performer', 'cd_title', 'cd_date', 'cd_genre'): for member in ('cd_performer', 'cd_title', 'cd_date', 'cd_genre'):
setattr(self, member, getattr(parent, member)) setattr(self, member, getattr(parent, member))
self.filename = filename self.filename = filename
self.filepath = filename[:filename.rfind('\\')+1] self.filepath = filename[:filename.rfind('\\')+1]
self.title = '' self.title = ''
self.index = track_index self.index = track_index
self.performer = self.cd_performer self.performer = self.cd_performer
self.time = { 1:0.0 } self.time = { 1:0.0 }
def __str__(self): def __str__(self):
return "{} - {} - {}".format(self.index, self.title, self.time) return "{} - {} - {}".format(self.index, self.title, self.time)
class CueSheet(): class CueSheet():
def __init__(self, filename): def __init__(self, filename):
self.filename = filename self.filename = filename
self.filepath = filename[:filename.rfind('\\')+1] self.filepath = filename[:filename.rfind('\\')+1]
self.cd_performer = '' self.cd_performer = ''
self.cd_title = '' self.cd_title = ''
self.cd_genre = '' self.cd_genre = ''
self.cd_date = '' self.cd_date = ''
self.current_file = '' self.current_file = ''
self.tracks = [] self.tracks = []
self.regex_lst = ( self.regex_lst = (
(re.compile(r'PERFORMER\s(.+)'), self.__performer), (re.compile(r'PERFORMER\s(.+)'), self.__performer),
(re.compile(r'REM DATE\s(.+)'), self.__date), (re.compile(r'REM DATE\s(.+)'), self.__date),
(re.compile(r'REM GENRE\s(.+)'), self.__genre), (re.compile(r'REM GENRE\s(.+)'), self.__genre),
(re.compile(r'TITLE\s(.+)'), self.__title), (re.compile(r'TITLE\s(.+)'), self.__title),
(re.compile(r'FILE\s(.+)\sWAVE'), self.__file), (re.compile(r'FILE\s(.+)\sWAVE'), self.__file),
(re.compile(r'TRACK\s(\d{2})\sAUDIO'), self.__track), (re.compile(r'TRACK\s(\d{2})\sAUDIO'), self.__track),
(re.compile(r'INDEX\s(\d{2})\s(\d{1,3}:\d{2}:\d{2})'), self.__index), (re.compile(r'INDEX\s(\d{2})\s(\d{1,3}:\d{2}:\d{2})'), self.__index),
) )
def __str__(self): def __str__(self):
value = "Title: {}\nPerformer: {}\nGenre: {}\nDate: {}\n".format(self.cd_title, self.cd_performer, self.cd_genre, self.cd_date) value = "Title: {}\nPerformer: {}\nGenre: {}\nDate: {}\n".format(self.cd_title, self.cd_performer, self.cd_genre, self.cd_date)
for track in self.tracks: for track in self.tracks:
value += ' ' + str(track) + '\n' value += ' ' + str(track) + '\n'
return value return value
def read(self): def read(self):
with open(self.filename, 'r', encoding='utf-8-sig') as f: with open(self.filename, 'r', encoding='utf-8-sig') as f:
for line in f: for line in f:
for regex, handler in self.regex_lst: for regex, handler in self.regex_lst:
mobj = regex.match(line.strip()) mobj = regex.match(line.strip())
if mobj: if mobj:
handler(*self.unquote(mobj.groups())) handler(*self.unquote(mobj.groups()))
def split(self): def split(self):
encoding_queue = multiprocessing.Queue(multiprocessing.cpu_count()) encoding_queue = multiprocessing.Queue(multiprocessing.cpu_count())
cds = set() cds = set()
tracks = set() tracks = set()
for i, track in enumerate(self.tracks): for i, track in enumerate(self.tracks):
# FATAL: sheet is not for .tta file # FATAL: sheet is not for .tta file
if track.filename[-4:] != '.tta': if track.filename[-4:] != '.tta':
f.write("\nFilename isn't .tta ({}):\n{}\n".format(track.filename, str(self))) f.write("\nFilename isn't .tta ({}):\n{}\n".format(track.filename, str(self)))
return return
track_path = track.filepath + ' - '.join((track.index, track.title)).replace('?', '').replace('\\', '').replace('\\', '').replace(':', '') track_path = track.filepath + ' - '.join((track.index, track.title)).replace('?', '').replace('\\', '').replace('\\', '').replace(':', '')
track_opus = track_path + '.opus' track_opus = track_path + '.opus'
track_wav = track_path + '.wav' track_wav = track_path + '.wav'
if os.path.exists(track_opus): if os.path.exists(track_opus):
f.write("File already exists, continuing... ({})".format(track_opus)) f.write("File already exists, continuing... ({})".format(track_opus))
remove_if_exists(track_wav) remove_if_exists(track_wav)
continue continue
cd_wav = track.filename[:-4] + '.wav' cd_wav = track.filename[:-4] + '.wav'
# decode .tta if needed # decode .tta if needed
if not os.path.exists(cd_wav): if not os.path.exists(cd_wav):
# FATAL: no file to decode # FATAL: no file to decode
if not os.path.exists(track.filename): if not os.path.exists(track.filename):
f.write("\nFile doesn't exist ({}):\n{}\n".format(track.filename, str(self))) f.write("\nFile doesn't exist ({}):\n{}\n".format(track.filename, str(self)))
return return
result = subprocess.call([ result = subprocess.call([
'tta', #'ttaenc', 'tta', #'ttaenc',
'-d', '-d',
track.filename, track.filename,
#'-o', #'-o',
cd_wav cd_wav
]) ])
# FATAL: .tta decode failed # FATAL: .tta decode failed
if result != 0: if result != 0:
f.write("Failed to decode .tta ({}):\n{}\n\n".format(track.index, str(self))) f.write("Failed to decode .tta ({}):\n{}\n\n".format(track.index, str(self)))
return return
# remove .tta # remove .tta
remove_if_exists(track.filename) remove_if_exists(track.filename)
# split .wav into track # split .wav into track
if not os.path.exists(track_wav): if not os.path.exists(track_wav):
wafi = wave.open(cd_wav, 'rb') wafi = wave.open(cd_wav, 'rb')
param_names = ('nchannels', 'sampwidth', 'framerate', 'nframes', 'comptype', 'compname') param_names = ('nchannels', 'sampwidth', 'framerate', 'nframes', 'comptype', 'compname')
params = wafi.getparams() params = wafi.getparams()
param_dict = dict(zip(param_names, params)) param_dict = dict(zip(param_names, params))
start = int(param_dict['framerate'] * track.time[1]) start = int(param_dict['framerate'] * track.time[1])
stop = param_dict['nframes'] stop = param_dict['nframes']
if len(sheet.tracks) > i+1 and sheet.tracks[i+1].filename == track.filename: if len(sheet.tracks) > i+1 and sheet.tracks[i+1].filename == track.filename:
stop = int(param_dict['framerate'] * sheet.tracks[i+1].time.get(0, sheet.tracks[i+1].time[1])) stop = int(param_dict['framerate'] * sheet.tracks[i+1].time.get(0, sheet.tracks[i+1].time[1]))
wafi_write = wave.open(track_wav, 'wb') wafi_write = wave.open(track_wav, 'wb')
newparams = list(params) newparams = list(params)
newparams[3] = 0 newparams[3] = 0
wafi_write.setparams( tuple(newparams) ) wafi_write.setparams( tuple(newparams) )
wafi.setpos(start) wafi.setpos(start)
wafi_write.writeframes(wafi.readframes(stop-start)) wafi_write.writeframes(wafi.readframes(stop-start))
wafi_write.close() wafi_write.close()
wafi.close() wafi.close()
encoding_queue.put(track_wav) encoding_queue.put(track_wav)
p = multiprocessing.Process( p = multiprocessing.Process(
target=opus_enc, target=opus_enc,
args=( args=(
encoding_queue, encoding_queue,
track_wav, track_wav,
track track
) )
) )
p.start() p.start()
if cd_wav not in cds: if cd_wav not in cds:
cds.add(cd_wav) cds.add(cd_wav)
tracks.add(track_wav) tracks.add(track_wav)
while not encoding_queue.empty(): while not encoding_queue.empty():
time.sleep(0.2) time.sleep(0.2)
for cd in cds: for cd in cds:
remove_if_exists(cd) remove_if_exists(cd)
for track in tracks: for track in tracks:
remove_if_exists(track) remove_if_exists(track)
remove_if_exists(self.filename) remove_if_exists(self.filename)
print(self.filename, "done!") print(self.filename, "done!")
def __performer(self, s): def __performer(self, s):
if not self.tracks: if not self.tracks:
self.cd_performer = s self.cd_performer = s
else: else:
self.tracks[-1].performer = s self.tracks[-1].performer = s
def __title(self, s): def __title(self, s):
if not self.tracks: if not self.tracks:
self.cd_title = s self.cd_title = s
else: else:
self.tracks[-1].title = s self.tracks[-1].title = s
def __genre(self, s): def __genre(self, s):
self.cd_genre = s self.cd_genre = s
def __date(self, s): def __date(self, s):
self.cd_date = s self.cd_date = s
def __file(self, s): def __file(self, s):
self.current_file = s self.current_file = s
def __track(self, s): def __track(self, s):
self.tracks.append( Track(s, self.filepath + self.current_file, self) ) self.tracks.append( Track(s, self.filepath + self.current_file, self) )
def __index(self, idx, s): def __index(self, idx, s):
idx = int(idx) idx = int(idx)
self.tracks[-1].time[idx] = self.index_split(s) self.tracks[-1].time[idx] = self.index_split(s)
@staticmethod @staticmethod
def index_split(s): def index_split(s):
t = s.split(':') t = s.split(':')
return float(t[0])*60 + float(t[1]) + float(t[2]) / 75.0 return float(t[0])*60 + float(t[1]) + float(t[2]) / 75.0
@staticmethod @staticmethod
def dqstrip(s): def dqstrip(s):
if s[0] == '"' and s[-1] == '"': return s[1:-1] if s[0] == '"' and s[-1] == '"': return s[1:-1]
return s return s
@staticmethod @staticmethod
def unquote(t): def unquote(t):
return tuple([CueSheet.dqstrip(s.strip()) for s in t]) return tuple([CueSheet.dqstrip(s.strip()) for s in t])
class SplitterWorker(Thread): class SplitterWorker(Thread):
def __init__(self, queue, filename): def __init__(self, queue, filename):
Thread.__init__(self) Thread.__init__(self)
self.queue = queue self.queue = queue
self.filename = filename self.filename = filename
def run(self): def run(self):
sheet = CueSheet(self.filename) sheet = CueSheet(self.filename)
sheet.read() sheet.read()
sheet.split() sheet.split()
if __name__ == '__main__': if __name__ == '__main__':
queue = Queue() queue = Queue()
for root, dirs, files in os.walk('.'): for root, dirs, files in os.walk('.'):
for name in files: for name in files:
if name[-4:].lower() == '.cue': if name[-4:].lower() == '.cue':
worker = SplitterWorker(queue, root + '\\' + name) worker = SplitterWorker(queue, root + '\\' + name)
worker.daemon = True worker.daemon = True
worker.start() worker.start()
if os.path.exists('./stop'): if os.path.exists('./stop'):
exit(1) exit(1)

View File

@@ -1,16 +1,17 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# extracts cover from flac audio file
# extracts cover from flac audio file
from mutagen.flac import FLAC, Picture
from mutagen.flac import FLAC, Picture
song = "cover.flac"
song = "cover.flac"
var = FLAC(song)
pics = var.pictures var = FLAC(song)
print (pics) pics = var.pictures
for p in pics: print (pics)
if p.type == 3: #front cover for p in pics:
print("\nfound front cover") if p.type == 3: #front cover
with open("cover.jpg", "wb") as f: print("\nfound front cover")
with open("cover.jpg", "wb") as f:
f.write(p.data) f.write(p.data)

View File

@@ -1,45 +1,46 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np import matplotlib.pyplot as plt
import numpy as np
class Ore:
def __init__(self, name, low, high): class Ore:
self.name = name def __init__(self, name, low, high):
self.low = low self.name = name
self.high = high self.low = low
self.high = high
oregen = (
Ore('gold', 0, 32), oregen = (
Ore('iron', 0, 64), Ore('gold', 0, 32),
Ore('coal', 0, 128), Ore('iron', 0, 64),
Ore('lapis', 0, 32), Ore('coal', 0, 128),
Ore('diamond', 0, 16), Ore('lapis', 0, 32),
Ore('redstone', 0, 16), Ore('diamond', 0, 16),
Ore('emerald', 0, 16), Ore('redstone', 0, 16),
Ore('certuz', 24, 48), Ore('emerald', 0, 16),
Ore('apatite', 54, 96), Ore('certuz', 24, 48),
Ore('uranium', 16, 42), Ore('apatite', 54, 96),
Ore('ruby', 16, 42), Ore('uranium', 16, 42),
Ore('sapphire', 16, 42), Ore('ruby', 16, 42),
Ore('bauxite', 48, 72), Ore('sapphire', 16, 42),
Ore('tungsten', 0, 10), Ore('bauxite', 48, 72),
Ore('peridot', 16, 42), Ore('tungsten', 0, 10),
Ore('copper', 40, 75), Ore('peridot', 16, 42),
Ore('tin', 20, 55), Ore('copper', 40, 75),
Ore('silver', 5, 30), Ore('tin', 20, 55),
Ore('lead', 5, 30), Ore('silver', 5, 30),
Ore('aluminum', 48, 72), Ore('lead', 5, 30),
Ore('nickel', 5, 20), Ore('aluminum', 48, 72),
Ore('platinum', 7, 75), Ore('nickel', 5, 20),
Ore('iridium', 8, 75), Ore('platinum', 7, 75),
) Ore('iridium', 8, 75),
)
oregen = sorted(oregen, key=lambda x: x.low, reverse=True)
oregen = sorted(oregen, key=lambda x: x.low, reverse=True)
plt.boxplot([(x.high, x.low) for x in oregen], labels=[x.name.title() for x in oregen], vert=False)
plt.title('FTB Continuum Oregen') plt.boxplot([(x.high, x.low) for x in oregen], labels=[x.name.title() for x in oregen], vert=False)
plt.xlabel('Y-level') plt.title('FTB Continuum Oregen')
plt.xticks() plt.xlabel('Y-level')
plt.xticks()
plt.savefig('oregen.svg', format='svg')
plt.savefig('oregen.svg', format='svg')

View File

@@ -1,14 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# -*- coding: utf-8 -*-
# converts code signatures found in ida to ones easily usable in c++ code
# converts code signatures found in ida to ones easily usable in c++ code
import sys
import sys
if len(sys.argv) < 2:
print("Usage: " + sys.argv[0] + " [ida style sig]") if len(sys.argv) < 2:
exit(1) print("Usage: " + sys.argv[0] + " [ida style sig]")
exit(1)
print(
'"' + ''.join([('\\x' + (byte if byte != '?' else '00')) for byte in sys.argv[1:]]) + '", "' + print(
''.join([('x' if byte != '?' else '?') for byte in sys.argv[1:]]) + '"' '"' + ''.join([('\\x' + (byte if byte != '?' else '00')) for byte in sys.argv[1:]]) + '", "' +
) ''.join([('x' if byte != '?' else '?') for byte in sys.argv[1:]]) + '"'
)

97
python/speedtyper.py Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import curses
class Word():
def __init__(self, target, x, y):
self.target = target
self.input = ""
self.x = x
self.y = y
def get_words(text, max_x, max_y):
curr_x = 0
curr_y = 0
words = []
for word in text.split():
if curr_x + len(word) > max_x:
curr_y += 1
curr_x = 0
if curr_y > max_y:
print("text too long, scrolling not implemented.")
exit(1)
words.append(Word(word, curr_x, curr_y))
curr_x += len(word) + 1
return words
def main_curses(stdscr, text):
curses.use_default_colors()
curses.init_pair(1, curses.COLOR_GREEN, -1)
curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_RED)
key = old_max_y = old_max_x = curr_word = 0
while True:
# rewrap words on screen size change
max_y, max_x = stdscr.getmaxyx()
if max_y != old_max_y or max_x != old_max_x:
words = get_words(text, max_x, max_y)
old_max_x = max_x
old_max_y = max_y
if key in (curses.KEY_BACKSPACE, 'KEY_BACKSPACE', '\b', '\x7f', 127): # fml
words[curr_word].input = words[curr_word].input[:-1]
elif key >= 32 and key <= 126:
words[curr_word].input += chr(key)
# increment current word if its completed
if words[curr_word].input == words[curr_word].target:
curr_word += 1
# text complete
if curr_word == len(words):
break
stdscr.clear()
for word in words:
if word.input == word.target:
stdscr.addstr(word.y, word.x, word.target, curses.A_DIM)
elif word == words[curr_word]:
stdscr.addstr(word.y, word.x, word.target, curses.A_UNDERLINE)
else:
stdscr.addstr(word.y, word.x, word.target)
for i, c in enumerate(words[curr_word].input):
if i >= len(words[curr_word].target) or words[curr_word].input[i] != words[curr_word].target[i]:
stdscr.addstr(words[curr_word].y, words[curr_word].x + i, c, curses.color_pair(2) | curses.A_BOLD)
else:
stdscr.addstr(words[curr_word].y, words[curr_word].x + i, c, curses.color_pair(1))
stdscr.move(words[curr_word].y, words[curr_word].x + len(words[curr_word].input))
key = stdscr.getch()
def main(argv):
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("input")
args = parser.parse_args(argv[1:])
text = open(args.input).read()
curses.wrapper(main_curses, text)
if __name__ == "__main__":
main(sys.argv)

View File

@@ -1,45 +1,46 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import bs4
import sys import bs4
import os import sys
import glob import os
import glob
# converts MyAnimeList's XML exports to readable (but less informative) text files.
# converts MyAnimeList's XML exports to readable (but less informative) text files.
animelists = glob.glob('animelist*.xml')
animelists = glob.glob('animelist*.xml')
for animelist in animelists:
with open(animelist, 'r') as xml, open(animelist + '.txt', 'w') as file: for animelist in animelists:
soup = bs4.BeautifulSoup(xml.read(), 'html.parser') with open(animelist, 'r') as xml, open(animelist + '.txt', 'w') as file:
soup = bs4.BeautifulSoup(xml.read(), 'html.parser')
completed = []
ptw = [] completed = []
movies = [] ptw = []
for anime in soup.select('anime'): movies = []
line = anime.select('series_title')[0].text + ' ' + anime.select('my_watched_episodes')[0].text + '/' + anime.select('series_episodes')[0].text + '\n' for anime in soup.select('anime'):
line = anime.select('series_title')[0].text + ' ' + anime.select('my_watched_episodes')[0].text + '/' + anime.select('series_episodes')[0].text + '\n'
series_type = anime.select('series_type')[0].text
status = anime.select('my_status')[0].text series_type = anime.select('series_type')[0].text
status = anime.select('my_status')[0].text
if series_type == 'Movie':
movies.append(line) if series_type == 'Movie':
continue movies.append(line)
continue
if status == 'Completed':
completed.append(line) if status == 'Completed':
elif status == 'Plan to Watch': completed.append(line)
ptw.append(line) elif status == 'Plan to Watch':
ptw.append(line)
for title in completed:
file.write(title) for title in completed:
file.write(title)
file.write('\n')
file.write('\n')
for title in ptw:
file.write(title) for title in ptw:
file.write(title)
file.write('\n')
file.write('\n')
for title in movies:
file.write(title) for title in movies:
file.write(title)

View File

@@ -1,14 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# converts youtube subscriptions export .xml to simple text file
# converts youtube subscriptions export .xml to simple text file
with open('subscription_manager', 'r', encoding='utf-8') as f:
while f: with open('subscription_manager', 'r', encoding='utf-8') as f:
line = f.readline() while f:
if not 'channel_id' in line: line = f.readline()
continue if not 'channel_id' in line:
continue
idpos = line.find('channel_id=') + len('channel_id=')
idpos = line.find('channel_id=') + len('channel_id=')
channel_id = line[idpos:idpos + len('UC3Y4vKAzTCqSdOt0ZeYWvTg')]
print('https://www.youtube.com/channel/' + channel_id) channel_id = line[idpos:idpos + len('UC3Y4vKAzTCqSdOt0ZeYWvTg')]
print('https://www.youtube.com/channel/' + channel_id)

View File

@@ -1,4 +1,5 @@
#!/bin/env python3 #!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys import sys
import os import os

View File

@@ -1,47 +1,50 @@
import requests #!/usr/bin/env python3
import json # -*- coding: utf-8 -*-
import sys
import requests
if len(sys.argv) < 3: import json
print("usage: python get_7k_pp.py [api key] [username]") import sys
exit(0)
if len(sys.argv) < 3:
api_key = sys.argv[1] print("usage: python get_7k_pp.py [api key] [username]")
usernames = sys.argv[2:] exit(0)
def get_json(url): api_key = sys.argv[1]
page = requests.get(url) usernames = sys.argv[2:]
try: def get_json(url):
page.raise_for_status() page = requests.get(url)
except:
print("Could not get '{}'".format(url)) try:
return [] page.raise_for_status()
except:
return json.loads(page.text) print("Could not get '{}'".format(url))
return []
def get_user_best(api_key, username):
return get_json("https://osu.ppy.sh/api/get_user_best?k={}&limit=100&m=3&u={}".format(api_key, username)) return json.loads(page.text)
def get_beatmap(api_key, id): def get_user_best(api_key, username):
return get_json("https://osu.ppy.sh/api/get_beatmaps?k={}&b={}".format(api_key, id)) return get_json("https://osu.ppy.sh/api/get_user_best?k={}&limit=100&m=3&u={}".format(api_key, username))
for username in usernames: def get_beatmap(api_key, id):
scores_7k = [] return get_json("https://osu.ppy.sh/api/get_beatmaps?k={}&b={}".format(api_key, id))
pp_7k = 0.0
for score in get_user_best(api_key, username): for username in usernames:
info = get_beatmap(api_key, score["beatmap_id"])[0] scores_7k = []
if info["diff_size"] == '7': pp_7k = 0.0
# theres probably a prettier solution for this for score in get_user_best(api_key, username):
percentage = 100.0 info = get_beatmap(api_key, score["beatmap_id"])[0]
for num in range(len(scores_7k)): if info["diff_size"] == '7':
percentage *= 0.95 # theres probably a prettier solution for this
percentage = 100.0
pp_7k += float(score["pp"]) / 100.0 * percentage for num in range(len(scores_7k)):
scores_7k.append("[{:.2f}+ ({:.2f}%)] {:.2f} {} [{}] {}k".format(pp_7k, percentage, float(score["pp"]), info["title"], info["version"], score["score"][:3])) percentage *= 0.95
print("7k pp for '{}'".format(username)) pp_7k += float(score["pp"]) / 100.0 * percentage
print("Total = {}".format(pp_7k)) scores_7k.append("[{:.2f}+ ({:.2f}%)] {:.2f} {} [{}] {}k".format(pp_7k, percentage, float(score["pp"]), info["title"], info["version"], score["score"][:3]))
for score_7k in scores_7k: print("7k pp for '{}'".format(username))
print(score_7k) print("Total = {}".format(pp_7k))
for score_7k in scores_7k:
print(score_7k)

View File

@@ -1,34 +1,37 @@
import sys #!/usr/bin/env python3
# -*- coding: utf-8 -*-
from selenium import webdriver
import sys
def login(driver, username, password):
driver.get("https://osu.ppy.sh/forum/ucp.php?mode=login") from selenium import webdriver
driver.find_element_by_name("username").send_keys(username)
driver.find_element_by_name("password").send_keys(password) def login(driver, username, password):
driver.find_element_by_name("login").click() driver.get("https://osu.ppy.sh/forum/ucp.php?mode=login")
driver.find_element_by_name("username").send_keys(username)
def main(argv): driver.find_element_by_name("password").send_keys(password)
if len(argv) < 5: driver.find_element_by_name("login").click()
print("Usage: {} [USERNAME] [PASSWORD] [SEARCH PARAMS] [NUM PAGES]".format(argv[0]))
return def main(argv):
if len(argv) < 5:
username = argv[1] print("Usage: {} [USERNAME] [PASSWORD] [SEARCH PARAMS] [NUM PAGES]".format(argv[0]))
password = argv[2] return
search_params = argv[3].strip('"') username = argv[1]
num_pages = int(argv[4]) password = argv[2]
with webdriver.Firefox() as driver: search_params = argv[3].strip('"')
login(driver, username, password) num_pages = int(argv[4])
for page_nr in range(1, num_pages + 1): with webdriver.Firefox() as driver:
if page_nr == 0: login(driver, username, password)
continue
for page_nr in range(1, num_pages + 1):
driver.get("https://old.ppy.sh/p/beatmaplist?{}&page={}".format(search_params, page_nr)) if page_nr == 0:
for beatmap_elem in driver.find_elements_by_class_name("beatmap"): continue
print(beatmap_elem.get_property("id"))
driver.get("https://old.ppy.sh/p/beatmaplist?{}&page={}".format(search_params, page_nr))
if __name__ == "__main__": for beatmap_elem in driver.find_elements_by_class_name("beatmap"):
main(sys.argv) print(beatmap_elem.get_property("id"))
if __name__ == "__main__":
main(sys.argv)

View File

@@ -1,23 +1,24 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests # http requests
import bs4 # html parser import requests # http requests
import bs4 # html parser
with open("titles.txt", "w", encoding="UTF-8") as file:
for index in range(1, 175): with open("titles.txt", "w", encoding="UTF-8") as file:
url = "https://www.gogdb.org/products?page=" + str(index) for index in range(1, 175):
print(url) url = "https://www.gogdb.org/products?page=" + str(index)
print(url)
page = requests.get("https://www.gogdb.org/products?page=" + str(index))
page.raise_for_status() page = requests.get("https://www.gogdb.org/products?page=" + str(index))
page.raise_for_status()
soup = bs4.BeautifulSoup(page.text, "html.parser")
soup = bs4.BeautifulSoup(page.text, "html.parser")
producttable = soup.select("#product-table")[0]
titles = producttable.select("tr") producttable = soup.select("#product-table")[0]
for title in titles: titles = producttable.select("tr")
if len(title.select(".col-type")) == 0: for title in titles:
continue if len(title.select(".col-type")) == 0:
continue
if title.select(".col-type")[0].text == 'Game':
file.write(title.select(".col-name")[0].text.strip() + '\n') if title.select(".col-type")[0].text == 'Game':
file.write(title.select(".col-name")[0].text.strip() + '\n')

View File

@@ -1,3 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests, bs4, time import requests, bs4, time
def get_titles(filename, title_type, maxrank): def get_titles(filename, title_type, maxrank):

View File

@@ -1,137 +1,138 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# reads SteamIDs from ./accounts.txt and outputs ban information into ./output.html
# reads SteamIDs from ./accounts.txt and outputs ban information into ./output.html
import urllib.request
import json import urllib.request
import time import json
import time
steamapikey = ""
steamapikey = ""
# read file and remove trailing newline because we're making a list
account_lines = [line.rstrip("\n") for line in open("accounts.txt").readlines()] # read file and remove trailing newline because we're making a list
account_lines = [line.rstrip("\n") for line in open("accounts.txt").readlines()]
ids = []
for line in account_lines: ids = []
# https://developer.valvesoftware.com/wiki/SteamID for line in account_lines:
Z = int(line.split(':')[2]) # https://developer.valvesoftware.com/wiki/SteamID
V = 0x0110000100000000 # profile ID constant Z = int(line.split(':')[2])
Y = int(line.split(':')[1]) V = 0x0110000100000000 # profile ID constant
W = Z * 2 + V + Y Y = int(line.split(':')[1])
ids.append(str(W)) W = Z * 2 + V + Y
ids.append(str(W))
# API takes in comma seperated steamids
ids_string = ",".join([x for x in ids]) # API takes in comma seperated steamids
ids_string = ",".join([x for x in ids])
# https://developer.valvesoftware.com/wiki/Steam_Web_API
summaries = json.load(urllib.request.urlopen("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=" + steamapikey + "&steamids=" + ids_string)) # https://developer.valvesoftware.com/wiki/Steam_Web_API
bans = json.load(urllib.request.urlopen("http://api.steampowered.com/ISteamUser/GetPlayerBans/v1/?key=" + steamapikey + "&steamids=" + ids_string)) summaries = json.load(urllib.request.urlopen("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=" + steamapikey + "&steamids=" + ids_string))
bans = json.load(urllib.request.urlopen("http://api.steampowered.com/ISteamUser/GetPlayerBans/v1/?key=" + steamapikey + "&steamids=" + ids_string))
output_file = open("output.html", "w", encoding="utf-8")
output_file = open("output.html", "w", encoding="utf-8")
output_file.write('\
<!DOCTYPE html>\n\ output_file.write('\
<html>\n\ <!DOCTYPE html>\n\
<head>\n\ <html>\n\
<style>\n\ <head>\n\
body {\n\ <style>\n\
font-family: sans-serif;\n\ body {\n\
}\n\ font-family: sans-serif;\n\
\n\ }\n\
table {\n\ \n\
color: #222;\n\ table {\n\
border-collapse: collapse;\n\ color: #222;\n\
}\n\ border-collapse: collapse;\n\
\n\ }\n\
tr, th, td {\n\ \n\
border: 1px solid #a2a9b1;\n\ tr, th, td {\n\
padding: 0.2em 0.4em;\n\ border: 1px solid #a2a9b1;\n\
}\n\ padding: 0.2em 0.4em;\n\
\n\ }\n\
.pwned {\n\ \n\
background-color: #ffb6c1\n\ .pwned {\n\
}\n\ background-color: #ffb6c1\n\
\n\ }\n\
th {\n\ \n\
background-color: #eaecf0;\n\ th {\n\
text-align: center;\n\ background-color: #eaecf0;\n\
}\n\ text-align: center;\n\
\n\ }\n\
a:hover, a:visited, a:link, a:active {\n\ \n\
text-decoration: none;\n\ a:hover, a:visited, a:link, a:active {\n\
}\n\ text-decoration: none;\n\
</style>\n\ }\n\
</head>\n\ </style>\n\
\n\ </head>\n\
<body>\n\ \n\
<table>\n\ <body>\n\
<tr>\n\ <table>\n\
<th>ID</th>\n\ <tr>\n\
<th>Name</th>\n\ <th>ID</th>\n\
<th>Status</th>\n\ <th>Name</th>\n\
<th>Type</th>\n\ <th>Status</th>\n\
<th>BanDays</th>\n\ <th>Type</th>\n\
<th>LogDays</th>\n\ <th>BanDays</th>\n\
<th>Profile</th>\n\ <th>LogDays</th>\n\
</tr>\n\ <th>Profile</th>\n\
') </tr>\n\
')
numbanned = 0
numbanned = 0
for i in range(len(ids)):
try: for i in range(len(ids)):
for summary in summaries['response']['players']: try:
if summary['steamid'] == str(ids[i]): for summary in summaries['response']['players']:
break if summary['steamid'] == str(ids[i]):
except: break
continue except:
continue
try:
for ban in bans['players']: try:
if ban['SteamId'] == str(ids[i]): for ban in bans['players']:
break if ban['SteamId'] == str(ids[i]):
except: break
continue except:
continue
status = ""
bantype = "" status = ""
bandays = "" bantype = ""
bandays = ""
if ban['VACBanned']:
status = "Pwned" if ban['VACBanned']:
bantype = "VAC" status = "Pwned"
bandays = str(ban['DaysSinceLastBan']) bantype = "VAC"
numbanned += 1 bandays = str(ban['DaysSinceLastBan'])
numbanned += 1
if ban['NumberOfGameBans'] > 0:
status = "Pwned" if ban['NumberOfGameBans'] > 0:
bantype = "Gameban" status = "Pwned"
bandays = str(ban['DaysSinceLastBan']) bantype = "Gameban"
numbanned += 1 bandays = str(ban['DaysSinceLastBan'])
numbanned += 1
name = summary['personaname']
name = name.replace("<", "&lt;") # escape html tag names name = summary['personaname']
name = name.replace(">", "&gt;") name = name.replace("<", "&lt;") # escape html tag names
name = name.replace(">", "&gt;")
logdays = str(int((time.time() - summary['lastlogoff']) / 86400)) # length of a day in epoch
logdays = str(int((time.time() - summary['lastlogoff']) / 86400)) # length of a day in epoch
line_start = ' <td>' if status != "Pwned" else ' <td class="pwned">'
line_start = ' <td>' if status != "Pwned" else ' <td class="pwned">'
output_file.write(' <tr>\n')
output_file.write(line_start + '<a target="_blank" href="' + 'https://steamcommunity.com/profiles/' + str(ids[i]) + '">' + str(ids[i]) + '</a></td>\n') output_file.write(' <tr>\n')
output_file.write(line_start + name + '</td>\n') output_file.write(line_start + '<a target="_blank" href="' + 'https://steamcommunity.com/profiles/' + str(ids[i]) + '">' + str(ids[i]) + '</a></td>\n')
output_file.write(line_start + status + '</td>\n') output_file.write(line_start + name + '</td>\n')
output_file.write(line_start + bantype + '</td>\n') output_file.write(line_start + status + '</td>\n')
output_file.write(line_start + bandays + '</td>\n') output_file.write(line_start + bantype + '</td>\n')
output_file.write(line_start + logdays + '</td>\n') output_file.write(line_start + bandays + '</td>\n')
output_file.write(line_start + '<a target="_blank" href="' + 'https://steamcommunity.com/profiles/' + str(ids[i]) + '"><img src=' + summary['avatarmedium'] + ">"+ '</img></td>\n') output_file.write(line_start + logdays + '</td>\n')
output_file.write(' </tr>\n') output_file.write(line_start + '<a target="_blank" href="' + 'https://steamcommunity.com/profiles/' + str(ids[i]) + '"><img src=' + summary['avatarmedium'] + ">"+ '</img></td>\n')
output_file.write(' </tr>\n')
i += 1
i += 1
output_file.write('\
</table>\n\ output_file.write('\
' + str(numbanned) + '/' + str(len(ids)) + ' banned\n\ </table>\n\
</body>\n\ ' + str(numbanned) + '/' + str(len(ids)) + ' banned\n\
\ </body>\n\
</html>\n') \
</html>\n')

View File

@@ -1,58 +1,59 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import bs4 import requests
import sys import bs4
import sys
if len(sys.argv) < 4:
print('Usage: ' + sys.argv[0] + ' [login] [password] [page name]') if len(sys.argv) < 4:
exit(1) print('Usage: ' + sys.argv[0] + ' [login] [password] [page name]')
exit(1)
login = sys.argv[1]
password = sys.argv[2] login = sys.argv[1]
page_name = sys.argv[3] password = sys.argv[2]
page_name = sys.argv[3]
def download_sheet(s, url):
page = s.get(url) def download_sheet(s, url):
page = s.get(url)
try:
page.raise_for_status() try:
except: page.raise_for_status()
print("Couldn't get %s" % url) except:
return print("Couldn't get %s" % url)
return
soup = bs4.BeautifulSoup(page.text, 'html.parser')
soup = bs4.BeautifulSoup(page.text, 'html.parser')
links = soup.select('a')
for link in links: links = soup.select('a')
if '.pdf' in link.text: for link in links:
with open(link.text[1:link.text.find('.pdf') + 4], 'wb') as f: if '.pdf' in link.text:
file = s.get(link.attrs['href']) with open(link.text[1:link.text.find('.pdf') + 4], 'wb') as f:
file = s.get(link.attrs['href'])
try:
page.raise_for_status() try:
except: page.raise_for_status()
print("Couldn't get %s" % link.text) except:
return print("Couldn't get %s" % link.text)
return
for chunk in file.iter_content(100000):
f.write(chunk) for chunk in file.iter_content(100000):
f.write(chunk)
with requests.session() as s:
login = s.post('https://hi10anime.com/wp-login.php', { 'login':login, 'password':password }) with requests.session() as s:
login.raise_for_status() login = s.post('https://hi10anime.com/wp-login.php', { 'login':login, 'password':password })
login.raise_for_status()
if not 'You have successfully logged in. Welcome back!' in login.text:
print("Couldn't log in") if not 'You have successfully logged in. Welcome back!' in login.text:
exit(1) print("Couldn't log in")
exit(1)
page = s.get('https://sheet.host/user/%s/sheets' % page_name)
page.raise_for_status() page = s.get('https://sheet.host/user/%s/sheets' % page_name)
page.raise_for_status()
soup = bs4.BeautifulSoup(page.text, 'html.parser')
soup = bs4.BeautifulSoup(page.text, 'html.parser')
titles = soup.select('.score-title')
titles = soup.select('.score-title')
for title in titles:
print('Getting %s' % title.text) for title in titles:
download_sheet(s, title.attrs['href']) print('Getting %s' % title.text)
download_sheet(s, title.attrs['href'])

View File

@@ -1,66 +1,67 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import bs4 import requests
import bs4
def download_file(url):
filename = url[url.rfind('/') + 1:] def download_file(url):
filename = url[url.rfind('/') + 1:]
print('Downloading %s' % filename)
print('Downloading %s' % filename)
file = requests.get(url)
file = requests.get(url)
try:
file.raise_for_status() try:
except: file.raise_for_status()
open(filename + '.failed', 'w') except:
open(filename + '.failed', 'w')
with open(filename, 'wb') as f:
for chunk in file.iter_content(100000): with open(filename, 'wb') as f:
f.write(chunk) for chunk in file.iter_content(100000):
f.write(chunk)
f.close()
f.close()
def get_file_name(url):
page = requests.get(url) def get_file_name(url):
page.raise_for_status() page = requests.get(url)
page.raise_for_status()
soup = bs4.BeautifulSoup(page.text, "html.parser")
soup = bs4.BeautifulSoup(page.text, "html.parser")
cells = soup.select('td.even') # gay retardness
for cell in cells: cells = soup.select('td.even') # gay retardness
text = cell.getText() for cell in cells:
text = cell.getText()
if '.rar' in text or '.zip' in text or '.7z' in text:
return text if '.rar' in text or '.zip' in text or '.7z' in text:
return text
def scrape_site(url):
# split the url to use later for constructing new urls def scrape_site(url):
base_url = url[:url.rfind('/') + 1] # split the url to use later for constructing new urls
url = url[url.rfind('/') + 1:] base_url = url[:url.rfind('/') + 1]
url = url[url.rfind('/') + 1:]
while True:
print('Getting %s' % url) while True:
print('Getting %s' % url)
page = requests.get(base_url + url)
page.raise_for_status() # throw on fail page = requests.get(base_url + url)
page.raise_for_status() # throw on fail
soup = bs4.BeautifulSoup(page.text, "html.parser")
soup = bs4.BeautifulSoup(page.text, "html.parser")
titles = soup.select('a[title]')
for title in titles: titles = soup.select('a[title]')
link = title.attrs['href'] for title in titles:
link = title.attrs['href']
if 'id' in link and not 'dl' in link: # find content links
print('Found %s' % title.attrs['title']) if 'id' in link and not 'dl' in link: # find content links
download_file(base_url + 'sub/enganime/' + get_file_name(base_url + link)) print('Found %s' % title.attrs['title'])
download_file(base_url + 'sub/enganime/' + get_file_name(base_url + link))
next_link = soup.select('span.pagenav_next > a')
if len(next_link) == 0: next_link = soup.select('span.pagenav_next > a')
print('End of site') if len(next_link) == 0:
break print('End of site')
break
url = next_link[0].attrs['href']
url = next_link[0].attrs['href']
scrape_site('http://subs.com.ru/list.php?c=enganime&p=5&w=asc&d=1')
scrape_site('http://subs.com.ru/list.php?c=enganime&p=5&w=asc&d=1')

View File

@@ -1,15 +1,15 @@
<!DOCTYPE html> <!DOCTYPE html>
<meta charset="utf-8"> <meta charset="utf-8">
<title>JavaScript</title> <title>JavaScript</title>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<h1>HTML/JavaScript mini-projects</h1> <h1>HTML/JavaScript mini-projects</h1>
<ul> <ul>
<li><a href="reaction/reaction.html">Reaction test</a></li> <li><a href="reaction/reaction.html">Reaction test</a></li>
<li><a href="trill/trill.html">Trill test</a></li> <li><a href="trill/trill.html">Trill test</a></li>
<li><a href="mania/mania.html">osu!mania playfield simulator</a></li> <li><a href="mania/mania.html">osu!mania playfield simulator</a></li>
</ul> </ul>

View File

@@ -1,36 +1,36 @@
<!DOCTYPE html> <!DOCTYPE html>
<meta charset="utf-8"> <meta charset="utf-8">
<title>osu!mania playfield</title> <title>osu!mania playfield</title>
<link rel="stylesheet" href="../style.css"> <link rel="stylesheet" href="../style.css">
<script src="../shared.js"></script> <script src="../shared.js"></script>
<script src="mania.js"></script> <script src="mania.js"></script>
<canvas id="playfield" width="800" height="600" style="border: 1px solid #000000"></canvas> <canvas id="playfield" width="800" height="600" style="border: 1px solid #000000"></canvas>
<br> <br>
<label for="columnstart">Column start</label><br> <label for="columnstart">Column start</label><br>
<input type="range" id="columnstart" min="0" max="200" value="150"> <input type="range" id="columnstart" min="0" max="200" value="150">
<output id="columnstart_out"></output><br> <output id="columnstart_out"></output><br>
<label for="columnwidth">Column width</label><br> <label for="columnwidth">Column width</label><br>
<input type="range" id="columnwidth" min="16" max="70" value="40"> <input type="range" id="columnwidth" min="16" max="70" value="40">
<output id="columnwidth_out"></output><br> <output id="columnwidth_out"></output><br>
<label for="hitposition">Hit position</label><br> <label for="hitposition">Hit position</label><br>
<input type="range" id="hitposition" min="350" max="480" value="420"> <input type="range" id="hitposition" min="350" max="480" value="420">
<output id="hitposition_out"></output><br> <output id="hitposition_out"></output><br>
<label for="scrollspeed">Scroll speed</label><br> <label for="scrollspeed">Scroll speed</label><br>
<input type="range" id="scrollspeed" min="12" max="40" value="28"> <input type="range" id="scrollspeed" min="12" max="40" value="28">
<output id="scrollspeed_out"></output><br> <output id="scrollspeed_out"></output><br>
<label for="noteratio">Note ratio</label><br> <label for="noteratio">Note ratio</label><br>
<input type="range" id="noteratio" min="0" max="1" value="0.5" step="0.1"> <input type="range" id="noteratio" min="0" max="1" value="0.5" step="0.1">
<output id="noteratio_out"></output><br> <output id="noteratio_out"></output><br>
<label for="keycount">Key count</label><br> <label for="keycount">Key count</label><br>
<input type="range" id="keycount" min="4" max="9" value="7"> <input type="range" id="keycount" min="4" max="9" value="7">
<output id="keycount_out"></output><br> <output id="keycount_out"></output><br>

View File

@@ -1,112 +1,112 @@
var canvas; var canvas;
var ctx; var ctx;
/* Base resolution in osu! skins used for scaling */ /* Base resolution in osu! skins used for scaling */
const internal_width = 640; const internal_width = 640;
const internal_height = 480; const internal_height = 480;
/* Updates per second */ /* Updates per second */
const framerate = 60; const framerate = 60;
/* Colors for playfield */ /* Colors for playfield */
const colors = { const colors = {
playfield: "#000", playfield: "#000",
lane_separator: "#222", lane_separator: "#222",
hitposition: "#AA0", hitposition: "#AA0",
note: "#FFF" note: "#FFF"
}; };
/* Values retrieved from DOM */ /* Values retrieved from DOM */
var options = { var options = {
columnstart: 0, columnstart: 0,
columnwidth: 0, columnwidth: 0,
hitposition: 0, hitposition: 0,
scrollspeed: 0, scrollspeed: 0,
noteratio: 0, noteratio: 0,
keycount: 0 keycount: 0
} }
/* Clears the canvas */ /* Clears the canvas */
function clear() { function clear() {
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
} }
/* Draws a rectangle */ /* Draws a rectangle */
function rect(x, y, w, h, color) { function rect(x, y, w, h, color) {
ctx.fillStyle = color; ctx.fillStyle = color;
ctx.fillRect(x, y, w, h); ctx.fillRect(x, y, w, h);
} }
/* Draws a string */ /* Draws a string */
function text(string, x, y, color) { function text(string, x, y, color) {
ctx.fillStyle = color; ctx.fillStyle = color;
ctx.fillText(string, x, y); ctx.fillText(string, x, y);
} }
/* Translates osu! coordinates to screen coordinates */ /* Translates osu! coordinates to screen coordinates */
function translate_pos(x, y) { function translate_pos(x, y) {
return { return {
x: Math.floor(x / internal_width * canvas.width), x: Math.floor(x / internal_width * canvas.width),
y: Math.floor(y / internal_height * canvas.height) y: Math.floor(y / internal_height * canvas.height)
} }
} }
function draw() { function draw() {
clear() clear()
const columnstart = translate_pos(options.columnstart, 0); const columnstart = translate_pos(options.columnstart, 0);
const columnwidth = translate_pos(options.columnwidth, 0); const columnwidth = translate_pos(options.columnwidth, 0);
const hitposition = translate_pos(options.columnstart, options.hitposition); const hitposition = translate_pos(options.columnstart, options.hitposition);
const playfield_width = columnwidth.x * options.keycount; const playfield_width = columnwidth.x * options.keycount;
const note_height = columnwidth.x * options.noteratio; const note_height = columnwidth.x * options.noteratio;
// playfield background // playfield background
rect(columnstart.x, 0, playfield_width, canvas.height, colors.playfield); rect(columnstart.x, 0, playfield_width, canvas.height, colors.playfield);
// lane separators // lane separators
for (var i = 0; i <= options.keycount; i++) { for (var i = 0; i <= options.keycount; i++) {
rect(columnstart.x + i * columnwidth.x, 0, 1, canvas.height, colors.lane_separator); rect(columnstart.x + i * columnwidth.x, 0, 1, canvas.height, colors.lane_separator);
} }
// hitpos // hitpos
rect(hitposition.x, hitposition.y, playfield_width, 5, colors.hitposition); rect(hitposition.x, hitposition.y, playfield_width, 5, colors.hitposition);
// notes // notes
let y_pos = hitposition.y - note_height; let y_pos = hitposition.y - note_height;
while (y_pos > 0) { while (y_pos > 0) {
for (let i = 0; i < options.keycount; ++i) { for (let i = 0; i < options.keycount; ++i) {
rect ( rect (
columnstart.x + i * columnwidth.x, columnstart.x + i * columnwidth.x,
y_pos, y_pos,
columnwidth.x, note_height, colors.note columnwidth.x, note_height, colors.note
); );
// completely inaccurate but i cba to simulate the whole playfield // completely inaccurate but i cba to simulate the whole playfield
y_pos -= options.scrollspeed * 3; y_pos -= options.scrollspeed * 3;
} }
} }
} }
window.onload = function () { window.onload = function () {
create_prologue(); create_prologue();
canvas = document.getElementById("playfield"); canvas = document.getElementById("playfield");
ctx = canvas.getContext("2d"); ctx = canvas.getContext("2d");
ctx.font = "15px Arial"; ctx.font = "15px Arial";
ctx.textBaseline = "hanging"; ctx.textBaseline = "hanging";
for (let input of document.getElementsByTagName("input")) { for (let input of document.getElementsByTagName("input")) {
input.onchange = function () { input.onchange = function () {
options[this.id] = this.value; options[this.id] = this.value;
document.getElementById(this.id + "_out").innerText = this.value; document.getElementById(this.id + "_out").innerText = this.value;
}; };
input.onchange(); input.onchange();
} }
setInterval(function () { setInterval(function () {
draw(); draw();
}, 1000 / framerate); }, 1000 / framerate);
}; };

View File

@@ -1,14 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Reaction time test</title> <title>Reaction time test</title>
<link rel="stylesheet" href="../style.css"> <link rel="stylesheet" href="../style.css">
<link rel="stylesheet" href="area.css"> <link rel="stylesheet" href="area.css">
<script src="../shared.js"></script> <script src="../shared.js"></script>
<script src="reaction.js"></script> <script src="reaction.js"></script>
<div id="area"></div> <div id="area"></div>
<h3 id="average"></h3> <h3 id="average"></h3>
<ul id="times"></ul> <ul id="times"></ul>

View File

@@ -1,88 +1,88 @@
const states = { const states = {
START: 'start', START: 'start',
TIMEOUT: 'timeout', TIMEOUT: 'timeout',
READY: 'ready' READY: 'ready'
} }
const colors = { const colors = {
TIMEOUT: 'crimson', TIMEOUT: 'crimson',
START: 'dodgerblue', START: 'dodgerblue',
READY: 'limegreen' READY: 'limegreen'
} }
var state = states.START; var state = states.START;
var times = []; var times = [];
var ready_time; var ready_time;
var ready_id; // timeout id var ready_id; // timeout id
const min_time = 1000; const min_time = 1000;
const max_time = 3000; const max_time = 3000;
function handle_click() { function handle_click() {
switch (state) { switch (state) {
// click received on start, activate timer and set state to timeout // click received on start, activate timer and set state to timeout
case states.START: { case states.START: {
// this is a hack to access thisptr from setTimeout // this is a hack to access thisptr from setTimeout
let self = this; let self = this;
ready_id = setTimeout(function () { ready_id = setTimeout(function () {
ready_time = Date.now(); ready_time = Date.now();
self.style["background-color"] = colors.READY; self.style["background-color"] = colors.READY;
self.innerText = "Click now!"; self.innerText = "Click now!";
state = states.READY; state = states.READY;
}, min_time + (Math.random() * (max_time - min_time))); }, min_time + (Math.random() * (max_time - min_time)));
this.style["background-color"] = colors.TIMEOUT; this.style["background-color"] = colors.TIMEOUT;
this.innerText = "Get ready!"; this.innerText = "Get ready!";
state = states.TIMEOUT; state = states.TIMEOUT;
} break; } break;
// click received during timeout, clear timeout and reset // click received during timeout, clear timeout and reset
case states.TIMEOUT: { case states.TIMEOUT: {
clearTimeout(ready_id); clearTimeout(ready_id);
this.style["background-color"] = colors.START; this.style["background-color"] = colors.START;
this.innerText = "Too early!"; this.innerText = "Too early!";
state = states.START; state = states.START;
} break; } break;
// click received after timeout, calculate score and reset // click received after timeout, calculate score and reset
case states.READY: { case states.READY: {
let time = (Date.now() - ready_time); let time = (Date.now() - ready_time);
times.push(time); times.push(time);
let average = times.reduce((a, b) => a + b) / times.length; let average = times.reduce((a, b) => a + b) / times.length;
// update average text // update average text
document.getElementById("average").innerText = "Average: " + average + "ms"; document.getElementById("average").innerText = "Average: " + average + "ms";
// create and add time listing // create and add time listing
var li = document.createElement("li"); var li = document.createElement("li");
li.appendChild(document.createTextNode(time + "ms")); li.appendChild(document.createTextNode(time + "ms"));
document.getElementById("times").appendChild(li); document.getElementById("times").appendChild(li);
this.style["background-color"] = colors.START; this.style["background-color"] = colors.START;
this.innerText = time + "ms"; this.innerText = time + "ms";
state = states.START; state = states.START;
} break; } break;
default: default:
break break
} }
} }
window.onload = function () { window.onload = function () {
create_prologue(); create_prologue();
let area = document.getElementById("area"); let area = document.getElementById("area");
area.innerText = "Click here to begin!"; area.innerText = "Click here to begin!";
area.onclick = handle_click; area.onclick = handle_click;
} }

View File

@@ -1,13 +1,13 @@
body { body {
color: #444; color: #444;
font: 18px/1.6 Arial, Helvetica, sans-serif; font: 18px/1.6 Arial, Helvetica, sans-serif;
margin: 40px auto; margin: 40px auto;
max-width: 650px; max-width: 650px;
padding: 0 10px; padding: 0 10px;
} }
h1, h1,
h2, h2,
h3 { h3 {
line-height: 1.2 line-height: 1.2
} }

View File

@@ -1,14 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Trill test</title> <title>Trill test</title>
<link rel="stylesheet" href="../style.css"> <link rel="stylesheet" href="../style.css">
<link rel="stylesheet" href="area.css"> <link rel="stylesheet" href="area.css">
<script src="../shared.js"></script> <script src="../shared.js"></script>
<script src="trill.js"></script> <script src="trill.js"></script>
<div id="area"></div> <div id="area"></div>
<h3 id="average"></h3> <h3 id="average"></h3>
<ul id="times"></ul> <ul id="times"></ul>

View File

@@ -1,102 +1,102 @@
const states = { const states = {
GETKEYS: 'getkeys', GETKEYS: 'getkeys',
TRILLING: 'trilling', TRILLING: 'trilling',
READY: 'ready', READY: 'ready',
RESULT: 'result' RESULT: 'result'
} }
const colors = { const colors = {
GETKEYS: 'gray', GETKEYS: 'gray',
TRILLING: 'crimson', TRILLING: 'crimson',
READY: 'darkgray', READY: 'darkgray',
RESULT: 'dodgerblue' RESULT: 'dodgerblue'
} }
var state = states.GETKEYS; var state = states.GETKEYS;
var times = [] var times = []
const max_count = 20; const max_count = 20;
var key1, key2; var key1, key2;
var time_start; var time_start;
var counter = 0; var counter = 0;
function handle_press(e) { function handle_press(e) {
switch (state) { switch (state) {
case states.GETKEYS: { case states.GETKEYS: {
if (!key1) { if (!key1) {
key1 = e.code; key1 = e.code;
area.style["background-color"] = colors.GETKEYS; area.style["background-color"] = colors.GETKEYS;
area.innerText = "Press 2nd key!"; area.innerText = "Press 2nd key!";
} else { } else {
key2 = e.code; key2 = e.code;
state = states.READY; state = states.READY;
area.style["background-color"] = colors.READY; area.style["background-color"] = colors.READY;
area.innerText = "Test will start on first keypress."; area.innerText = "Test will start on first keypress.";
} }
} break; } break;
case states.READY: { case states.READY: {
if (e.code == key1 || e.code == key2) { if (e.code == key1 || e.code == key2) {
state = states.TRILLING; state = states.TRILLING;
time_start = Date.now(); time_start = Date.now();
area.style["background-color"] = colors.TRILLING; area.style["background-color"] = colors.TRILLING;
handle_press(e); // update couter/text for first keypress handle_press(e); // update couter/text for first keypress
} }
} break; } break;
case states.TRILLING: { case states.TRILLING: {
if (e.code == key1 || e.code == key2) { if (e.code == key1 || e.code == key2) {
counter++; counter++;
} }
area.innerText = counter + "/" + max_count; area.innerText = counter + "/" + max_count;
if (counter == max_count) { if (counter == max_count) {
state = states.RESULT; state = states.RESULT;
counter = 0; counter = 0;
let time = parseInt((max_count / ((Date.now() - time_start) / 1000) * 60 / 4)); let time = parseInt((max_count / ((Date.now() - time_start) / 1000) * 60 / 4));
times.push(time); times.push(time);
let average = times.reduce((a, b) => a + b) / times.length; let average = times.reduce((a, b) => a + b) / times.length;
document.getElementById("average").innerText = "Average: " + average + "bpm"; document.getElementById("average").innerText = "Average: " + average + "bpm";
var li = document.createElement("li"); var li = document.createElement("li");
li.appendChild(document.createTextNode(time + "bpm")); li.appendChild(document.createTextNode(time + "bpm"));
document.getElementById("times").appendChild(li); document.getElementById("times").appendChild(li);
area.style["background-color"] = colors.RESULT; area.style["background-color"] = colors.RESULT;
area.innerText = time + "bpm" + '\n(press space to try again)'; area.innerText = time + "bpm" + '\n(press space to try again)';
} }
} break; } break;
case states.RESULT: { case states.RESULT: {
if (e.code == "Space") { if (e.code == "Space") {
state = states.READY; state = states.READY;
area.style["background-color"] = colors.READY; area.style["background-color"] = colors.READY;
area.innerText = "Test will start on first keypress."; area.innerText = "Test will start on first keypress.";
} }
} break; } break;
default: default:
break break
} }
} }
window.onload = function () { window.onload = function () {
create_prologue(); create_prologue();
area = document.getElementById("area"); area = document.getElementById("area");
area.innerText = "Press 1st key!"; area.innerText = "Press 1st key!";
document.addEventListener('keydown', handle_press); document.addEventListener('keydown', handle_press);
} }