woju
/
rcb
1
0
Fork 0
rcb/tlib.py

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