| 1 |
#!/usr/bin/env python3
|
| 2 |
|
| 3 |
import base64
|
| 4 |
import flask
|
| 5 |
import random
|
| 6 |
import openpyxl
|
| 7 |
import svgwrite
|
| 8 |
|
| 9 |
app = flask.Flask(__name__)
|
| 10 |
|
| 11 |
TEXT_STYLE = 'font-family: "Arial", "Helvetica", sans-serif;'
|
| 12 |
|
| 13 |
@app.route('/')
|
| 14 |
def index():
|
| 15 |
return flask.send_from_directory('.', 'page.html')
|
| 16 |
|
| 17 |
|
| 18 |
@app.route('/process', methods=['POST'])
|
| 19 |
def process():
|
| 20 |
if 'file' not in flask.request.files:
|
| 21 |
raise Exception('No file uploaded!')
|
| 22 |
f = flask.request.files['file']
|
| 23 |
if f.filename == '':
|
| 24 |
raise Exception('No file uploaded!')
|
| 25 |
choices = choices_from_excel(openpyxl.load_workbook(f.stream))
|
| 26 |
choice_str = base64.urlsafe_b64encode('\x1c'.join(choices).encode('utf-8'))
|
| 27 |
return flask.redirect('/bingo.svg?choices={0}'.format(choice_str.decode('utf-8')))
|
| 28 |
|
| 29 |
|
| 30 |
@app.route('/bingo.svg')
|
| 31 |
def generate():
|
| 32 |
choice_str = base64.urlsafe_b64decode(flask.request.args.get('choices'))
|
| 33 |
choices = choice_str.decode('utf-8').split('\x1c')
|
| 34 |
print(choices)
|
| 35 |
return mk_svg(choices)
|
| 36 |
|
| 37 |
|
| 38 |
def choices_from_excel(wb):
|
| 39 |
sheet = wb.get_sheet_by_name(wb.get_sheet_names()[0])
|
| 40 |
choices = []
|
| 41 |
for row in range(1, sheet.max_row + 1):
|
| 42 |
choices.append(sheet.cell(row=row, column=1).value)
|
| 43 |
return choices
|
| 44 |
|
| 45 |
|
| 46 |
def mk_svg(choices):
|
| 47 |
choices = list(choices)
|
| 48 |
if len(choices) < 24:
|
| 49 |
raise Exception('Must have at least 24 possible choices!')
|
| 50 |
random.shuffle(choices)
|
| 51 |
d = svgwrite.Drawing(size=('8.5in', '11in'))
|
| 52 |
# t = svgwrite.mixins.Transform.translate('0.25in', '0.25in')
|
| 53 |
for x in range(6):
|
| 54 |
d.add(d.line(('{0}in'.format(x*1.6), '0in'),
|
| 55 |
('{0}in'.format(x*1.6), '8in'),
|
| 56 |
stroke=svgwrite.rgb(0, 0, 0))).translate(45, 45)
|
| 57 |
for y in range(6):
|
| 58 |
d.add(d.line(('0in', '{0}in'.format(y*1.6)),
|
| 59 |
('8in', '{0}in'.format(y*1.6)),
|
| 60 |
stroke=svgwrite.rgb(0, 0, 0))).translate(45, 45)
|
| 61 |
for x in range(5):
|
| 62 |
for y in range(5):
|
| 63 |
if x == 2 and y == 2:
|
| 64 |
text = 'FREE\nSQUARE'
|
| 65 |
color = '#b00'
|
| 66 |
else:
|
| 67 |
text = choices.pop()
|
| 68 |
color = '#000'
|
| 69 |
d.add(d.text(text,
|
| 70 |
insert=
|
| 71 |
('{0}in'.format(x*1.6 + 0.8),
|
| 72 |
'{0}in'.format(y*1.6 + 0.8)),
|
| 73 |
text_anchor='middle',
|
| 74 |
alignment_baseline='central',
|
| 75 |
style=TEXT_STYLE,
|
| 76 |
fill=color)).translate(45, 45)
|
| 77 |
return d.tostring()
|
| 78 |
|
| 79 |
|
| 80 |
if __name__ == '__main__':
|
| 81 |
app.run()
|