poc/1- but with plainole leaky bucket

master
Bel LaPointe 2022-04-12 15:41:07 -06:00
parent ae7b8ceaba
commit 1b38935cb0
11 changed files with 1656 additions and 0 deletions

36
poc/2-py-rps/buttons.py Normal file
View File

@ -0,0 +1,36 @@
from Xlib.display import Display
from Xlib.ext.xtest import fake_input
from Xlib import X
from os import environ
_display = Display(environ['DISPLAY'])
def tap(keycode):
down(keycode)
up(keycode)
def down(keycode):
fake_input(_display, X.KeyPress, keycode)
_display.sync()
def up(keycode):
fake_input(_display, X.KeyRelease, keycode)
_display.sync()
def __init_keys__():
import subprocess
_p = subprocess.run(
"xmodmap -pke".split(),
capture_output=True,
)
assert(_p.returncode == 0)
stdout = _p.stdout
result = []
for line in stdout.split("\n".encode()):
if line:
words = line.split()
key = int(words[1])
if len(words) < 4:
result.append(key)
return result
keys = __init_keys__()

View File

@ -0,0 +1 @@
pyautogui

View File

@ -0,0 +1,37 @@
import argparse
import os
from time import sleep
#import buttons
def main():
args = get_args()
buckets = {}
with open(args.p, "r") as f:
f.seek(0, os.SEEK_END)
while True:
line = f.readline().strip()
if not line:
sleep(0.25)
continue
key = line.strip("/").split()[0]
if not key in buckets:
buckets[key] = [False, len(buckets)]
buckets[key][0] = False if line[0] == "/" else float(line.split()[-1])
for key in buckets:
#keycode = buttons.keys[bucket[key][1]]
if buckets[key][0]:
print("down", key, end=" ") #, button[key])
#buttons.down(keycode)
else:
print("up", key, end=" ") #, button[key])
#buttons.up(keycode)
print()
def get_args():
ap = argparse.ArgumentParser()
ap.add_argument("-p", type=str, help="path to write out to", default="/tmp/cbappend.both.txt")
return ap.parse_args()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,164 @@
import signal
from os import getpid, kill
import time
import argparse
def main():
args = get_args()
with_(
N=args.n,
M=args.m,
R=args.r,
T=args.t,
p=args.p,
)
def get_args():
ap = argparse.ArgumentParser()
ap.add_argument("-n", type=int, help="queue capacity", default=3)
ap.add_argument("-m", type=int, help="queue fill line", default=3)
ap.add_argument("-r", type=int, help="drain rate per second", default=2)
ap.add_argument("-t", type=int, help="threshold for state", default=2)
ap.add_argument("-p", type=str, help="path to write out to", default="/tmp/cbappend.both.txt")
return ap.parse_args()
def with_(N, M, R, T, p):
triggered = CBAppend(p)
released = CBAppend(p)
cb = CBFork(triggered, released)
buckets = {}
while True:
got = readline()
if got:
if not got in buckets:
buckets[got] = Bucket(N, M, R, T, cb.cb(got))
buckets[got].push()
# TODO no /state
[buckets[i].pop() for i in buckets]
def readline():
def __input(*args):
return input()
def _input(*args):
try:
foo = __input()
except Exception as e:
foo = None
return foo
timeout = 1
signal.signal(signal.SIGALRM, __input)
signal.alarm(timeout)
foo = _input()
return foo
class State():
def __init__(self, active, f):
self.active = active
self.f = f
class Bucket():
def __init__(self, N, M, R, T, CB):
self.q = 0.0
self.N = N
self.M = M
self.R = R
self.T = T
self.CB = CB
self.__last_pop = 0
self.__last_state = False
def push(self):
result = self.__push_c(1)
self.__cb()
return result
def pop(self):
result = self.__pop()
self.__cb()
return result
def __cb(self):
new_state = self.q > self.T
if new_state == self.__last_state:
return
self.__last_state = new_state
filledness = int(
100*(
max(
[self.q-self.T, 0]
)/max(
[self.M-self.T, 1]
)
)
)/100.0
if filledness > 1.0:
filledness = 1.0
self.CB(State(new_state, filledness))
def state(self):
return self.__last_state
def __push_c(self, c):
self.__pop()
if self.q+c > self.N:
return False
self.q += c
return True
def __pop(self):
now = self.__now()
remove_up_to = (now - self.__last_pop) / self.R
if remove_up_to > self.q:
remove_up_to = self.q
self.q -= remove_up_to
self.__last_pop = now
def __now(self):
return time.time()
class CBSignals():
def __init__(self, pid, signal_triggered, signal_released):
self.__pid = pid
self.__signal_triggered = signal_triggered
self.__signal_released = signal_released
def cb(self, payload):
def cb(state):
print(f"state is now {state}")
kill(
self.__pid,
self.__signal_triggered if state.active else self.__signal_released,
)
handler = lambda s, f: print("SIGNAL:", s)
signal.signal(self.__signal_triggered, handler)
signal.signal(self.__signal_released, handler)
return cb
class CBAppend():
def __init__(self, path):
self.__path = path
def cb(self, payload):
def cb(state):
with open(self.__path, "a") as f:
f.write(f"{'/' if not state.active else ''}{payload} {state.f}\n")
return cb
class CBFork():
def __init__(self, triggered, released):
self.__triggered = triggered
self.__released = released
def cb(self, payload):
cb_triggered = self.__triggered.cb(payload)
cb_released = self.__released.cb(payload)
def cb(state):
if state.active:
return cb_triggered(state)
return cb_released(state)
return cb
if __name__ == "__main__":
main()

