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__