#!/usr/bin/python #################################################################################################### from __future__ import print_function import urllib, urllib2, httplib, json, time, subprocess, math, sys, os, random, getopt, re from Adafruit_Thermal import * from bottle import get, post, request, run, static_file, template from xml.dom.minidom import parseString from xml.etree import ElementTree as etree #################################################################################################### #################################################################################################### @get('/') def index(): return ''' Notes & Lists

The Dagedi Personal Digital Assistant & Networked Thermal Printer

''' #################################################################################################### @post('/printstring') def printstring(): printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout = 5) mytext = request.forms.get('mytext') printer.boldOn() printer.print(mytext) printer.boldOff() printer.feed(2) printer.sleep() printer.wake() return template('''

printing {{ message }}!

go back.

''', message = mytext) #################################################################################################### @post('/fortune') def fortune(): printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout = 5) text = urllib.urlopen('http://fortunecookieapi.com/v1/cookie?lottoId=0&lessonId=0') obj = json.load(text)[0]; printer.boldOn() printer.print(obj['fortune']['message']) printer.boldOff() printer.feed(2) printer.sleep() printer.wake() return template('''

printing {{ message }}!

go back.

''', message = obj) #################################################################################################### @post('/forecast') def forecast(): printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout = 5) dom = parseString(urllib.urlopen('http://weather.yahooapis.com/forecastrss?w=2400539').read()) deg = chr(0xf8) # print heading printer.inverseOn() printer.print('{:^32}'.format(dom.getElementsByTagName('description')[0].firstChild.data)) printer.inverseOff() # print current conditions printer.boldOn() printer.print('{:^32}'.format('Current conditions:')) printer.boldOff() printer.print('{:^32}'.format(dom.getElementsByTagName('pubDate')[0].firstChild.data)) temp = dom.getElementsByTagName('yweather:condition')[0].getAttribute('temp') cond = dom.getElementsByTagName('yweather:condition')[0].getAttribute('text') printer.print(temp) printer.print(deg) printer.println(' ' + cond) # print forecast printer.boldOn() printer.print('{:^32}'.format('Forecast:')) printer.boldOff() forecast_idx(printer, dom, 0) forecast_idx(printer, dom, 1) printer.feed(2) printer.sleep() printer.wake() return template('''

printing {{ message }}!

go back.

''', message = format) #################################################################################################### def forecast_idx(printer, dom, idx): tag = 'yweather:forecast' deg = chr(0xf8) day = dom.getElementsByTagName(tag)[idx].getAttribute('day') lo = dom.getElementsByTagName(tag)[idx].getAttribute('low') hi = dom.getElementsByTagName(tag)[idx].getAttribute('high') cond = dom.getElementsByTagName(tag)[idx].getAttribute('text') printer.print(day + ': low ' + lo) printer.print(deg) printer.print(' high ' + hi) printer.print(deg) printer.println(' ' + cond) #################################################################################################### @post('/calculator') def calculator(): printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout = 5) mymath = request.forms.get('mymath') math = subprocess.Popen(['bc', '-i', '-q'], stdin = subprocess.PIPE, stdout = subprocess.PIPE) result = math.communicate(mymath + "\nquit")[0].rstrip() printer.boldOn() printer.print(result) printer.boldOff() printer.feed(2) printer.sleep() printer.wake() return template('''

printing {{ message }}!

go back.