33
poc/2-py-rps/test.sh Normal file
View File

@ -0,0 +1,33 @@
#! /bin/bash
set -e
set -o pipefail
peek() {
while read -r line; do
echo $line
#echo $line >&2
done
}
cleanup() {
kill -9 $(jobs -p) || true
}
trap cleanup EXIT
python3 ./state_to_buttons.py &
python3 ./testdata/rand_0_n_weighted_stream.py \
-n 6 \
-b-min 1 \
-b-max 10 \
-d-min 100 \
-d-max 3000 \
-between 100 \
-b-min 10 \
-b-max 100 \
-d-min 100 \
-d-max 3000 \
-between 10 \
-w 3 \
| peek \
| python3 ./stream_to_state.py

9
poc/2-py-rps/testdata/lorem.txt vendored Normal file
View File

@ -0,0 +1,9 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eu mi bibendum neque egestas congue quisque egestas. Semper eget duis at tellus at urna. Ac turpis egestas sed tempus urna et. Viverra nibh cras pulvinar mattis nunc sed blandit libero volutpat. Rhoncus aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque. Tincidunt arcu non sodales neque sodales ut etiam. Sit amet aliquam id diam. Non blandit massa enim nec dui. Leo urna molestie at elementum. Sed adipiscing diam donec adipiscing tristique. Duis at consectetur lorem donec. Fringilla phasellus faucibus scelerisque eleifend donec pretium vulputate sapien. Adipiscing commodo elit at imperdiet dui accumsan. Ultricies lacus sed turpis tincidunt id aliquet risus feugiat in. Commodo ullamcorper a lacus vestibulum sed arcu non odio euismod. Malesuada bibendum arcu vitae elementum curabitur vitae nunc sed. Morbi tempus iaculis urna id volutpat lacus laoreet non curabitur. Nec nam aliquam sem et tortor consequat id.
Iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Cursus mattis molestie a iaculis at. Proin nibh nisl condimentum id venenatis. Proin nibh nisl condimentum id venenatis a condimentum vitae. A diam maecenas sed enim ut sem viverra aliquet. Id volutpat lacus laoreet non curabitur. At urna condimentum mattis pellentesque. Eu mi bibendum neque egestas congue quisque egestas diam in. Egestas dui id ornare arcu odio. Convallis convallis tellus id interdum velit laoreet id donec. Mattis aliquam faucibus purus in. In massa tempor nec feugiat nisl pretium fusce id. Euismod in pellentesque massa placerat duis. Pellentesque diam volutpat commodo sed egestas egestas fringilla. Pharetra pharetra massa massa ultricies mi quis hendrerit dolor.
Odio eu feugiat pretium nibh ipsum consequat nisl vel. Quis commodo odio aenean sed adipiscing diam. Ut sem nulla pharetra diam sit. Risus sed vulputate odio ut enim. Morbi tincidunt ornare massa eget egestas purus. Viverra accumsan in nisl nisi scelerisque eu ultrices vitae auctor. Faucibus scelerisque eleifend donec pretium vulputate sapien nec sagittis aliquam. Id faucibus nisl tincidunt eget nullam non. Feugiat scelerisque varius morbi enim nunc. In tellus integer feugiat scelerisque varius. Semper feugiat nibh sed pulvinar proin gravida hendrerit lectus.
Ultrices gravida dictum fusce ut placerat orci nulla. Sodales ut etiam sit amet nisl purus in mollis. Cras ornare arcu dui vivamus arcu felis. Sit amet massa vitae tortor. Ornare arcu odio ut sem nulla pharetra diam. Amet commodo nulla facilisi nullam vehicula ipsum. Porta non pulvinar neque laoreet suspendisse interdum consectetur libero. Dui sapien eget mi proin sed. Enim sit amet venenatis urna cursus eget nunc scelerisque viverra. Eget nunc scelerisque viverra mauris in. Mauris sit amet massa vitae tortor condimentum. Id faucibus nisl tincidunt eget nullam non nisi est sit. Et odio pellentesque diam volutpat. Dignissim convallis aenean et tortor at. Amet massa vitae tortor condimentum lacinia quis vel eros donec. Pretium fusce id velit ut tortor pretium viverra suspendisse potenti. Quis varius quam quisque id diam vel quam. Tellus in metus vulputate eu scelerisque felis imperdiet proin fermentum. Adipiscing diam donec adipiscing tristique risus nec.
Ullamcorper morbi tincidunt ornare massa. Lacus sed turpis tincidunt id aliquet risus feugiat in ante. Turpis massa tincidunt dui ut ornare. Sed elementum tempus egestas sed sed. Eu mi bibendum neque egestas congue quisque. Euismod in pellentesque massa placerat. Dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. At tempor commodo ullamcorper a lacus. Sed viverra ipsum nunc aliquet bibendum. Volutpat commodo sed egestas egestas fringilla phasellus faucibus scelerisque. Amet consectetur adipiscing elit duis tristique sollicitudin nibh sit amet. Aliquam vestibulum morbi blandit cursus risus. Sit amet cursus sit amet dictum sit amet justo. Pellentesque elit eget gravida cum sociis natoque penatibus et magnis. Ultrices eros in cursus turpis massa tincidunt dui ut ornare. Ut pharetra sit amet aliquam id diam maecenas ultricies mi. Facilisi cras fermentum odio eu.

