clock: initial commit.

master
Michael Hope 4 years ago
commit 20a077d5d0

@ -0,0 +1,225 @@
import time
RANGES = {
'w': 94,
'seven': 88,
'we': 94,
'cl': 102,
'le': 80,
't': 109,
'qua': 17,
'd': 12,
'ne': 63,
'q': 19,
'ex': 31,
'ar': 16,
'hal': 41,
'ac': 20,
'y': 27,
'k': 99,
'twelve': 93,
'ha': 42,
'es': 62,
'lock': 99,
'pa': 44,
'h': 84,
'quarter': 13,
'aster': 45,
'eleven': 77,
'ns': 106,
'se': 105,
'five': 70,
'pas': 44,
'clock': 99,
'p': 44,
'lo': 101,
'went': 23,
'nes': 62,
'paste': 44,
'ur': 68,
'rte': 14,
'e': 105,
'six': 60,
'st': 46,
'amp': 7,
'three': 55,
'tense': 105,
'our': 67,
'x': 60,
'ten': 107,
'sixth': 58,
'quart': 15,
'eight': 83,
'n': 107,
'v': 97,
'tens': 106,
'l': 102,
'to': 33,
's': 106,
'nine': 51,
'four': 66,
'rd': 12,
'twentyfive': 22,
'art': 15,
'wen': 23,
'vent': 90,
'as': 45,
'er': 48,
'am': 7,
'its': 0,
'halfs': 39,
'oclock': 99,
'vet': 72,
'two': 74,
'eve': 89,
'ty': 26,
're': 56,
'pm': 9,
'o': 101,
'si': 61,
'fs': 39,
'run': 49,
'it': 0,
'even': 89,
'past': 44,
'f': 70,
'm': 10,
'r': 69,
'event': 89,
'a': 45,
'g': 85,
'ru': 49,
'c': 100,
'twenty': 22,
'vex': 30,
'half': 40,
'sis': 2,
'th': 58,
'is': 3,
'al': 41,
'in': 52,
'one': 63,
'i': 86,
'on': 64,
'ni': 51,
'ive': 71,
'u': 68,
'ones': 62,
'sam': 6,
'ts': 1
}
MINUTES = ('oclock', 'five past', 'ten past', 'quarter past', 'twenty past',
'twentyfive past', 'half past', 'twentyfive to', 'twenty to',
'quarter to', 'ten to', 'five to')
HOURS = ('twelve', 'one', 'two', 'three', 'four', 'five', 'six', 'seven',
'eight', 'nine', 'ten', 'eleven')
AMPM = ('am', 'pm')
def split(now: tuple):
minute = now.tm_min // 5
hour = now.tm_hour
if now.tm_min >= 35:
hour += 1
hour %= len(HOURS)
ampm = (now.tm_hour // 12) % len(AMPM)
return MINUTES[minute], HOURS[hour], AMPM[ampm]
def fps(dt: float):
until = time.monotonic()
while True:
d = until - time.monotonic()
until += dt
if d > 0:
sleep(d)
yield None
class Frame:
Max = 255
def __init__(self, n: int=11 * 10, pixels: list=None):
if pixels is None:
pixels = [0] * n
self.pixels = pixels
def set(self, idx: int):
self.pixels[idx] = self.Max
def __add__(self, other):
return Frame(pixels=[
min(self.Max, x + y) for x, y in zip(self.pixels, other.pixels)
])
def muldiv(self, num: int, den: int):
return Frame(pixels=[x * num // den for x in self.pixels])
def render(words: list) -> Frame:
f = Frame()
for word in words:
idx = RANGES[word]
for i in range(len(word)):
f.set(idx + i)
return f
EPOCH = time.time()
def now():
secs = EPOCH + (time.time() - EPOCH) * 11
return time.gmtime(secs)
def sleep(dt: float):
time.sleep(dt)
def show(f: Frame):
print('\033\143')
stride = 11
dots = ' .:~*#@'
for y in range(len(f.pixels) // stride):
s = f.pixels[y * stride:(y + 1) * stride]
if y & 1 != 0:
s.reverse()
d = [dots[x * len(dots) // (Frame.Max + 1)] for x in s]
print(''.join(d))
print()
DT = 0.1
def run():
src = Frame()
words = None
steps = int(2.0 / DT)
while True:
yield src
nxt = split(now())
print(nxt)
if nxt == words:
sleep(1)
continue
dest = render(nxt)
f = fps(DT)
for i in range(steps):
yield src.muldiv(steps - i, steps) + dest.muldiv(i, steps)
next(f)
words = nxt
src = dest
def main():
for f in run():
show(f)
main()

121
gen.py

@ -0,0 +1,121 @@
import pprint
import itertools
def parse_board(board: str) -> list:
return board.strip().split('\n')
def gen_order(w, h):
i = 0
lr = True
for y in range(h):
cells = [i + x for x in range(w)]
if not lr:
cells.reverse()
yield cells
i += len(cells)
lr = not lr
def gen_dict(fname: str):
with open(fname) as f:
for line in f:
for word in line.split():
yield word.lower().replace("'", "")
def gen_words(board, dictonary):
for y, row in enumerate(board):
for x in range(len(row)):
for j in range(x, len(row)):
word = row[x:j + 1]
if word in dictonary:
yield x, y, word
def gen_ranges(words, order):
for x, y, word in words:
row = order[y]
l, r = row[x], row[x + len(word) - 1]
yield word, min(l, r)
def gen_word_map(ranges):
return {x: y for x, y in ranges}
BOARD2 = """
ItsIs.AMPM
TwentyFIVE
QuarterTen
ToPast.One
TwoFourSix
Three.Five
SevenEight
NineEleven
TenTwelve.
"""
BOARD = """
ITSISASAMPM
ACQUARTERDC
TWENTYFIVEX
HALFSTENFTO
PASTERUNINE
ONESIXTHREE
FOURFIVETWO
EIGHTELEVEN
SEVENTWELVE
TENSEOCLOCK
"""
def pack(words, width=11):
best = None
for p in itertools.permutations(words):
rows = []
row = ''
for word in p:
if len(row) + len(word) <= width:
row += word
else:
rows.append(row)
row = word
rows.append(row)
if best is None:
best = [rows]
elif len(rows) <= len(best[0]):
best = [rows]
yield rows
def fill(words, width=11):
todo = words
rows = []
while todo:
row = ''
t = []
for word in todo:
if len(row) + len(word) <= width:
row += word
else:
t.append(word)
rows.append(row)
todo = t
return rows
def main():
board = parse_board(BOARD.lower())
order = list(gen_order(len(board[0]), len(board)))
d = set(gen_dict('/usr/share/dict/words'))
d.add('twentyfive')
words = list(gen_words(board, d))
ranges = gen_ranges(words, order)
word_map = {x: y for x, y in ranges}
print('RANGES = %s' % word_map)
main()

@ -0,0 +1,50 @@
import datetime
import sys
import time
from geoip import geolite2
import astral
import dateutil.tz
import flask
app = flask.Flask(__name__)
def to_sec(dt):
return dt.hour * 60 * 60 + dt.minute * 60 + dt.second
@app.route('/iptime')
def iptime():
ip = flask.request.args.get('ip')
if not ip:
ip = flask.request.remote_addr
loc = geolite2.lookup(ip)
if loc is None:
flask.abort(
400,
'LOOKUP_FAILURE: unable to resolve the location of IP address %r' %
ip)
tz = dateutil.tz.gettz(loc.timezone)
epoch = time.time()
now = datetime.datetime.now(tz)
l = astral.Location((loc.ip, loc.country, loc.location[0], loc.location[1],
loc.timezone, 0))
s = l.sun()
dawn = s['dawn']
dusk = s['dusk']
resp = dict(
ip=loc.ip,
country=loc.country,
latitude=loc.location[0],
longitude=loc.location[1],
timezone=loc.timezone,
dawn=dawn,
dawn_sec=to_sec(dawn),
dusk=dusk,
dusk_sec=to_sec(dusk),
local_time=now,
day_sec=to_sec(now),
posix_sec=int(epoch))
return flask.jsonify(resp)
Loading…
Cancel
Save