From 814aa8c1824c87807cd4479416450d2fa16cd12f Mon Sep 17 00:00:00 2001 From: jaseg Date: Wed, 10 Feb 2016 00:20:46 +0100 Subject: Telnet, terminal and display interfaces working fine --- clippy.py | 71 +++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/clippy.py b/clippy.py index 7f93a47..4e67f60 100755 --- a/clippy.py +++ b/clippy.py @@ -9,6 +9,8 @@ import numpy import bz2 import os import functools +import contextlib +import math from PIL import Image @@ -34,9 +36,11 @@ class Display: self.size = 56*8, 8*20 def sendframe(self, frame): - self.sock.sendto(struct.pack('!HHHHH', CMD_LED_DRAW, 0, - (56*8*(12*20-8))%65536, 0x627a, 0) + # do. not. fucking. ask. - bz2.compress(frame), (HOST, PORT)) + pl = struct.pack('!HHHHH', CMD_LED_DRAW, 0, 0, 0x627a, 0) + bz2.compress(frame) + self.sock.sendto(pl, (HOST, PORT)) +# for i in range(100): +# time.sleep(0.0001) + self.sock.sendto(pl, (HOST, PORT)) @staticmethod def do_gamma(im, gamma): @@ -66,35 +70,41 @@ class Agent: for ani in self.config['animations'].values(): for f in ani['frames']: branching, exitBranch = f.get('branching'), f.get('exitBranch') - if 'branching' in f: + if 'exitBranch' in f: + f['next'] = lambda f, idx: f['exitBranch'] + elif 'branching' in f: f['next'] = lambda f, idx: weightedChoice( [ (b['weight']/100, b['frameIndex']) for b in f['branching']['branches'] ] , default=idx+1) - elif 'exitBranch' in f: - f['next'] = lambda f, idx: f['exitBranch'] else: f['next'] = lambda f, idx: idx+1 self.picmap = Image.open(path / 'map.png') self.path = path def __call__(self, action): - print('Playing:', action) for frame in self._animate(action): - print('frame:', frame) +# print('frame:', frame) if 'images_encoded' in frame: # some frames contain branch info and sound, but no images yield frame['images_encoded'] time.sleep(frame['duration']/1000) def precalculate_images(self, dsp, termsize): + print('\033[93mPrecalculating images\033[0m') + total = sum(1 for ani in self.config['animations'].values() for f in ani['frames'] if 'images' in f) + i = 0 for ani in self.config['animations'].values(): for f in ani['frames']: if 'images' in f: + print(('(\033[38;5;245m{: '+str(1+int(math.log10(total)))+'}/{}\033[0m) ').format(i, total), end='') + i += 1 f['images_encoded'] = self._precalculate_one_image(tuple(f['images'][0]), dsp, termsize) + print() + print('\033[93mdone.\033[0m') self._precalculate_one_image.cache_clear() @functools.lru_cache(maxsize=None) def _precalculate_one_image(self, coords, dsp, termsize): - img = self.get_image(*coords) + img = self._get_image(*coords) return ( dsp.encode_image(img, dsp.size) if dsp else None, pixelterm.termify_pixels(resize_image(img, termsize)) if termsize else None ) @@ -104,8 +114,9 @@ class Agent: yield anim[idx] idx = anim[idx]['next'](anim[idx], idx) - def get_image(self, x, y): - print('cropbox:', x, y, *self.config['framesize'], 'map:', self.picmap.size) + def _get_image(self, x, y): + print('\033[38;5;96mcropbox:\033[0m {:04} {:04} {:04} {:04} \033[38;5;96mmap:\033[0m {:04} {:04}'.format( + x, y, *self.config['framesize'], *self.picmap.size), end='') tw, th = self.config['framesize'] return self.picmap.crop((x, y, x+tw, y+th)) @@ -122,6 +133,9 @@ if __name__ == '__main__': parser.add_argument('-e', '--endless', action='store_true') parser.add_argument('-d', '--display', action='store_true') parser.add_argument('-t', '--terminal', action='store_true') + parser.add_argument('-x', '--termsize', type=str) + parser.add_argument('-s', '--socket', action='store_true') + parser.add_argument('-b', '--bind', type=str, default='0.0.0.0:2342') parser.add_argument('action', default='Greeting', nargs='?') args = parser.parse_args() @@ -136,18 +150,39 @@ if __name__ == '__main__': dsp = Display() if args.display else None agent = Agent(agent_path) - tx, ty = os.get_terminal_size() - termsize = (tx, ty*2) if args.terminal else None + if args.socket: + tx, ty = (args.termsize or '60x30').split('x') + tx, ty = int(tx), int(ty) + elif args.terminal: + tx, ty = args.termsize.split('x') or os.get_terminal_size() + tx, ty = int(tx), int(ty) + termsize = (tx, ty*2) if args.terminal or args.socket else None agent.precalculate_images(dsp, termsize) - if args.endless: + if args.socket: + import socketserver + class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): + pass + class ClippyRequestHandler(socketserver.BaseRequestHandler): + def handle(self): + with contextlib.suppress(BrokenPipeError): + while True: + action = random.choice(agent.animations) + print('[\033[38;5;245m{}\033[0m] Playing: {}'.format(self.client_address[0], action)) + for _img_dsp, img_term in agent(action): + self.request.sendall(b'\033[H'+img_term.encode()) + host, port = args.bind.split(':') + port = int(port) + server = ThreadedTCPServer((host, port), ClippyRequestHandler) + server.serve_forever() + elif args.endless: while True: if random.random() > 0.2: - for img_dsp, img_term in agent(random.choice(agent.animations)): + action = random.choice(agent.animations) + print('Playing:', action) + for img_dsp, img_term in agent(action): if args.terminal: - print('\033[H', end='') - print(pixelterm.termify_pixels( - resize_image(img, termsize))) + print('\033[H'+img_term) if args.display: dsp.sendframe(img_dsp) time.sleep(1) -- cgit