630
poc/2-py-rps/testdata/rand_0_13.txt vendored Normal file
View File

@ -0,0 +1,630 @@
10
1
11
3
11
11
4
5
2
3
8
7
2
4
7
5
8
13
0
4
8
3
0
11
6
1
11
7
13
13
8
13
8
3
7
9
11
2
8
3
5
10
7
7
2
2
8
2
10
3
7
10
13
0
5
10
11
2
2
2
5
4
5
9
0
9
4
4
3
11
6
8
0
5
10
1
2
9
0
1
3
7
8
6
2
4
0
13
4
7
13
8
11
10
13
6
13
12
10
5
13
9
2
12
4
5
5
8
7
0
6
4
0
2
9
5
8
6
13
0
0
5
2
11
0
7
2
4
5
8
5
1
3
4
6
6
8
6
8
2
6
8
7
3
8
7
0
2
5
8
9
8
6
9
5
3
3
8
7
8
2
2
4
5
5
8
7
8
2
7
11
7
8
6
7
9
2
8
2
6
7
9
2
8
2
11
2
6
11
0
10
2
2
4
9
10
6
8
7
0
2
5
8
8
3
2
2
2
4
8
3
0
11
6
1
11
0
0
11
0
8
7
4
8
2
2
13
8
8
11
2
8
13
2
6
12
5
0
0
1
7
9
0
9
9
4
8
5
0
2
1
8
13
2
0
7
5
2
11
11
6
5
5
1
1
4
8
6
7
11
8
4
0
9
7
1
3
9
0
6
5
8
13
2
4
0
4
9
5
5
0
3
13
2
2
8
4
2
6
5
7
1
13
11
5
10
6
0
9
2
10
4
7
6
12
12
10
5
13
9
2
12
9
0
6
8
12
9
5
13
8
5
0
10
5
6
2
8
0
13
2
0
10
5
7
0
7
2
2
6
13
7
2
7
13
7
4
4
8
4
5
9
4
4
3
11
9
5
0
8
7
7
4
0
1
4
8
3
11
1
6
3
7
4
8
4
9
5
5
0
11
5
5
5
8
7
1
9
5
2
0
2
0
8
11
3
0
12
13
8
6
2
2
3
11
2
3
8
13
8
10
10
13
8
10
10
11
0
11
3
11
1
6
3
2
8
12
9
5
13
8
5
2
4
3
5
8
2
0
7
2
2
13
5
3
8
11
1
6
3
2
7
6
0
9
13
9
4
8
11
4
3
9
10
0
8
6
5
0
1
8
0
0
0
13
0
3
2
4
10
8
7
6
7
4
0
13
4
7
13
9
2
6
5
7
1
0
2
9
5
8
6
13
0
0
1
9
1
5
0
4
7
2
6
8
11
2
2
4
8
3
0
11
6
1
5
0
2
1
8
11
3
11
11
4
5
2
5
6
8
7
5
2
11
0
2
10
1
8
6
3
7
5
2
11
11
6
13
12
10
11
11
4
5
13
7
3
7
3
11
6
7
6
10
8
13
3
11
8
3
11
7
3
11
11
2
5
13
13
8
8
8
12
5
7
7
9
0
8
9
1
5
0
4
7
4
5
3
11
6
8
0
10
4
8
5
7
7
8
4

