| 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()
                  
                 |