twitch-plays/src/reader.py

112 lines
2.7 KiB
Python

import threading
import math
import queue
import time
import sys
import select
import random
import log
__interval__ = .1
class Reader:
def __init__(self, reader):
self.reader = reader
def read(self):
q = queue.Queue(maxsize=1)
class async_reader(threading.Thread):
def __init__(self, q, foo):
threading.Thread.__init__(self)
self.q = q
self.foo = foo
self.stopping = False
def stop(self):
self.stopping = True
def run(self):
while not self.stopping:
try:
self.q.put_nowait(self.foo())
except queue.Full:
pass
except StopIteration:
self.stop()
reader = async_reader(q, self.reader.read)
reader.start()
try:
while not reader.stopping:
try:
s = q.get(timeout=__interval__)
if s:
s = s.lower().strip()
yield s
except queue.Empty:
yield None
pass
except KeyboardInterrupt as e:
reader.stop()
reader.join()
class StdinReader:
def __init__(self):
self.__closed__ = False
def read(self):
if self.__closed__:
raise StopIteration
try:
if select.select([sys.stdin,],[],[],__interval__/2.0)[0]:
line = sys.stdin.readline()
self.__closed__ = not line
return line
except Exception as e:
pass
return None
class RandomReader:
def __init__(self, keys={"a":{"weight":1}, "b":{"weight":1}}):
self.keys = keys
self.pool = RandomPool(keys)
def read(self):
return self.pool.pop()
class RandomPool:
def __init__(self, values):
self.values = {
k:int(1000*v["weight"]) for k,v in values.items()
}
self.total = sum(self.values.values())
self.consumed = set()
log.info("RandomPool with", {k:int(100.0*v/self.total) for k,v in self.values.items()})
def reset(self):
self.consumed = set()
def pop(self):
idx = random.randint(0, self.total-1)
idx_offset = 0
for k in sorted(self.values.keys()):
if self.values[k] > idx+idx_offset:
return k
idx_offset -= self.values[k]
raise Exception(":(")
def should_reset(self):
return len(self.consumed) >= len(self.values)/2
class FileReader:
def __init__(self, path):
self.f = open(path, "r")
self.__closed__ = False
def read(self):
if self.__closed__:
raise StopIteration
result = self.f.readline()
result = not self.__closed__