View File

@ -0,0 +1,33 @@
import time
import random
from sys import stdout
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-b-min", type=int, help="burst minimum", default=1)
ap.add_argument("-b-max", type=int, help="burst maximum", default=20)
ap.add_argument("-d-min", type=int, help="sleep minimum ms", default=0)
ap.add_argument("-d-max", type=int, help="sleep maximum ms", default=3000)
ap.add_argument("-between", type=int, help="between maximum ms", default=1000)
args = ap.parse_args()
random.seed(int(1000*time.time()))
def new_burst():
return random.randint(args.b_min, args.b_max)
def new_between():
return random.randint(0, args.between) / 1000.0
def new_delay():
return random.randint(args.d_min, args.d_max) / 1000.0
with open("testdata/rand_0_13.txt", "r") as f:
burst = new_burst()
for line in f.readlines():
if burst:
print(line.strip(), file=stdout)
stdout.flush()
time.sleep(new_between())
burst -= 1
if not burst:
time.sleep(new_delay())
burst = new_burst()

View File

@ -0,0 +1,34 @@
import time
import random
from sys import stdout
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-b-min", type=int, help="burst minimum", default=1)
ap.add_argument("-b-max", type=int, help="burst maximum", default=20)
ap.add_argument("-d-min", type=int, help="sleep minimum ms", default=0)
ap.add_argument("-d-max", type=int, help="sleep maximum ms", default=3000)
ap.add_argument("-between", type=int, help="between maximum ms", default=1000)
ap.add_argument("-n", type=int, help="max to gen", default=14)
args = ap.parse_args()
random.seed(int(1000*time.time()))
def new_burst():
return random.randint(args.b_min, args.b_max)
def new_between():
return random.randint(0, args.between) / 1000.0
def new_delay():
return random.randint(args.d_min, args.d_max) / 1000.0
burst = new_burst()
while True:
line = random.randint(0, args.n-1)
if burst:
print(line, file=stdout)
stdout.flush()
time.sleep(new_between())
burst -= 1
if not burst:
time.sleep(new_delay())
burst = new_burst()

