diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rwxr-xr-x | bridge.py | 11 | ||||
| -rwxr-xr-x | brige.py | 100 | ||||
| -rw-r--r-- | sunrise.py | 127 | ||||
| -rwxr-xr-x | twinkle.py | 112 | ||||
| -rw-r--r-- | webapp/app/__init__.py | 11 | ||||
| -rw-r--r-- | webapp/app/templates/index.html | 55 | ||||
| -rw-r--r-- | webapp/app/views.py | 37 | ||||
| -rwxr-xr-x | webapp/run.py | 7 |
9 files changed, 463 insertions, 0 deletions
@@ -1,2 +1,5 @@ __pycache__ *.pyc + +webapp/packages +webapp/tmp @@ -4,6 +4,7 @@ from __future__ import division, print_function import color import constants import fish_render +import sunrise import time import random try: @@ -14,6 +15,16 @@ except ImportError: else: have_lumiversepython = True + + + +#fish_render = sunrise + + + + + + def get_all_lights(rig): """Return a list of all panels.""" return [ diff --git a/brige.py b/brige.py new file mode 100755 index 0000000..314f9db --- /dev/null +++ b/brige.py @@ -0,0 +1,100 @@ +#!/usr/bin/python2 +from __future__ import division, print_function +import color +import constants +import curses +import fish_render +import time +import random +try: + import lumiversepython +except ImportError: + have_lumiversepython = False + from DummyRig import DummyRig +else: + have_lumiversepython = True + +def get_all_lights(rig): + """Return a list of all panels.""" + return [ + [ + fish_render.Light( + x, int(y == 'top'), + rig.select('$side={y}[$sequence={x}]'.format(y=y, x=x)) + ) for y in ('top', 'bot') + ] for x in xrange(1, 200) + ] + + +def colorSection(lights, color, *ranges): + for start, end in ranges: + map(lambda l: map(lambda x: x.light.setRGBRaw(*color), l), lights[start:end]) + +def onSection(lights, *ranges): + colorSection(lights, (1, 1, 1), *ranges) + +def offSection(lights, *ranges): + colorSection(lights, (0, 0, 0), *ranges) + +def mapKey(key): + if key == ord('a'): + return (0, 20) + if key == ord('o'): + return (20, 40) + if key == ord('e'): + return (40, 60) + if key == ord('u'): + return (60, 80) + if key == ord('i'): + return (80, 100) + if key == ord('d'): + return (100, 120) + if key == ord('h'): + return (120, 140) + if key == ord('t'): + return (140, 160) + if key == ord('n'): + return (160, 180) + if key == ord('s'): + return (180, 200) + return (0, 0) + +def demo(lights, rig, screen): + """Do some light things.""" + sections = [] + while True: + k = screen.getch() + offSection(lights, *sections) + r = mapKey(k) + try: + i = sections.index(r) + except ValueError: + sections.append(r) + else: + del sections[i] + onSection(lights, *sections) + rig.updateOnce() + +def main(): + """Run show.""" + if have_lumiversepython: + rig = lumiversepython.Rig('/home/teacher/Lumiverse/PBridge.rig.json') + else: + rig = DummyRig(200, 2) + rig.init() + stdscr = curses.initscr() + stdscr.keypad(1) + curses.noecho() + + lights = get_all_lights(rig) + try: + demo(lights, rig, stdscr) + except BaseException: + curses.nocbreak() + stdscr.keypad(0) + curses.echo() + curses.endwin() + raise + +if __name__ == '__main__': + main() diff --git a/sunrise.py b/sunrise.py new file mode 100644 index 0000000..68a423c --- /dev/null +++ b/sunrise.py @@ -0,0 +1,127 @@ +"""Rendering classes and helper functions.""" +from __future__ import division +import color +import random +import constants +from constants import * +import math + +class Fish(object): + """Object displayed on the bridge, probably a fish.""" + def __init__(self, x, y, width, height, c, step): + """Create fish with default parameters.""" + self.x = x + self.y = y + self.x = 75 + self.y = -2 + self.width = width + self.width = 75 + self.height = height + self.height = 2 + self.color = c + self.color = color.RGB(1, 0.5, 0) + self.speed = step + self.step = step + self.wait = 0 + + def update(self): + """Swim gently to the other side of the bridge.""" + #self.x += self.step + #if self.x > 200: + # self.x = 0 + #self.y = 0.25 + 0.25 * math.sin(math.pi * self.x / 10) + #theta = random.random() * math.pi / 2 - math.pi / 4 + #self.y += 0.01 * math.sin(theta) + #print(self.y) + self.y += 0.000005 + if self.y >= 1: + self.y = 1 + self.wait += 1 + if self.wait >= 200: + self.wait = 0 + self.y = -2 + + +class Light(object): + """Represent a bridge light and its state.""" + def __init__(self, x, y, light): + """Store all facts about a light.""" + self.light = light + self.color = color.black + self.transitioning_to = self.color + self.step = 0 + self.x = x + self.y = y + + def update(self, fish): + """Change color depending on where the fish is.""" + if self.y == 1: + new_color = color.RGB(0.5, 0.5, 0.5) + else: + new_color = color.RGB(0.5, 0.5, 0) + coverage = compute_coverage(fish, self.x, self.y) + ccolor = new_color * (1 - coverage) + fish.color * coverage + self.light.setRGBRaw( + *map(lambda x: clamp(0, x, 1), ccolor.components) + ) + + +class Bridge(object): + """Store objects on the bridge.""" + def __init__(self, lights, fish, rig): + """Initialize with lights and fish.""" + self.lights = lights + self.fish = fish + self.rig = rig + + def update(self): + """Compute fish coverages and push lights to bridge.""" + for x, light_col in enumerate(self.lights): + for y, light in enumerate(light_col): + self.fish.update() + light.update(self.fish) + self.rig.updateOnce() + + +def compute_coverage(fish, x, y): + """Calculate the coverage of a fish over a box.""" + middle_of_fish = fish.x + fish.width / 2 + middle_of_panel = x + 0.5 + diff = abs(middle_of_fish - middle_of_panel) / (fish.width / 2) + scale = 1 - diff + min_x = min(max(x, fish.x), x + 1) + max_x = max(min(x+1, fish.x + fish.width), x) + min_y = min(max(y, fish.y), y + 1) + max_y = max(min(y+1, fish.y + fish.height), y) + coverage = (max_x - min_x) * (max_y - min_y) + return coverage * scale + + +def pick_HSV(): + """Return a random color in an appropriate interval.""" + hue = random.random() * (constants.MAX_HUE - constants.MIN_HUE) + constants.MIN_HUE + saturation = random.random() * (MAX_SATURATION - MIN_SATURATION) + MIN_SATURATION + value = random.random() * (MAX_VALUE - MIN_VALUE) + MIN_VALUE + return color.HSV(hue, saturation, value) + + +def transition(start, end, step): + """Return a vector equal to (end - start) * step + start.""" + if start == end: + return start + diff_vector = end - start + step_vector = diff_vector / abs(diff_vector) * step + result = step_vector + start + return result + + +def random_change(): + """Return a random amount that a light should change each frame.""" + min_time = int(constants.MIN_TIME * FRAME_RATE) + max_time = int(MAX_TIME * FRAME_RATE) + return 1 / random.randint(min_time, max_time) + + +def clamp(low, x, high): + """Return v such that low <= v <= high and |x - v| is minimal.""" + return max(low, min(x, high)) diff --git a/twinkle.py b/twinkle.py new file mode 100755 index 0000000..a2cb3d2 --- /dev/null +++ b/twinkle.py @@ -0,0 +1,112 @@ +#!/usr/bin/python2 +"""Simple demo of twinkle lights.""" +from __future__ import division +import color +import constants +#from DummyRig import DummyRig +from fish_render import * +import fish_render +from constants import * +import time +import random +try: + import lumiversepython +except ImportError: + have_lumiversepython = False +else: + have_lumiversepython = True + +def get_all_lights(rig): + """Return a list of all panels.""" + return [ + [ + fish_render.Light( + x, int(y == 'top'), + rig.select('$side={y}[$sequence={x}]'.format(y=y, x=x)) + ) for y in ('top', 'bot') + ] for x in xrange(1, 200) + ] + +def flip(): + """Return 0 with 99.9% prob. & 1 with .1% prob.""" + # should be black most of the time + return random.random() < 0.0005 + + +def twinkle(lights, rig): + """Try to do some light things.""" + light_status = [ + { + 'is_increasing': True, + 'is_on': False, + 'change': random_change(), + 'light': light, + 'intensity': 0, + } + for light_col in lights for light in light_col + ] + shooting_stars = list() + while True: + if random.random() < 1: + shooting_stars.append([random.randint(1, 180), random.random() < 0.5, 0]) + for light_s in light_status: + is_increasing = light_s['is_increasing'] + is_on = light_s['is_on'] + change = light_s['change'] + light = light_s['light'] + intensity = light_s['intensity'] + # R and G are either 0 or 1 + if not is_on: + if flip(): + is_on = True + is_increasing = True + change = 1.5 / FRAME_RATE + light_s['is_on'] = is_on + light_s['is_increasing'] = is_increasing + light_s['change'] = change + else: + continue + intensity = clamp(0, intensity + change * (int(is_increasing) * 2 - 1), 1) + light.light.setRGBRaw(intensity, intensity, intensity) + light_s['intensity'] = intensity + if intensity == 0: + light_s['is_on'] = False + if intensity == 1: + light_s['is_increasing'] = False + for i, star in enumerate(shooting_stars): + star[2] += 1 + if star[2] > 10: + for dx in range(-6, 7): + light_status[star[0] + dx]['light'].light.setRGBRaw(0, 0, 0) + del shooting_stars[i] + continue + star[0] += int(star[1]) * 2 - 1 + for dx in range(-6, 7): + intensity = 1 - 1 / 6 * abs(dx) + light_status[star[0] + dx]['light'].light.setRGBRaw(intensity, intensity, intensity) + rig.updateOnce() + time.sleep(1 / FRAME_RATE) + +def sunrise(lights, rig): + #rig.select('$side={y}[$sequence={x}]'.format(y=y, x=x)) + rig.select("$side=top[$panel=27|$panel=28]") + rig.updateOnce() + time.sleep(1) + + +def main(): + """Run show.""" + if have_lumiversepython: + rig = lumiversepython.Rig('/home/teacher/Lumiverse/PBridge.rig.json') + else: + rig = DummyRig(200, 2) + rig.init() + lights = get_all_lights(rig) + #for light in lights: + # light.setRGBRaw(0, 0, 0) + rig.updateOnce() + time.sleep(3) + twinkle(lights, rig) + +if __name__ == '__main__': + main() diff --git a/webapp/app/__init__.py b/webapp/app/__init__.py new file mode 100644 index 0000000..aa2e264 --- /dev/null +++ b/webapp/app/__init__.py @@ -0,0 +1,11 @@ +from flask import Flask +import socketio +import eventlet +import eventlet.wsgi + +sio = socketio.Server(async_mode='threading') +app = Flask(__name__) +app.wsgi_app = socketio.Middleware(sio, app.wsgi_app) +from app import views + + diff --git a/webapp/app/templates/index.html b/webapp/app/templates/index.html new file mode 100644 index 0000000..b0d9bb3 --- /dev/null +++ b/webapp/app/templates/index.html @@ -0,0 +1,55 @@ +<html> + <head> + <script type="text/javascript" src="//code.jquery.com/jquery-2.1.4.min.js"></script> + <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script> + + <script> + var SPAWN_URL = "/spawn"; + + function creature(name, socket) { + var self = this; + self.name = name; + self.socket = socket; + + self.render = function($parent) { + var $a = $('<a>'); + $a.text(self.name); + $a.click(self.click.bind(self)); + + var $li = $('<li>'); + $li.append($a); + $parent.append($li); + }; + + self.click = function() { + self.socket.emit('spawn', {name:self.name}); + } + } + + $(document).ready(function() { + var namespace = '/spawn'; + var socket = io.connect('http://' + document.domain + ':' + location.port + namespace); + + socket.on('connect', function() { + console.log('connected!'); + }); + + socket.on('new creature', function(msg) { + console.log('new!'); + var c = new creature(msg.name, socket); + c.render($('#creatures')); + }); + + socket.on('disconnect', function() { + console.log('disconnected'); + }); + }); + + </script> + <title>{{ title }}</title> + </head> + <body> + <h1>Ocean Fun Times</h1> + <ul id="creatures"></ul> + </body> +</html> diff --git a/webapp/app/views.py b/webapp/app/views.py new file mode 100644 index 0000000..4aa2c05 --- /dev/null +++ b/webapp/app/views.py @@ -0,0 +1,37 @@ +from flask import render_template, request +from app import app, sio +import time + +import threading + +thread = None + +@app.route('/') +@app.route('/index') +def index(): + return render_template('index.html', + title='F16 Group1') + +connections = set() + +@sio.on('connect', namespace='/spawn') +def connect(sid, environ): + print("connect ", sid) + connections.add(sid) + +@sio.on('spawn', namespace='/spawn') +def message(sid, data): + print("message ", data) + +@sio.on('disconnect', namespace='/spawn') +def disconnect(sid): + print('disconnect', sid) + connections.remove(sid) + + + +def add_creature(): + time.sleep(5) + sio.emit('new creature', {'name': 'fish1'}, namespace='/spawn') + +thread = sio.start_background_task(add_creature) diff --git a/webapp/run.py b/webapp/run.py new file mode 100755 index 0000000..b5c8c6f --- /dev/null +++ b/webapp/run.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +import sys +sys.path.append('packages') + +from app import app +app.run(threaded=True, host='', port=8000) |
