112 lines
2.7 KiB
Python
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__
|