View File

@ -0,0 +1,49 @@
import time
import random
from sys import stdout
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-b-min", type=int, help="burst minimum", default=1)
ap.add_argument("-b-max", type=int, help="burst maximum", default=20)
ap.add_argument("-d-min", type=int, help="sleep minimum ms", default=0)
ap.add_argument("-d-max", type=int, help="sleep maximum ms", default=3000)
ap.add_argument("-between", type=int, help="between maximum ms", default=1000)
ap.add_argument("-n", type=int, help="max to gen", default=14)
ap.add_argument("-w", type=int, help="weight scalar", default=1)
ap.add_argument("-r-min", type=float, help="rotation interval min", default=1500)
ap.add_argument("-r-max", type=float, help="rotation interval max", default=5000)
args = ap.parse_args()
random.seed(int(1000*time.time()))
def new_burst():
return random.randint(args.b_min, args.b_max)
def new_between():
return random.randint(0, args.between) / 1000.0
def new_delay():
return random.randint(args.d_min, args.d_max) / 1000.0
def new_rotation_deadline():
return time.time() + random.randint(args.r_min, args.r_max) / 1000.0
def new_rotation():
return random.randint(0, args.n-1)
pool = []
for i in range(args.n):
pool.extend([i for _ in range(i**args.w)])
burst = new_burst()
rotation_deadline = new_rotation_deadline()
rotation = new_rotation()
while True:
line = (pool[random.randint(0, len(pool)-1)] + rotation) % args.n
if burst:
print(line, file=stdout)
stdout.flush()
time.sleep(new_between())
burst -= 1
if not burst:
time.sleep(new_delay())
burst = new_burst()
if time.time() >= rotation_deadline:
rotation = (rotation + new_rotation()) % args.n
rotation_deadline = new_rotation_deadline()

630
poc/2-py-rps/testdata/words.txt vendored Normal file
View File