''', message = mymath) #################################################################################################### @post('/sodoku') def sodoku(): printer = Adafruit_Thermal("/dev/ttyAMA0", 19200, timeout = 5) printer.setLineHeight(24) # So graphical chars fit together args = sys.argv[1:] if len(args) > 0: puzzles = [loadboard(filename) for filename in args] else: puzzles = [makepuzzle(solution([None] * 81))] for puzzle in puzzles: printer.println("PUZZLE:") printer.feed(1) printer.print(printboard(puzzle)) printer.feed(1) printer.println("RATING:", ratepuzzle(puzzle, 4)) if len(args) > 0: printer.println() printer.println("SOLUTION:") answer = solution(puzzle) if answer is None: printer.println("NO SOLUTION") else: printer.print(printboard(answer)) printer.feed(3) def makepuzzle(board): puzzle = []; deduced = [None] * 81 order = random.sample(xrange(81), 81) for pos in order: if deduced[pos] is None: puzzle.append((pos, board[pos])) deduced[pos] = board[pos] deduce(deduced) random.shuffle(puzzle) for i in xrange(len(puzzle) - 1, -1, -1): e = puzzle[i]; del puzzle[i] rating = checkpuzzle(boardforentries(puzzle), board) if rating == -1: puzzle.append(e) return boardforentries(puzzle) def ratepuzzle(puzzle, samples): total = 0 for i in xrange(samples): state, answer = solveboard(puzzle) if answer is None: return -1 total += len(state) return float(total) / samples def checkpuzzle(puzzle, board = None): state, answer = solveboard(puzzle) if answer is None: return -1 if board is not None and not boardmatches(board, answer): return -1 difficulty = len(state) state, second = solvenext(state) if second is not None: return -1 return difficulty def solution(board): return solveboard(board)[1] def solveboard(original): board = list(original) guesses = deduce(board) if guesses is None: return ([], board) track = [(guesses, 0, board)] return solvenext(track) def solvenext(remembered): while len(remembered) > 0: guesses, c, board = remembered.pop() if c >= len(guesses): continue remembered.append((guesses, c + 1, board)) workspace = list(board) pos, n = guesses[c] workspace[pos] = n guesses = deduce(workspace) if guesses is None: return (remembered, workspace) remembered.append((guesses, 0, workspace)) return ([], None) def deduce(board): while True: stuck, guess, count = True, None, 0 # fill in any spots determined by direct conflicts allowed, needed = figurebits(board) for pos in xrange(81): if None == board[pos]: numbers = listbits(allowed[pos]) if len(numbers) == 0: return [] elif len(numbers) == 1: board[pos] = numbers[0]; stuck = False elif stuck: guess, count = pickbetter(guess, count, [(pos, n) for n in numbers]) if not stuck: allowed, needed = figurebits(board) # fill in any spots determined by elimination of other locations for axis in xrange(3): for x in xrange(9): numbers = listbits(needed[axis * 9 + x]) for n in numbers: bit = 1 << n spots = [] for y in xrange(9): pos = posfor(x, y, axis) if allowed[pos] & bit: spots.append(pos) if len(spots) == 0: return [] elif len(spots) == 1: board[spots[0]] = n; stuck = False elif stuck: guess, count = pickbetter(guess, count, [(pos, n) for pos in spots]) if stuck: if guess is not None: random.shuffle(guess) return guess def figurebits(board): allowed, needed = [e is None and 511 or 0 for e in board], [] for axis in xrange(3): for x in xrange(9): bits = axismissing(board, x, axis) needed.append(bits) for y in xrange(9): allowed[posfor(x, y, axis)] &= bits return allowed, needed def posfor(x, y, axis = 0): if axis == 0: return x * 9 + y elif axis == 1: return y * 9 + x else: return ((0,3,6,27,30,33,54,57,60)[x] + (0,1,2,9,10,11,18,19,20)[y]) def axisfor(pos, axis): if axis == 0: return pos / 9 elif axis == 1: return pos % 9 else: return (pos / 27) * 3 + (pos / 3) % 3 def axismissing(board, x, axis): bits = 0 for y in xrange(9): e = board[posfor(x, y, axis)] if e is not None: bits |= 1 << e return 511 ^ bits def listbits(bits): return [y for y in xrange(9) if 0 != bits & 1 << y] def allowed(board, pos): bits = 511 for axis in xrange(3): x = axisfor(pos, axis) bits &= axismissing(board, x, axis) return bits def pickbetter(b, c, t): if b is None or len(t) < len(b): return (t, 1) if len(t) > len(b): return (b, c) if random.randint(0, c) == 0: return (t, c + 1) else: return (b, c + 1) def entriesforboard(board): return [(pos, board[pos]) for pos in xrange(81) if board[pos] is not None] def boardforentries(entries): board = [None] * 81 for pos, n in entries: board[pos] = n return board def boardmatches(b1, b2): for i in xrange(81): if b1[i] != b2[i]: return False return True def printboard(board): # Top edge of board: out = (' ' + chr(0xC9) # Top left corner + chr(0xCD) # Top edge + chr(0xD1) # Top 'T' + chr(0xCD) # Top edge + chr(0xD1) # Top 'T' + chr(0xCD) # Top edge + chr(0xCB) # Top 'T' (double) + chr(0xCD) # Top edge + chr(0xD1) # Top 'T' + chr(0xCD) # Top edge + chr(0xD1) # Top 'T' + chr(0xCD) # Top edge + chr(0xCB) # Top 'T' (double) + chr(0xCD) # Top edge + chr(0xD1) # Top 'T' + chr(0xCD) # Top edge + chr(0xD1) # Top 'T' + chr(0xCD) # Top edge + chr(0xBB) # Top right corner + '\n') for row in xrange(9): out += (' ' + chr(0xBA)) # Double Bar for col in xrange(9): n = board[posfor(row, col)] if n is None: out += ' ' else: out += str(n+1) if (col == 2) or (col == 5) or (col == 8): out += chr(0xBA) # Double bar else: out += chr(0xB3) # Single bar out += '\n' if(row < 8): if(row == 2) or (row == 5): out += (' ' + chr(0xCC) # Left 'T' (double) + chr(0xCD) # Horizontal bar + chr(0xD8) # + + chr(0xCD) # Horizontal bar + chr(0xD8) # + + chr(0xCD) # Horizontal bar + chr(0xCE) # Double + + chr(0xCD) # Horizontal bar + chr(0xD8) # + + chr(0xCD) # Horizontal bar + chr(0xD8) # + + chr(0xCD) # Horizontal bar + chr(0xCE) # Double + + chr(0xCD) # Horizontal bar + chr(0xD8) # + + chr(0xCD) # Horizontal bar + chr(0xD8) # + + chr(0xCD) # Horizontal bar + chr(0xB9) # Right 'T' (double) + '\n') else: out += (' ' + chr(0xC7) # Left 'T' + chr(0xC4) # Horizontal bar + chr(0xC5) # + + chr(0xC4) # Horizontal bar + chr(0xC5) # + + chr(0xC4) # Horizontal bar + chr(0xD7) # Double + + chr(0xC4) # Horizontal bar + chr(0xC5) # + + chr(0xC4) # Horizontal bar + chr(0xC5) # + + chr(0xC4) # Horizontal bar + chr(0xD7) # Double + + chr(0xC4) # Horizontal bar + chr(0xC5) # + + chr(0xC4) # Horizontal bar + chr(0xC5) # + + chr(0xC4) # Horizontal bar + chr(0xB6) # Right 'T' + '\n') out += (' ' + chr(0xC8) # Bottom left corner + chr(0xCD) # Bottom edge + chr(0xCF) # Bottom 'T' + chr(0xCD) # Bottom edge + chr(0xCF) # Bottom 'T' + chr(0xCD) # Bottom edge + chr(0xCA) # Bottom 'T' (double) + chr(0xCD) # Bottom edge + chr(0xCF) # Bottom 'T' + chr(0xCD) # Bottom edge + chr(0xCF) # Bottom 'T' + chr(0xCD) # Bottom edge + chr(0xCA) # Bottom 'T' (double) + chr(0xCD) # Bottom edge + chr(0xCF) # Bottom 'T' + chr(0xCD) # Bottom edge + chr(0xCF) # Bottom 'T' + chr(0xCD) # Bottom edge + chr(0xBC) # Bottom-right corner + '\n') # Original output code: # out = "" # for row in xrange(9): # for col in xrange(9): # out += (""," "," "," "," "," "," "," "," ")[col] # out += printcode(board[posfor(row, col)]) # out += ('\n','\n','\n\n','\n','\n','\n\n','\n','\n','\n')[row] return out def parseboard(str): result = [] for w in str.split(): for x in w: if x in '|-=+': continue if x in '123456789': result.append(int(x) - 1) else: result.append(None) if len(result) == 81: return result def loadboard(filename): f = file(filename, 'r') result = parseboard(f.read()) f.close() return result def basedir(): if hasattr(sys.modules[__name__], '__file__'): return os.path.split(__file__)[0] elif __name__ == '__main__': if len(sys.argv) > 0 and sys.argv[0] != '': return os.path.split(sys.argv[0])[0] else: return os.curdir def loadsudokutemplate(ext): f = open(os.path.join(basedir(), 'sudoku-template.%s' % ext), 'r') result = f.read() f.close() return result return template('''

