gdritter repos bingo / master bingo.py
master

Tree @master (Download .tar.gz)

bingo.py @masterraw · history · blame

#!/usr/bin/env python3

import base64
import flask
import io
import random
import openpyxl
import os
import svgwrite
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF

app = flask.Flask(__name__)

TEXT_STYLE = 'font-family: "Arial", "Helvetica", sans-serif;'

@app.route('/')
def index():
    return flask.send_from_directory('.', 'page.html')


@app.route('/process', methods=['POST'])
def process():
    if 'file' not in flask.request.files:
        raise Exception('No file uploaded!')
    f = flask.request.files['file']
    if f.filename == '':
        raise Exception('No file uploaded!')
    choices = choices_from_excel(openpyxl.load_workbook(f.stream))
    choice_str = base64.urlsafe_b64encode('\x1c'.join(choices).encode('utf-8'))
    return flask.redirect('/bingo.pdf?choices={0}'.format(choice_str.decode('utf-8')))


@app.route('/bingo.svg')
@app.route('/bingo.pdf')
def generate():
    choice_str = base64.urlsafe_b64decode(flask.request.args.get('choices'))
    choices = choice_str.decode('utf-8').split('\x1c')
    return mk_svg(choices), 200, {'Content-Type': 'application/pdf'}


def choices_from_excel(wb):
    sheet = wb.get_sheet_by_name(wb.get_sheet_names()[0])
    choices = []
    for row in range(1, sheet.max_row + 1):
        choices.append(sheet.cell(row=row, column=1).value)
    return choices


def mk_svg(choices):
    choices = list(choices)
    if len(choices) < 24:
        raise Exception('Must have at least 24 possible choices!')
    random.shuffle(choices)

    # make the empty drawing
    d = svgwrite.Drawing(size=('8.5in', '11in'))

    # draw the lines
    for x in range(6):
        d.add(d.line(('{0}in'.format(x*1.6), '0in'),
                     ('{0}in'.format(x*1.6), '8in'),
                     stroke=svgwrite.rgb(0, 0, 0))).translate(22.5, 22.5)
    for y in range(6):
        d.add(d.line(('0in', '{0}in'.format(y*1.6)),
                     ('8in', '{0}in'.format(y*1.6)),
                     stroke=svgwrite.rgb(0, 0, 0))).translate(22.5, 22.5)

    # draw the text
    for x in range(5):
        for y in range(5):
            if x == 2 and y == 2:
                text = 'FREE SQUARE'
                color = '#b00'
            else:
                text = choices.pop()
                color = '#000'
            d.add(d.text(text,
                         insert=
                         ('{0}in'.format(x*1.6 + 0.8),
                          '{0}in'.format(y*1.6 + 0.8)),
                         text_anchor='middle',
                         alignment_baseline='central',
                         style=TEXT_STYLE,
                         fill=color)).translate(22.5, 22.5)

    buf = io.StringIO(d.tostring())
    r = svg2rlg(buf)
    return renderPDF.drawToString(r)
    # return d.tostring()


if __name__ == '__main__':
    if os.getenv('DEBUG'):
        app.run()
    else:
        from flup.server.fcgi import WSGIServer
        WSGIServer(app, bindAddress='/var/run/www/bingo.sock').run()