prototyped
parent
0b0d001a2f
commit
52e9df34d3
|
|
@ -0,0 +1,133 @@
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
import queue
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
def main():
|
||||||
|
def __input__():
|
||||||
|
return input()
|
||||||
|
if argv[1:]:
|
||||||
|
f = open(argv[1])
|
||||||
|
def __input__():
|
||||||
|
return f.readline()
|
||||||
|
input_buffer = InputBuffer()
|
||||||
|
input_buffer.start()
|
||||||
|
print("accepting input")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
got = __input__()
|
||||||
|
input_buffer.enqueue(got.strip())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("stopping")
|
||||||
|
input_buffer.stop()
|
||||||
|
break
|
||||||
|
input_buffer.join()
|
||||||
|
print("stopped")
|
||||||
|
|
||||||
|
class InputBuffer(threading.Thread):
|
||||||
|
def __init__(self):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.pages = {}
|
||||||
|
self.q = queue.Queue()
|
||||||
|
self.done = False
|
||||||
|
|
||||||
|
def now():
|
||||||
|
return time.time()
|
||||||
|
|
||||||
|
def interval():
|
||||||
|
return .1
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.done = True
|
||||||
|
self.q.put(None)
|
||||||
|
|
||||||
|
def bucket(self, t):
|
||||||
|
t *= 1000
|
||||||
|
i = InputBuffer.interval() * 1000
|
||||||
|
tp = int(t // i) * int(i)
|
||||||
|
return tp / 1000
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
state = InputBuffer.State(0, None)
|
||||||
|
previous = None
|
||||||
|
while not self.done:
|
||||||
|
try:
|
||||||
|
state = InputBuffer.State.choose(state, self._run())
|
||||||
|
latest = state.v
|
||||||
|
if latest != previous:
|
||||||
|
print(InputBuffer.now(), latest)
|
||||||
|
previous = latest
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
time.sleep(InputBuffer.interval())
|
||||||
|
|
||||||
|
def _run(self):
|
||||||
|
now = InputBuffer.now()
|
||||||
|
deadline = now + InputBuffer.interval()
|
||||||
|
while InputBuffer.now() < deadline:
|
||||||
|
if self.dequeue(deadline - InputBuffer.now()) == None:
|
||||||
|
self.done = True
|
||||||
|
return
|
||||||
|
return InputBuffer.State(now, self.pick(now))
|
||||||
|
|
||||||
|
def enqueue(self, k):
|
||||||
|
self.q.put([ InputBuffer.now(), k.lower() ])
|
||||||
|
|
||||||
|
def dequeue(self, timeout):
|
||||||
|
try:
|
||||||
|
if timeout <= 0:
|
||||||
|
return False
|
||||||
|
got = self.q.get(timeout=timeout)
|
||||||
|
except queue.Empty:
|
||||||
|
return False
|
||||||
|
if got:
|
||||||
|
t = self.bucket(got[0])
|
||||||
|
k = got[1]
|
||||||
|
if not t in self.pages:
|
||||||
|
self.pages[t] = InputBuffer.Page()
|
||||||
|
self.pages[t].push(k)
|
||||||
|
return got
|
||||||
|
|
||||||
|
def pick(self, t):
|
||||||
|
return self.pages.get(self.bucket(t), InputBuffer.Page()).pick()
|
||||||
|
|
||||||
|
class Page:
|
||||||
|
def __init__(self):
|
||||||
|
self.inputs = {}
|
||||||
|
|
||||||
|
def push(self, k):
|
||||||
|
self.inputs[k] = self.inputs.get(k, 0) + 1
|
||||||
|
|
||||||
|
def pick(self):
|
||||||
|
if not self.inputs:
|
||||||
|
return None
|
||||||
|
options = []
|
||||||
|
for k,v in self.inputs.items():
|
||||||
|
for i in range(0, v):
|
||||||
|
options.append(k)
|
||||||
|
return options[random.randint(0, len(options)-1)]
|
||||||
|
|
||||||
|
class State:
|
||||||
|
def __init__(self, t, v):
|
||||||
|
self.t = t
|
||||||
|
self.v = v
|
||||||
|
|
||||||
|
def choose(a, b):
|
||||||
|
if not a:
|
||||||
|
return b
|
||||||
|
if not b:
|
||||||
|
return a
|
||||||
|
latest = a
|
||||||
|
oldest = b
|
||||||
|
if b.t > a.t:
|
||||||
|
latest = b
|
||||||
|
oldest = a
|
||||||
|
if latest.v == None:
|
||||||
|
t_a_few_intervals_ago = InputBuffer.now() - InputBuffer.interval() * 10
|
||||||
|
if oldest.t > t_a_few_intervals_ago:
|
||||||
|
return oldest
|
||||||
|
return latest
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cleanup() {
|
||||||
|
jobs="$(jobs -p)"
|
||||||
|
test -n "$jobs" && kill -9 $jobs
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
local pipe=/tmp/breel.pipe
|
||||||
|
test -e "$pipe" || mkfifo $pipe
|
||||||
|
while true; do
|
||||||
|
read -s v
|
||||||
|
echo "$v"
|
||||||
|
done | python3 ./main.py
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$0" == "$BASH_SOURCE" ]; then
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
Loading…
Reference in New Issue