91 lines
2.1 KiB
Python
91 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import datetime
|
|
import random
|
|
|
|
_roman_numerals = (
|
|
(1000, 'M'),
|
|
( 900, 'CM'),
|
|
( 500, 'D'),
|
|
( 400, 'CD'),
|
|
( 100, 'C'),
|
|
( 90, 'XC'),
|
|
( 50, 'L'),
|
|
( 40, 'XL'),
|
|
( 10, 'X'),
|
|
( 9, 'IX'),
|
|
( 5, 'V'),
|
|
( 4, 'IV'),
|
|
( 1, 'I'),
|
|
)
|
|
|
|
def _int_to_roman(n):
|
|
for value, numeral in _roman_numerals:
|
|
for _ in range(n // value):
|
|
yield numeral
|
|
n -= value
|
|
assert n >= 0
|
|
if n == 0:
|
|
return
|
|
|
|
def int_to_roman(n):
|
|
return ''.join(_int_to_roman(n))
|
|
|
|
|
|
def _render(template):
|
|
if isinstance(template, str):
|
|
yield template
|
|
return
|
|
|
|
if callable(template):
|
|
yield from _render(template())
|
|
return
|
|
|
|
for t in template:
|
|
yield from _render(t)
|
|
|
|
def render(template):
|
|
return ''.join(_render(template))
|
|
|
|
def c(*args, min=1, max=1):
|
|
'''choose an amount of template from the args, (min, max) inclusive'''
|
|
return lambda: random.sample(args, random.randint(min, max))
|
|
|
|
def sh(*args):
|
|
'''shuffle args'''
|
|
def wrapped():
|
|
l = list(args)
|
|
random.shuffle(l)
|
|
return l
|
|
return wrapped()
|
|
|
|
def b(weight, first, second):
|
|
'''branch with probability (weight -> first, 1-weight -> second)'''
|
|
return lambda: first if random.random() <= weight else second
|
|
|
|
def f(freq, template):
|
|
'''b(freq, template, '')'''
|
|
return b(freq, template, '')
|
|
|
|
def w(*args):
|
|
'''weighted options'''
|
|
def wrapped():
|
|
q = random.random() * sum(weight for weight, template in args)
|
|
for weight, template in args:
|
|
q -= weight
|
|
if q <= 0:
|
|
return template
|
|
assert False
|
|
return wrapped
|
|
|
|
def d(fmt='%e.%m', date=None):
|
|
return lambda: (date or datetime.date.today)().strftime(fmt).strip()
|
|
|
|
def next_isoweekday(isoweekday, after=None):
|
|
def wrapped(after=after):
|
|
if after is None:
|
|
after = datetime.date.today()
|
|
offset = (isoweekday - after.isoweekday() - 1) % 7 + 1
|
|
return after + datetime.timedelta(days=offset)
|
|
return wrapped
|