printing {{ message }}!

go back.

''', message = 'Random Sodoku') #################################################################################################### @post('/kndyquit') def kndyquit(): tunes = subprocess.Popen(['killall', 'mplayer']) return template('''

Killing K N D Y!

go back.

''') #################################################################################################### @post('/kndy') def kndy(): tunes = subprocess.Popen(['mplayer', 'http://ushroo.com:1776/listen.ogg']) return template(''' Playing K N D Y!

Playing K N D Y!

go back.

''') #################################################################################################### @post('/pandora') def pandora(): tunes = subprocess.Popen(['pianobar', '>', '~/root/.config/pianobar/stationcreate']) return template(''' Playing Pandora!

thumbs up= +

thumbs donwn= -

next song= n

pause = S

resume = P

volume down = (

volume up = )

go back.

''') #################################################################################################### @post('/pandoracommand') def pandoracommand(): command = request.forms.get('command') tunes = subprocess.Popen([''], stdin = subprocess.PIPE, stdout = subprocess.PIPE) result = tunes.communicate(command)[0].rstrip() #################################################################################################### @post('/pandoraquit') def pandoraquit(): tunes = subprocess.Popen(['killall', 'pianobar']) return template('''

Killing Pandora!

go back.

''') #################################################################################################### @get('/') def server_static(filename): return static_file(filename, root = '.') #################################################################################################### run(host = '0.0.0.0', port = 80, debug = True) ####################################################################################################