@ -0,0 +1,630 @@
lorem
ipsum
dolor
sit
amet,
consectetur
adipiscing
elit,
sed
do
eiusmod
tempor
incididunt
ut
labore
et
dolore
magna
aliqua
eu
mi
bibendum
neque
egestas
congue
quisque
egestas
semper
eget
duis
at
tellus
at
urna
ac
turpis
egestas
sed
tempus
urna
et
viverra
nibh
cras
pulvinar
mattis
nunc
sed
blandit
libero
volutpat
rhoncus
aenean
vel
elit
scelerisque
mauris
pellentesque
pulvinar
pellentesque
tincidunt
arcu
non
sodales
neque
sodales
ut
etiam
sit
amet
aliquam
id
diam
non
blandit
massa
enim
nec
dui
leo
urna
molestie
at
elementum
sed
adipiscing
diam
donec
adipiscing
tristique
duis
at
consectetur
lorem
donec
fringilla
phasellus
faucibus
scelerisque
eleifend
donec
pretium
vulputate
sapien
adipiscing
commodo
elit
at
imperdiet
dui
accumsan
ultricies
lacus
sed
turpis
tincidunt
id
aliquet
risus
feugiat
in
commodo
ullamcorper
a
lacus
vestibulum
sed
arcu
non
odio
euismod
malesuada
bibendum
arcu
vitae
elementum
curabitur
vitae
nunc
sed
morbi
tempus
iaculis
urna
id
volutpat
lacus
laoreet
non
curabitur
nec
nam
aliquam
sem
et
tortor
consequat
id
iaculis
at
erat
pellentesque
adipiscing
commodo
elit
at
imperdiet
cursus
mattis
molestie
a
iaculis
at
proin
nibh
nisl
condimentum
id
venenatis
proin
nibh
nisl
condimentum
id
venenatis
a
condimentum
vitae
a
diam
maecenas
sed
enim
ut
sem
viverra
aliquet
id
volutpat
lacus
laoreet
non
curabitur
at
urna
condimentum
mattis
pellentesque
eu
mi
bibendum
neque
egestas
congue
quisque
egestas
diam
in
egestas
dui
id
ornare
arcu
odio
convallis
convallis
tellus
id
interdum
velit
laoreet
id
donec
mattis
aliquam
faucibus
purus
in
in
massa
tempor
nec
feugiat
nisl
pretium
fusce
id
euismod
in
pellentesque
massa
placerat
duis
pellentesque
diam
volutpat
commodo
sed
egestas
egestas
fringilla
pharetra
pharetra
massa
massa
ultricies
mi
quis
hendrerit
dolor
odio
eu
feugiat
pretium
nibh
ipsum
consequat
nisl
vel
quis
commodo
odio
aenean
sed
adipiscing
diam
ut
sem
nulla
pharetra
diam
sit
risus
sed
vulputate
odio
ut
enim
morbi
tincidunt
ornare
massa
eget
egestas
purus
viverra
accumsan
in
nisl
nisi
scelerisque
eu
ultrices
vitae
auctor
faucibus
scelerisque
eleifend
donec
pretium
vulputate
sapien
nec
sagittis
aliquam
id
faucibus
nisl
tincidunt
eget
nullam
non
feugiat
scelerisque
varius
morbi
enim
nunc
in
tellus
integer
feugiat
scelerisque
varius
semper
feugiat
nibh
sed
pulvinar
proin
gravida
hendrerit
lectus
ultrices
gravida
dictum
fusce
ut
placerat
orci
nulla
sodales
ut
etiam
sit
amet
nisl
purus
in
mollis
cras
ornare
arcu
dui
vivamus
arcu
felis
sit
amet
massa
vitae
tortor
ornare
arcu
odio
ut
sem
nulla
pharetra
diam
amet
commodo
nulla
facilisi
nullam
vehicula
ipsum
porta
non
pulvinar
neque
laoreet
suspendisse
interdum
consectetur
libero
dui
sapien
eget
mi
proin
sed
enim
sit
amet
venenatis
urna
cursus
eget
nunc
scelerisque
viverra
eget
nunc
scelerisque
viverra
mauris
in
mauris
sit
amet
massa
vitae
tortor
condimentum
id
faucibus
nisl
tincidunt
eget
nullam
non
nisi
est
sit
et
odio
pellentesque
diam
volutpat
dignissim
convallis
aenean
et
tortor
at
amet
massa
vitae
tortor
condimentum
lacinia
quis
vel
eros
donec
pretium
fusce
id
velit
ut
tortor
pretium
viverra
suspendisse
potenti
quis
varius
quam
quisque
id
diam
vel
quam
tellus
in
metus
vulputate
eu
scelerisque
felis
imperdiet
proin
fermentum
adipiscing
diam
donec
adipiscing
tristique
risus
nec
ullamcorper
morbi
tincidunt
ornare
massa
lacus
sed
turpis
tincidunt
id
aliquet
risus
feugiat
in
ante
turpis
massa
tincidunt
dui
ut
ornare
sed
elementum
tempus
egestas
sed
sed
eu
mi
bibendum
neque
egestas
congue
quisque
euismod
in
pellentesque
massa
placerat
dolor
sit
amet
consectetur
adipiscing
elit
pellentesque
habitant
morbi
at
tempor
commodo
ullamcorper
a
lacus
sed
viverra
ipsum
nunc
aliquet
bibendum
volutpat
commodo
sed
egestas
egestas
fringilla
phasellus
faucibus
scelerisque
amet
consectetur
adipiscing
elit
duis
tristique
sollicitudin
nibh
sit
amet
aliquam
vestibulum
morbi
blandit
cursus
risus
sit
amet
cursus
sit
amet
dictum
sit
amet
justo
pellentesque
elit
eget
gravida
cum
sociis
natoque
penatibus
et
magnis
ultrices
eros
in
cursus
turpis
massa
tincidunt
dui
ut
ornare
ut
pharetra
sit
amet
aliquam
id
diam
maecenas
ultricies
mi
facilisi
cras
fermentum
odio
eu