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()
|
@ -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…
Reference in new issue