Bunco Simulator

Hex Artifact Content

Artifact b91166ec316051ac8fb6511badaf7d1af1d3ee132753db99c58e15d6c5817263:


0000: 69 6d 70 6f 72 74 20 62 75 6e 63 6f 0a 69 6d 70  import bunco.imp
0010: 6f 72 74 20 78 6c 73 78 77 72 69 74 65 72 0a 69  ort xlsxwriter.i
0020: 6d 70 6f 72 74 20 63 72 65 64 73 20 23 20 6c 6f  mport creds # lo
0030: 63 61 6c 0a 66 72 6f 6d 20 62 6c 65 73 73 69 6e  cal.from blessin
0040: 67 73 20 69 6d 70 6f 72 74 20 54 65 72 6d 69 6e  gs import Termin
0050: 61 6c 0a 66 72 6f 6d 20 74 77 69 6c 69 6f 2e 72  al.from twilio.r
0060: 65 73 74 20 69 6d 70 6f 72 74 20 43 6c 69 65 6e  est import Clien
0070: 74 0a 0a 74 20 3d 20 54 65 72 6d 69 6e 61 6c 28  t..t = Terminal(
0080: 29 0a 67 20 3d 20 62 75 6e 63 6f 2e 47 61 6d 65  ).g = bunco.Game
0090: 28 22 70 6c 61 79 65 72 73 2e 63 73 76 22 29 0a  ("players.csv").
00a0: 0a 65 6e 61 62 6c 65 5f 73 6d 73 20 3d 20 46 61  .enable_sms = Fa
00b0: 6c 73 65 0a 6c 61 73 74 5f 73 74 61 74 75 73 20  lse.last_status 
00c0: 3d 20 27 4f 66 66 20 74 6f 20 61 20 67 72 65 61  = 'Off to a grea
00d0: 74 20 73 74 61 72 74 21 27 0a 0a 64 65 66 20 70  t start!'..def p
00e0: 6c 75 72 61 6c 28 73 74 72 2c 6e 2c 73 75 66 66  lural(str,n,suff
00f0: 69 78 3d 22 73 22 29 3a 0a 20 20 20 20 72 65 74  ix="s"):.    ret
0100: 75 72 6e 20 73 74 72 20 2b 20 73 75 66 66 69 78  urn str + suffix
0110: 20 69 66 20 6e 20 3e 20 31 20 65 6c 73 65 20 73   if n > 1 else s
0120: 74 72 0a 0a 64 65 66 20 70 72 69 6e 74 5f 63 65  tr..def print_ce
0130: 6e 74 65 72 28 62 65 66 6f 72 65 2c 20 73 74 72  nter(before, str
0140: 69 6e 67 2c 20 61 66 74 65 72 29 3a 0a 20 20 20  ing, after):.   
0150: 20 63 6f 6c 20 3d 20 69 6e 74 28 28 74 2e 77 69   col = int((t.wi
0160: 64 74 68 20 2d 20 6c 65 6e 28 73 74 72 69 6e 67  dth - len(string
0170: 29 29 20 2f 20 32 29 20 2d 20 31 0a 20 20 20 20  )) / 2) - 1.    
0180: 70 72 69 6e 74 28 66 22 7b 74 2e 6d 6f 76 65 5f  print(f"{t.move_
0190: 78 28 63 6f 6c 29 7d 7b 62 65 66 6f 72 65 7d 7b  x(col)}{before}{
01a0: 73 74 72 69 6e 67 7d 7b 61 66 74 65 72 7d 22 29  string}{after}")
01b0: 0a 0a 64 65 66 20 73 74 61 74 75 73 28 74 65 78  ..def status(tex
01c0: 74 29 3a 0a 20 20 20 20 67 6c 6f 62 61 6c 20 6c  t):.    global l
01d0: 61 73 74 5f 73 74 61 74 75 73 0a 20 20 20 20 72  ast_status.    r
01e0: 6f 77 20 3d 20 36 20 2b 20 28 6c 65 6e 28 67 2e  ow = 6 + (len(g.
01f0: 74 61 62 6c 65 73 29 20 2a 20 35 29 0a 20 20 20  tables) * 5).   
0200: 20 70 72 69 6e 74 28 74 2e 6d 6f 76 65 28 72 6f   print(t.move(ro
0210: 77 2c 20 30 29 2c 20 65 6e 64 3d 27 27 29 0a 20  w, 0), end=''). 
0220: 20 20 20 70 72 69 6e 74 28 74 2e 63 6c 65 61 72     print(t.clear
0230: 5f 65 6f 6c 2c 20 65 6e 64 3d 27 27 29 0a 20 20  _eol, end='').  
0240: 20 20 70 72 69 6e 74 5f 63 65 6e 74 65 72 28 66    print_center(f
0250: 22 7b 74 2e 62 6f 6c 64 5f 67 72 65 65 6e 7d 22  "{t.bold_green}"
0260: 2c 66 22 5b 20 7b 74 65 78 74 7d 20 5d 22 2c 20  ,f"[ {text} ]", 
0270: 74 2e 6e 6f 72 6d 61 6c 29 0a 20 20 20 20 70 72  t.normal).    pr
0280: 69 6e 74 28 74 2e 63 6c 65 61 72 5f 65 6f 73 29  int(t.clear_eos)
0290: 0a 20 20 20 20 6c 61 73 74 5f 73 74 61 74 75 73  .    last_status
02a0: 20 3d 20 74 65 78 74 0a 0a 64 65 66 20 64 69 73   = text..def dis
02b0: 70 6c 61 79 5f 64 61 73 68 62 6f 61 72 64 28 29  play_dashboard()
02c0: 3a 0a 20 20 20 20 70 72 69 6e 74 28 74 2e 63 6c  :.    print(t.cl
02d0: 65 61 72 2c 74 2e 6d 6f 76 65 28 30 2c 30 29 29  ear,t.move(0,0))
02e0: 0a 20 20 20 20 70 72 69 6e 74 5f 63 65 6e 74 65  .    print_cente
02f0: 72 28 74 2e 62 6f 6c 64 5f 72 65 64 2c 22 42 20  r(t.bold_red,"B 
0300: 55 20 4e 20 43 20 4f 20 20 20 53 20 49 20 4d 20  U N C O   S I M 
0310: 55 20 4c 20 41 20 54 20 4f 20 52 22 2c 20 74 2e  U L A T O R", t.
0320: 6e 6f 72 6d 61 6c 29 0a 20 20 20 20 70 72 69 6e  normal).    prin
0330: 74 28 66 22 7b 74 2e 72 65 64 7d 7b 27 2d 27 2a  t(f"{t.red}{'-'*
0340: 74 2e 77 69 64 74 68 7d 7b 74 2e 6e 6f 72 6d 61  t.width}{t.norma
0350: 6c 7d 5c 6e 22 29 0a 20 20 20 20 0a 20 20 20 20  l}\n").    .    
0360: 23 20 50 72 69 6e 74 20 63 6f 6c 75 6d 6e 20 68  # Print column h
0370: 65 61 64 69 6e 67 73 20 66 6f 72 20 72 6f 75 6e  eadings for roun
0380: 64 73 0a 20 20 20 20 72 6f 75 6e 64 73 20 3d 20  ds.    rounds = 
0390: 5b 73 74 72 28 6e 20 2b 20 31 29 2e 72 6a 75 73  [str(n + 1).rjus
03a0: 74 28 34 29 20 66 6f 72 20 6e 20 69 6e 20 72 61  t(4) for n in ra
03b0: 6e 67 65 28 67 2e 63 75 72 72 65 6e 74 5f 72 6f  nge(g.current_ro
03c0: 75 6e 64 28 29 29 5d 0a 20 20 20 20 72 6f 75 6e  und())].    roun
03d0: 64 5f 73 74 72 20 3d 20 22 22 2e 6a 6f 69 6e 28  d_str = "".join(
03e0: 72 6f 75 6e 64 73 29 0a 20 20 20 20 70 72 69 6e  rounds).    prin
03f0: 74 28 66 22 7b 74 2e 6d 6f 76 65 5f 78 28 31 38  t(f"{t.move_x(18
0400: 29 7d 7b 74 2e 62 6f 6c 64 7d 7b 72 6f 75 6e 64  )}{t.bold}{round
0410: 5f 73 74 72 7d 7b 74 2e 6e 6f 72 6d 61 6c 7d 22  _str}{t.normal}"
0420: 29 0a 0a 20 20 20 20 23 20 50 72 69 6e 74 20 74  )..    # Print t
0430: 61 62 6c 65 20 6f 66 20 70 6c 61 79 65 72 73 20  able of players 
0440: 61 6e 64 20 74 68 65 69 72 20 73 63 6f 72 65 73  and their scores
0450: 20 65 61 63 68 20 72 6f 75 6e 64 0a 20 20 20 20   each round.    
0460: 66 6f 72 20 74 61 62 6c 65 20 69 6e 20 67 2e 74  for table in g.t
0470: 61 62 6c 65 73 3a 0a 20 20 20 20 20 20 20 20 70  ables:.        p
0480: 72 69 6e 74 28 66 22 20 20 7b 74 2e 62 6c 75 65  rint(f"  {t.blue
0490: 7d 7b 74 61 62 6c 65 7d 22 29 0a 20 20 20 20 20  }{table}").     
04a0: 20 20 20 66 6f 72 20 70 6c 61 79 65 72 20 69 6e     for player in
04b0: 20 74 61 62 6c 65 2e 70 6c 61 79 65 72 73 3a 0a   table.players:.
04c0: 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20 70              if p
04d0: 6c 61 79 65 72 20 69 73 20 62 75 6e 63 6f 2e 66  layer is bunco.f
04e0: 75 7a 7a 79 64 69 65 5f 68 6f 6c 64 65 72 3a 0a  uzzydie_holder:.
04f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
0500: 70 72 69 6e 74 28 66 22 f0 9f 8e b2 22 2c 65 6e  print(f"....",en
0510: 64 3d 27 27 29 0a 20 20 20 20 20 20 20 20 20 20  d='').          
0520: 20 20 70 72 69 6e 74 28 66 22 7b 74 2e 6d 6f 76    print(f"{t.mov
0530: 65 5f 78 28 33 29 7d 7b 74 2e 63 79 61 6e 7d 7b  e_x(3)}{t.cyan}{
0540: 70 6c 61 79 65 72 7d 7b 74 2e 6e 6f 72 6d 61 6c  player}{t.normal
0550: 7d 22 2c 65 6e 64 3d 27 27 29 0a 20 20 20 20 20  }",end='').     
0560: 20 20 20 20 20 20 20 66 6f 72 20 6e 20 69 6e 20         for n in 
0570: 72 61 6e 67 65 28 67 2e 63 75 72 72 65 6e 74 5f  range(g.current_
0580: 72 6f 75 6e 64 28 29 29 3a 0a 20 20 20 20 20 20  round()):.      
0590: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
05a0: 74 2e 6d 6f 76 65 5f 78 28 31 38 2b 28 34 2a 6e  t.move_x(18+(4*n
05b0: 29 29 2c 65 6e 64 3d 27 27 29 0a 20 20 20 20 20  )),end='').     
05c0: 20 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74             print
05d0: 28 73 74 72 28 70 6c 61 79 65 72 2e 72 6f 75 6e  (str(player.roun
05e0: 64 5f 73 63 6f 72 65 73 5b 6e 5d 29 2e 72 6a 75  d_scores[n]).rju
05f0: 73 74 28 34 29 2c 65 6e 64 3d 27 27 29 0a 20 20  st(4),end='').  
0600: 20 20 20 20 20 20 20 20 20 20 70 72 69 6e 74 28            print(
0610: 27 27 29 0a 20 20 20 20 73 74 61 74 75 73 28 6c  '').    status(l
0620: 61 73 74 5f 73 74 61 74 75 73 29 0a 0a 64 65 66  ast_status)..def
0630: 20 64 6f 31 28 29 3a 0a 20 20 20 20 67 2e 70 6c   do1():.    g.pl
0640: 61 79 5f 6f 6e 65 5f 72 6f 75 6e 64 28 29 0a 20  ay_one_round(). 
0650: 20 20 20 69 66 20 65 6e 61 62 6c 65 5f 73 6d 73     if enable_sms
0660: 3a 0a 20 20 20 20 20 20 20 20 73 74 61 74 75 73  :.        status
0670: 28 22 53 65 6e 64 69 6e 67 20 72 65 73 75 6c 74  ("Sending result
0680: 73 20 62 79 20 53 4d 53 20 74 6f 20 70 6c 61 79  s by SMS to play
0690: 65 72 73 e2 80 a6 22 29 0a 20 20 20 20 20 20 20  ers...").       
06a0: 20 66 6f 72 20 70 6c 61 79 65 72 20 69 6e 20 67   for player in g
06b0: 2e 70 6c 61 79 65 72 73 3a 0a 20 20 20 20 20 20  .players:.      
06c0: 20 20 20 20 20 20 73 6d 73 28 70 6c 61 79 65 72        sms(player
06d0: 2e 73 6d 73 6e 75 6d 62 65 72 2c 20 73 75 6d 6d  .smsnumber, summ
06e0: 61 72 79 5f 74 65 78 74 28 70 6c 61 79 65 72 29  ary_text(player)
06f0: 29 0a 20 20 20 20 0a 20 20 20 20 64 69 73 70 6c  ).    .    displ
0700: 61 79 5f 64 61 73 68 62 6f 61 72 64 28 29 0a 20  ay_dashboard(). 
0710: 20 20 20 73 74 61 74 75 73 28 22 50 72 65 70 70     status("Prepp
0720: 69 6e 67 20 66 6f 72 20 6e 65 78 74 20 72 6f 75  ing for next rou
0730: 6e 64 e2 80 a6 22 29 0a 20 20 20 20 67 2e 70 72  nd...").    g.pr
0740: 65 70 5f 6e 65 78 74 5f 72 6f 75 6e 64 28 29 0a  ep_next_round().
0750: 20 20 20 20 73 74 61 74 75 73 28 22 52 65 61 64      status("Read
0760: 79 20 66 6f 72 20 61 6e 6f 74 68 65 72 20 72 6f  y for another ro
0770: 75 6e 64 21 22 29 0a 0a 64 65 66 20 73 75 6d 6d  und!")..def summ
0780: 61 72 79 28 6e 29 3a 0a 20 20 20 20 72 65 74 75  ary(n):.    retu
0790: 72 6e 20 73 75 6d 6d 61 72 79 5f 74 65 78 74 28  rn summary_text(
07a0: 67 2e 70 6c 61 79 65 72 73 5b 6e 5d 29 0a 0a 64  g.players[n])..d
07b0: 65 66 20 73 6d 73 28 6e 75 6d 62 65 72 2c 20 6d  ef sms(number, m
07c0: 65 73 73 61 67 65 29 3a 0a 20 20 20 20 69 66 20  essage):.    if 
07d0: 65 6e 61 62 6c 65 5f 73 6d 73 20 61 6e 64 20 6e  enable_sms and n
07e0: 75 6d 62 65 72 3a 0a 20 20 20 20 20 20 20 20 63  umber:.        c
07f0: 6c 69 20 3d 20 43 6c 69 65 6e 74 28 63 72 65 64  li = Client(cred
0800: 73 2e 53 49 44 2c 20 63 72 65 64 73 2e 74 6f 6b  s.SID, creds.tok
0810: 65 6e 29 0a 20 20 20 20 20 20 20 20 63 6c 69 2e  en).        cli.
0820: 6d 65 73 73 61 67 65 73 2e 63 72 65 61 74 65 28  messages.create(
0830: 74 6f 3d 6e 75 6d 62 65 72 2c 20 66 72 6f 6d 5f  to=number, from_
0840: 3d 63 72 65 64 73 2e 73 65 6e 64 65 72 2c 20 62  =creds.sender, b
0850: 6f 64 79 3d 6d 65 73 73 61 67 65 29 0a 0a 64 65  ody=message)..de
0860: 66 20 73 75 6d 6d 61 72 79 5f 74 65 78 74 28 70  f summary_text(p
0870: 6c 61 79 65 72 29 3a 0a 20 20 20 20 66 6f 72 20  layer):.    for 
0880: 74 61 62 6c 65 20 69 6e 20 67 2e 74 61 62 6c 65  table in g.table
0890: 73 3a 0a 20 20 20 20 20 20 20 20 69 66 20 70 6c  s:.        if pl
08a0: 61 79 65 72 20 69 6e 20 74 61 62 6c 65 2e 70 6c  ayer in table.pl
08b0: 61 79 65 72 73 3a 0a 20 20 20 20 20 20 20 20 20  ayers:.         
08c0: 20 20 20 63 75 72 74 61 62 6c 65 20 3d 20 74 61     curtable = ta
08d0: 62 6c 65 0a 20 20 20 20 20 20 20 20 20 20 20 20  ble.            
08e0: 62 72 65 61 6b 0a 20 20 20 20 0a 20 20 20 20 73  break.    .    s
08f0: 69 74 63 68 20 3d 20 63 75 72 74 61 62 6c 65 2e  itch = curtable.
0900: 67 65 74 5f 70 6c 61 79 65 72 5f 73 69 74 75 61  get_player_situa
0910: 74 69 6f 6e 28 70 6c 61 79 65 72 29 0a 0a 20 20  tion(player)..  
0920: 20 20 69 66 20 70 6c 61 79 65 72 2e 72 6f 75 6e    if player.roun
0930: 64 5f 73 63 6f 72 65 73 5b 67 2e 63 75 72 72 65  d_scores[g.curre
0940: 6e 74 5f 72 6f 75 6e 64 28 29 2d 31 5d 20 3e 20  nt_round()-1] > 
0950: 73 69 74 63 68 5b 27 6f 70 70 6f 6e 65 6e 74 5f  sitch['opponent_
0960: 73 63 6f 72 65 27 5d 3a 0a 20 20 20 20 20 20 20  score']:.       
0970: 20 77 69 6e 6c 6f 73 73 20 3d 20 22 62 65 61 74   winloss = "beat
0980: 69 6e 67 22 0a 20 20 20 20 65 6c 73 65 3a 0a 20  ing".    else:. 
0990: 20 20 20 20 20 20 20 77 69 6e 6c 6f 73 73 20 3d         winloss =
09a0: 20 22 6c 6f 73 69 6e 67 20 74 6f 22 0a 20 20 20   "losing to".   
09b0: 20 66 6f 65 5f 6e 61 6d 65 73 20 3d 20 22 20 26   foe_names = " &
09c0: 20 22 2e 6a 6f 69 6e 28 5b 73 74 72 28 6f 70 70   ".join([str(opp
09d0: 29 20 66 6f 72 20 6f 70 70 20 69 6e 20 73 69 74  ) for opp in sit
09e0: 63 68 5b 27 6f 70 70 6f 6e 65 6e 74 73 27 5d 5d  ch['opponents']]
09f0: 29 0a 0a 20 20 20 20 62 75 6e 63 6f 5f 63 74 20  )..    bunco_ct 
0a00: 3d 20 70 6c 61 79 65 72 2e 72 6f 75 6e 64 5f 62  = player.round_b
0a10: 75 6e 63 6f 5f 63 6f 75 6e 74 73 5b 67 2e 63 75  unco_counts[g.cu
0a20: 72 72 65 6e 74 5f 72 6f 75 6e 64 28 29 2d 31 5d  rrent_round()-1]
0a30: 0a 20 20 20 20 69 66 20 62 75 6e 63 6f 5f 63 74  .    if bunco_ct
0a40: 20 3e 20 30 3a 0a 20 20 20 20 20 20 20 20 62 75   > 0:.        bu
0a50: 6e 63 6f 73 20 3d 20 66 22 20 28 26 20 7b 62 75  ncos = f" (& {bu
0a60: 6e 63 6f 5f 63 74 7d 20 7b 70 6c 75 72 61 6c 28  nco_ct} {plural(
0a70: 27 62 75 6e 63 6f 27 2c 62 75 6e 63 6f 5f 63 74  'bunco',bunco_ct
0a80: 29 7d 21 29 22 0a 20 20 20 20 65 6c 73 65 3a 0a  )}!)".    else:.
0a90: 20 20 20 20 20 20 20 20 62 75 6e 63 6f 73 20 3d          buncos =
0aa0: 20 22 22 0a 0a 20 20 20 20 74 73 20 3d 20 5b 66   ""..    ts = [f
0ab0: 22 52 6f 75 6e 64 20 7b 67 2e 63 75 72 72 65 6e  "Round {g.curren
0ac0: 74 5f 72 6f 75 6e 64 28 29 7d 20 40 20 7b 63 75  t_round()} @ {cu
0ad0: 72 74 61 62 6c 65 7d 20 77 69 74 68 20 7b 73 69  rtable} with {si
0ae0: 74 63 68 5b 27 74 65 61 6d 6d 61 74 65 27 5d 7d  tch['teammate']}
0af0: 3a 22 2c 0a 20 20 20 20 20 20 20 20 20 20 66 22  :",.          f"
0b00: 59 6f 75 20 6d 61 64 65 20 7b 70 6c 61 79 65 72  You made {player
0b10: 2e 72 6f 75 6e 64 5f 72 6f 6c 6c 5f 63 6f 75 6e  .round_roll_coun
0b20: 74 73 5b 67 2e 63 75 72 72 65 6e 74 5f 72 6f 75  ts[g.current_rou
0b30: 6e 64 28 29 2d 31 5d 7d 20 72 6f 6c 6c 73 2c 22  nd()-1]} rolls,"
0b40: 2c 0a 20 20 20 20 20 20 20 20 20 20 66 22 61 64  ,.          f"ad
0b50: 64 69 6e 67 20 7b 70 6c 61 79 65 72 2e 70 65 72  ding {player.per
0b60: 73 6f 6e 61 6c 5f 72 6f 6c 6c 5f 73 63 6f 72 65  sonal_roll_score
0b70: 73 5b 67 2e 63 75 72 72 65 6e 74 5f 72 6f 75 6e  s[g.current_roun
0b80: 64 28 29 2d 31 5d 7d 20 70 74 73 7b 62 75 6e 63  d()-1]} pts{bunc
0b90: 6f 73 7d 22 2c 0a 20 20 20 20 20 20 20 20 20 20  os}",.          
0ba0: 66 22 74 6f 20 79 6f 75 72 20 74 65 61 6d 20 73  f"to your team s
0bb0: 63 6f 72 65 20 6f 66 20 7b 70 6c 61 79 65 72 2e  core of {player.
0bc0: 72 6f 75 6e 64 5f 73 63 6f 72 65 73 5b 67 2e 63  round_scores[g.c
0bd0: 75 72 72 65 6e 74 5f 72 6f 75 6e 64 28 29 2d 31  urrent_round()-1
0be0: 5d 7d 2c 22 2c 0a 20 20 20 20 20 20 20 20 20 20  ]},",.          
0bf0: 66 22 7b 77 69 6e 6c 6f 73 73 7d 20 7b 66 6f 65  f"{winloss} {foe
0c00: 5f 6e 61 6d 65 73 7d e2 80 99 73 20 73 63 6f 72  _names}...s scor
0c10: 65 20 6f 66 20 7b 73 69 74 63 68 5b 27 6f 70 70  e of {sitch['opp
0c20: 6f 6e 65 6e 74 5f 73 63 6f 72 65 27 5d 7d 2e 22  onent_score']}."
0c30: 5d 0a 20 20 20 20 72 65 74 75 72 6e 20 22 20 22  ].    return " "
0c40: 2e 6a 6f 69 6e 28 74 73 29 0a 0a 64 65 66 20 73  .join(ts)..def s
0c50: 6d 73 5f 74 61 62 6c 65 5f 6d 6f 76 65 28 70 6c  ms_table_move(pl
0c60: 61 79 65 72 2c 20 77 6f 6e 6c 6f 73 74 2c 20 74  ayer, wonlost, t
0c70: 61 62 6c 65 5f 66 72 6f 6d 2c 20 74 61 62 6c 65  able_from, table
0c80: 5f 74 6f 29 3a 0a 20 20 20 20 69 66 20 70 6c 61  _to):.    if pla
0c90: 79 65 72 2e 73 6d 73 6e 75 6d 62 65 72 3a 0a 20  yer.smsnumber:. 
0ca0: 20 20 20 20 20 20 20 6d 65 73 73 61 67 65 20 3d         message =
0cb0: 20 66 22 48 61 76 69 6e 67 20 7b 77 6f 6e 6c 6f   f"Having {wonlo
0cc0: 73 74 7d 20 74 68 65 20 6c 61 73 74 20 72 6f 75  st} the last rou
0cd0: 6e 64 2c 20 79 6f 75 20 6d 6f 76 65 20 66 72 6f  nd, you move fro
0ce0: 6d 20 7b 74 61 62 6c 65 5f 66 72 6f 6d 7d 20 74  m {table_from} t
0cf0: 6f 20 7b 74 61 62 6c 65 5f 74 6f 7d 2e 22 0a 20  o {table_to}.". 
0d00: 20 20 20 20 20 20 20 73 6d 73 28 70 6c 61 79 65         sms(playe
0d10: 72 2e 73 6d 73 6e 75 6d 62 65 72 2c 20 6d 65 73  r.smsnumber, mes
0d20: 73 61 67 65 29 0a 0a 62 75 6e 63 6f 2e 74 61 62  sage)..bunco.tab
0d30: 6c 65 5f 6d 6f 76 65 5f 63 61 6c 6c 62 61 63 6b  le_move_callback
0d40: 20 3d 20 73 6d 73 5f 74 61 62 6c 65 5f 6d 6f 76   = sms_table_mov
0d50: 65 0a 0a 64 65 66 20 73 6d 73 5f 61 6c 6c 5f 73  e..def sms_all_s
0d60: 69 74 75 61 74 69 6f 6e 73 28 29 3a 0a 20 20 20  ituations():.   
0d70: 20 66 6f 72 20 74 61 62 6c 65 20 69 6e 20 67 2e   for table in g.
0d80: 74 61 62 6c 65 73 3a 0a 20 20 20 20 20 20 20 20  tables:.        
0d90: 66 6f 72 20 70 6c 61 79 65 72 20 69 6e 20 74 61  for player in ta
0da0: 62 6c 65 2e 70 6c 61 79 65 72 73 3a 0a 20 20 20  ble.players:.   
0db0: 20 20 20 20 20 20 20 20 20 69 66 20 70 6c 61 79           if play
0dc0: 65 72 2e 73 6d 73 6e 75 6d 62 65 72 3a 0a 20 20  er.smsnumber:.  
0dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73 69                si
0de0: 74 63 68 20 3d 20 74 61 62 6c 65 2e 67 65 74 5f  tch = table.get_
0df0: 70 6c 61 79 65 72 5f 73 69 74 75 61 74 69 6f 6e  player_situation
0e00: 28 70 6c 61 79 65 72 29 0a 20 20 20 20 20 20 20  (player).       
0e10: 20 20 20 20 20 20 20 20 20 6d 73 67 20 3d 20 66           msg = f
0e20: 22 59 6f 75 20 61 72 65 20 73 69 74 74 69 6e 67  "You are sitting
0e30: 20 61 74 20 7b 74 61 62 6c 65 7d 20 77 69 74 68   at {table} with
0e40: 20 7b 73 69 74 63 68 5b 27 74 65 61 6d 6d 61 74   {sitch['teammat
0e50: 65 27 5d 7d 20 66 6f 72 20 61 20 74 65 61 6d 6d  e']} for a teamm
0e60: 61 74 65 2e 20 22 20 5c 0a 20 20 20 20 20 20 20  ate. " \.       
0e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 2b 20 66               + f
0e80: 22 7b 73 69 74 63 68 5b 27 6f 70 70 6f 6e 65 6e  "{sitch['opponen
0e90: 74 73 27 5d 5b 30 5d 7d 20 61 6e 64 20 7b 73 69  ts'][0]} and {si
0ea0: 74 63 68 5b 27 6f 70 70 6f 6e 65 6e 74 73 27 5d  tch['opponents']
0eb0: 5b 31 5d 7d 20 66 6f 72 6d 20 74 68 65 20 6f 70  [1]} form the op
0ec0: 70 6f 73 69 74 69 6f 6e 2e 22 0a 20 20 20 20 20  position.".     
0ed0: 20 20 20 20 20 20 20 20 20 20 20 73 6d 73 28 70             sms(p
0ee0: 6c 61 79 65 72 2e 73 6d 73 6e 75 6d 62 65 72 2c  layer.smsnumber,
0ef0: 20 6d 73 67 29 0a 0a 64 65 66 20 73 6d 73 5f 61   msg)..def sms_a
0f00: 6c 6c 28 6d 65 73 73 61 67 65 29 3a 0a 20 20 20  ll(message):.   
0f10: 20 69 66 20 65 6e 61 62 6c 65 5f 73 6d 73 3a 0a   if enable_sms:.
0f20: 20 20 20 20 20 20 20 20 73 74 61 74 75 73 28 22          status("
0f30: 53 65 6e 64 69 6e 67 20 53 4d 53 20 74 6f 20 61  Sending SMS to a
0f40: 6c 6c 20 70 6c 61 79 65 72 73 e2 80 a6 22 29 0a  ll players...").
0f50: 20 20 20 20 20 20 20 20 66 6f 72 20 70 6c 61 79          for play
0f60: 65 72 20 69 6e 20 67 2e 70 6c 61 79 65 72 73 3a  er in g.players:
0f70: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
0f80: 70 6c 61 79 65 72 2e 73 6d 73 6e 75 6d 62 65 72  player.smsnumber
0f90: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
0fa0: 20 20 73 6d 73 28 70 6c 61 79 65 72 2e 73 6d 73    sms(player.sms
0fb0: 6e 75 6d 62 65 72 2c 20 6d 65 73 73 61 67 65 29  number, message)
0fc0: 0a 20 20 20 20 65 6c 73 65 3a 0a 20 20 20 20 20  .    else:.     
0fd0: 20 20 20 73 74 61 74 75 73 28 22 53 4d 53 20 6d     status("SMS m
0fe0: 65 73 73 61 67 69 6e 67 20 69 73 20 64 69 73 61  essaging is disa
0ff0: 62 6c 65 64 21 22 29 0a 0a 64 69 73 70 6c 61 79  bled!")..display
1000: 5f 64 61 73 68 62 6f 61 72 64 28 29 0a 0a 64 65  _dashboard()..de
1010: 66 20 65 78 63 65 6c 5f 73 68 65 65 74 28 74 69  f excel_sheet(ti
1020: 74 6c 65 29 3a 0a 20 20 20 20 77 62 20 3d 20 78  tle):.    wb = x
1030: 6c 73 78 77 72 69 74 65 72 2e 57 6f 72 6b 62 6f  lsxwriter.Workbo
1040: 6f 6b 28 27 62 75 6e 63 6f 2e 78 6c 73 78 27 29  ok('bunco.xlsx')
1050: 0a 20 20 20 20 77 73 20 3d 20 77 62 2e 61 64 64  .    ws = wb.add
1060: 5f 77 6f 72 6b 73 68 65 65 74 28 27 4f 76 65 72  _worksheet('Over
1070: 76 69 65 77 27 29 0a 20 20 20 20 73 74 79 6c 65  view').    style
1080: 20 3d 20 7b 7d 0a 0a 20 20 20 20 63 6f 6c 5f 68   = {}..    col_h
1090: 65 61 64 69 6e 67 20 3d 20 77 62 2e 61 64 64 5f  eading = wb.add_
10a0: 66 6f 72 6d 61 74 28 7b 27 66 6f 6e 74 5f 6e 61  format({'font_na
10b0: 6d 65 27 3a 20 27 42 61 63 6b 20 49 73 73 75 65  me': 'Back Issue
10c0: 73 20 42 42 27 2c 20 0a 20 20 20 20 20 20 20 20  s BB', .        
10d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
10e0: 20 20 20 20 20 20 20 20 20 27 66 6f 6e 74 5f 73           'font_s
10f0: 69 7a 65 27 3a 20 31 32 2c 0a 20 20 20 20 20 20  ize': 12,.      
1100: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1110: 20 20 20 20 20 20 20 20 20 20 20 27 61 6c 69 67             'alig
1120: 6e 27 3a 20 27 63 65 6e 74 65 72 27 7d 29 0a 20  n': 'center'}). 
1130: 20 20 20 74 69 74 6c 65 5f 73 74 79 6c 65 20 3d     title_style =
1140: 20 77 62 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b   wb.add_format({
1150: 27 66 6f 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61  'font_name': 'Ba
1160: 63 6b 20 49 73 73 75 65 73 20 42 42 27 2c 20 0a  ck Issues BB', .
1170: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1180: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1190: 20 27 66 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 34   'font_size': 14
11a0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
11b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
11c0: 20 20 20 27 62 6f 6c 64 27 3a 20 54 72 75 65 7d     'bold': True}
11d0: 29 0a 20 20 20 20 72 6f 77 5f 68 65 61 64 69 6e  ).    row_headin
11e0: 67 20 3d 20 77 62 2e 61 64 64 5f 66 6f 72 6d 61  g = wb.add_forma
11f0: 74 28 7b 27 66 6f 6e 74 5f 6e 61 6d 65 27 3a 20  t({'font_name': 
1200: 27 42 61 63 6b 20 49 73 73 75 65 73 20 42 42 27  'Back Issues BB'
1210: 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  , .             
1220: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1230: 20 20 20 20 27 66 6f 6e 74 5f 73 69 7a 65 27 3a      'font_size':
1240: 20 31 32 7d 29 0a 20 20 20 20 73 63 6f 72 65 5f   12}).    score_
1250: 73 74 79 6c 65 20 3d 20 77 62 2e 61 64 64 5f 66  style = wb.add_f
1260: 6f 72 6d 61 74 28 7b 27 66 6f 6e 74 5f 6e 61 6d  ormat({'font_nam
1270: 65 27 3a 20 27 4d 69 6c 6b 20 4d 75 73 74 61 63  e': 'Milk Mustac
1280: 68 65 20 42 42 27 2c 20 0a 20 20 20 20 20 20 20  he BB', .       
1290: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12a0: 20 20 20 20 20 20 20 20 20 20 27 66 6f 6e 74 5f            'font_
12b0: 73 69 7a 65 27 3a 20 31 34 2c 0a 20 20 20 20 20  size': 14,.     
12c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
12d0: 20 20 20 20 20 20 20 20 20 20 20 20 27 61 6c 69              'ali
12e0: 67 6e 27 3a 20 27 72 69 67 68 74 27 2c 0a 20 20  gn': 'right',.  
12f0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1300: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27                 '
1310: 6e 75 6d 5f 66 6f 72 6d 61 74 27 3a 20 27 5f 28  num_format': '_(
1320: 2a 20 23 2c 23 23 30 5f 29 3b 5f 28 2a 20 28 23  * #,##0_);_(* (#
1330: 2c 23 23 30 29 3b 5f 28 2a 20 22 2d 22 3f 3f 5f  ,##0);_(* "-"??_
1340: 29 3b 5f 28 40 5f 29 27 2c 0a 20 20 20 20 20 20  );_(@_)',.      
1350: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1360: 20 20 20 20 20 20 20 20 20 20 20 27 63 6f 6c 6f             'colo
1370: 72 27 3a 20 27 23 30 30 37 30 43 30 27 7d 29 0a  r': '#0070C0'}).
1380: 20 20 20 20 74 6f 74 61 6c 5f 73 74 79 6c 65 20      total_style 
1390: 3d 20 77 62 2e 61 64 64 5f 66 6f 72 6d 61 74 28  = wb.add_format(
13a0: 7b 27 66 6f 6e 74 5f 6e 61 6d 65 27 3a 20 27 4d  {'font_name': 'M
13b0: 69 6c 6b 20 4d 75 73 74 61 63 68 65 20 42 42 27  ilk Mustache BB'
13c0: 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20 20 20  , .             
13d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
13e0: 20 20 20 20 27 66 6f 6e 74 5f 73 69 7a 65 27 3a      'font_size':
13f0: 20 31 34 2c 0a 20 20 20 20 20 20 20 20 20 20 20   14,.           
1400: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1410: 20 20 20 20 20 20 27 61 6c 69 67 6e 27 3a 20 27        'align': '
1420: 63 65 6e 74 65 72 27 2c 0a 20 20 20 20 20 20 20  center',.       
1430: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1440: 20 20 20 20 20 20 20 20 20 20 27 62 6f 6c 64 27            'bold'
1450: 3a 20 27 74 72 75 65 27 7d 29 0a 20 20 20 20 70  : 'true'}).    p
1460: 72 69 7a 65 6e 61 6d 65 5f 73 74 79 6c 65 20 3d  rizename_style =
1470: 20 77 62 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b   wb.add_format({
1480: 27 66 6f 6e 74 5f 6e 61 6d 65 27 3a 20 27 4d 69  'font_name': 'Mi
1490: 6c 6b 20 4d 75 73 74 61 63 68 65 20 42 42 27 2c  lk Mustache BB',
14a0: 20 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20   .              
14b0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
14c0: 20 20 20 27 66 6f 6e 74 5f 73 69 7a 65 27 3a 20     'font_size': 
14d0: 31 34 7d 29 0a 20 20 20 20 70 72 69 7a 65 77 69  14}).    prizewi
14e0: 6e 6e 65 72 5f 73 74 79 6c 65 20 3d 20 77 62 2e  nner_style = wb.
14f0: 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f 6e  add_format({'fon
1500: 74 5f 6e 61 6d 65 27 3a 20 27 42 61 63 6b 20 49  t_name': 'Back I
1510: 73 73 75 65 73 20 42 42 27 2c 20 0a 20 20 20 20  ssues BB', .    
1520: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1530: 20 20 20 20 20 20 20 20 20 20 20 20 20 27 66 6f               'fo
1540: 6e 74 5f 73 69 7a 65 27 3a 20 31 32 2c 0a 20 20  nt_size': 12,.  
1550: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1560: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27                 '
1570: 63 6f 6c 6f 72 27 3a 20 27 23 45 32 36 42 30 41  color': '#E26B0A
1580: 27 7d 29 0a 0a 20 20 20 20 73 74 79 6c 65 5b 27  '})..    style['
1590: 70 6c 61 79 65 72 5f 74 69 74 6c 65 27 5d 20 3d  player_title'] =
15a0: 20 77 62 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b   wb.add_format({
15b0: 27 66 6f 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61  'font_name': 'Ba
15c0: 63 6b 20 49 73 73 75 65 73 20 42 42 27 2c 20 0a  ck Issues BB', .
15d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15e0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15f0: 20 27 66 6f 6e 74 5f 73 69 7a 65 27 3a 20 32 38   'font_size': 28
1600: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1610: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1620: 20 20 20 27 62 6f 6c 64 27 3a 20 54 72 75 65 2c     'bold': True,
1630: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1640: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1650: 20 20 27 63 6f 6c 6f 72 27 3a 20 27 23 30 30 39    'color': '#009
1660: 36 46 46 27 7d 29 0a 20 20 20 20 73 74 79 6c 65  6FF'}).    style
1670: 5b 27 70 6c 61 79 65 72 5f 73 75 62 74 69 74 6c  ['player_subtitl
1680: 65 27 5d 20 3d 20 77 62 2e 61 64 64 5f 66 6f 72  e'] = wb.add_for
1690: 6d 61 74 28 7b 27 66 6f 6e 74 5f 6e 61 6d 65 27  mat({'font_name'
16a0: 3a 20 27 42 61 63 6b 20 49 73 73 75 65 73 20 42  : 'Back Issues B
16b0: 42 27 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20  B', .           
16c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
16d0: 20 20 20 20 20 20 27 66 6f 6e 74 5f 73 69 7a 65        'font_size
16e0: 27 3a 20 31 36 7d 29 0a 20 20 20 20 73 74 79 6c  ': 16}).    styl
16f0: 65 5b 27 73 63 6f 72 65 5f 63 6f 6c 5f 68 65 61  e['score_col_hea
1700: 64 27 5d 20 3d 20 77 62 2e 61 64 64 5f 66 6f 72  d'] = wb.add_for
1710: 6d 61 74 28 7b 27 66 6f 6e 74 5f 6e 61 6d 65 27  mat({'font_name'
1720: 3a 20 27 42 61 63 6b 20 49 73 73 75 65 73 20 42  : 'Back Issues B
1730: 42 27 2c 20 0a 20 20 20 20 20 20 20 20 20 20 20  B', .           
1740: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1750: 20 20 20 20 20 20 27 66 6f 6e 74 5f 73 69 7a 65        'font_size
1760: 27 3a 20 31 32 2c 0a 20 20 20 20 20 20 20 20 20  ': 12,.         
1770: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1780: 20 20 20 20 20 20 20 20 27 62 6f 6c 64 27 3a 20          'bold': 
1790: 27 74 72 75 65 27 2c 0a 20 20 20 20 20 20 20 20  'true',.        
17a0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
17b0: 20 20 20 20 20 20 20 20 20 27 61 6c 69 67 6e 27           'align'
17c0: 3a 20 27 63 65 6e 74 65 72 27 7d 29 0a 20 20 20  : 'center'}).   
17d0: 20 73 74 79 6c 65 5b 27 73 63 6f 72 65 5f 72 6f   style['score_ro
17e0: 77 5f 68 65 61 64 27 5d 20 3d 20 77 62 2e 61 64  w_head'] = wb.ad
17f0: 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f 6e 74 5f  d_format({'font_
1800: 6e 61 6d 65 27 3a 20 27 42 61 63 6b 20 49 73 73  name': 'Back Iss
1810: 75 65 73 20 42 42 27 2c 20 0a 20 20 20 20 20 20  ues BB', .      
1820: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1830: 20 20 20 20 20 20 20 20 20 20 20 27 66 6f 6e 74             'font
1840: 5f 73 69 7a 65 27 3a 20 31 36 2c 0a 20 20 20 20  _size': 16,.    
1850: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1860: 20 20 20 20 20 20 20 20 20 20 20 20 20 27 62 6f               'bo
1870: 6c 64 27 3a 20 27 74 72 75 65 27 2c 0a 20 20 20  ld': 'true',.   
1880: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1890: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27 61                'a
18a0: 6c 69 67 6e 27 3a 20 27 63 65 6e 74 65 72 27 7d  lign': 'center'}
18b0: 29 0a 20 20 20 20 73 74 79 6c 65 5b 27 73 63 6f  ).    style['sco
18c0: 72 65 5f 6e 75 6d 27 5d 20 3d 20 77 62 2e 61 64  re_num'] = wb.ad
18d0: 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f 6e 74 5f  d_format({'font_
18e0: 6e 61 6d 65 27 3a 20 27 4d 69 6c 6b 20 4d 75 73  name': 'Milk Mus
18f0: 74 61 63 68 65 20 42 42 27 2c 20 0a 20 20 20 20  tache BB', .    
1900: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1910: 20 20 20 20 20 20 20 20 20 20 20 20 20 27 66 6f               'fo
1920: 6e 74 5f 73 69 7a 65 27 3a 20 31 38 2c 0a 20 20  nt_size': 18,.  
1930: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1940: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27                 '
1950: 61 6c 69 67 6e 27 3a 20 27 72 69 67 68 74 27 2c  align': 'right',
1960: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1970: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1980: 20 20 27 6e 75 6d 5f 66 6f 72 6d 61 74 27 3a 20    'num_format': 
1990: 27 5f 28 2a 20 23 2c 23 23 30 5f 29 3b 5f 28 2a  '_(* #,##0_);_(*
19a0: 20 28 23 2c 23 23 30 29 3b 5f 28 2a 20 22 2d 22   (#,##0);_(* "-"
19b0: 3f 3f 5f 29 3b 5f 28 40 5f 29 27 2c 0a 20 20 20  ??_);_(@_)',.   
19c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
19d0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27 63                'c
19e0: 6f 6c 6f 72 27 3a 20 27 23 38 33 33 43 30 43 27  olor': '#833C0C'
19f0: 7d 29 0a 20 20 20 20 73 74 79 6c 65 5b 27 73 63  }).    style['sc
1a00: 6f 72 65 5f 74 6f 74 61 6c 27 5d 20 3d 20 77 62  ore_total'] = wb
1a10: 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f  .add_format({'fo
1a20: 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61 63 6b 20  nt_name': 'Back 
1a30: 49 73 73 75 65 73 20 42 42 27 2c 20 0a 20 20 20  Issues BB', .   
1a40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1a50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27 66                'f
1a60: 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 38 2c 0a 20  ont_size': 18,. 
1a70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1a80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1a90: 27 61 6c 69 67 6e 27 3a 20 27 72 69 67 68 74 27  'align': 'right'
1aa0: 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ,.              
1ab0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ac0: 20 20 20 27 74 6f 70 27 3a 20 31 2c 0a 20 20 20     'top': 1,.   
1ad0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27 6e                'n
1af0: 75 6d 5f 66 6f 72 6d 61 74 27 3a 20 27 5f 28 2a  um_format': '_(*
1b00: 20 23 2c 23 23 30 5f 29 3b 5f 28 2a 20 28 23 2c   #,##0_);_(* (#,
1b10: 23 23 30 29 3b 5f 28 2a 20 22 2d 22 3f 3f 5f 29  ##0);_(* "-"??_)
1b20: 3b 5f 28 40 5f 29 27 7d 29 0a 20 20 20 20 73 74  ;_(@_)'}).    st
1b30: 79 6c 65 5b 27 77 69 6e 73 27 5d 20 3d 20 77 62  yle['wins'] = wb
1b40: 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f  .add_format({'fo
1b50: 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61 63 6b 20  nt_name': 'Back 
1b60: 49 73 73 75 65 73 20 42 42 27 2c 20 0a 20 20 20  Issues BB', .   
1b70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1b80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27 66                'f
1b90: 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 38 2c 0a 20  ont_size': 18,. 
1ba0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bc0: 27 63 6f 6c 6f 72 27 3a 20 27 23 35 34 38 32 33  'color': '#54823
1bd0: 35 27 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  5',.            
1be0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1bf0: 20 20 20 20 20 27 61 6c 69 67 6e 27 3a 20 27 63       'align': 'c
1c00: 65 6e 74 65 72 27 7d 29 0a 20 20 20 20 73 74 79  enter'}).    sty
1c10: 6c 65 5b 27 6c 6f 73 73 65 73 27 5d 20 3d 20 77  le['losses'] = w
1c20: 62 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27 66  b.add_format({'f
1c30: 6f 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61 63 6b  ont_name': 'Back
1c40: 20 49 73 73 75 65 73 20 42 42 27 2c 20 0a 20 20   Issues BB', .  
1c50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27                 '
1c70: 66 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 38 2c 0a  font_size': 18,.
1c80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1c90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ca0: 20 27 63 6f 6c 6f 72 27 3a 20 27 23 46 46 30 30   'color': '#FF00
1cb0: 30 30 27 2c 0a 20 20 20 20 20 20 20 20 20 20 20  00',.           
1cc0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1cd0: 20 20 20 20 20 20 27 61 6c 69 67 6e 27 3a 20 27        'align': '
1ce0: 63 65 6e 74 65 72 27 7d 29 0a 20 20 20 20 73 74  center'}).    st
1cf0: 79 6c 65 5b 27 77 69 6e 73 5f 74 27 5d 20 3d 20  yle['wins_t'] = 
1d00: 77 62 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27  wb.add_format({'
1d10: 66 6f 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61 63  font_name': 'Bac
1d20: 6b 20 49 73 73 75 65 73 20 42 42 27 2c 20 0a 20  k Issues BB', . 
1d30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d50: 27 66 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 38 2c  'font_size': 18,
1d60: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1d70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d80: 20 20 27 63 6f 6c 6f 72 27 3a 20 27 23 35 34 38    'color': '#548
1d90: 32 33 35 27 2c 0a 20 20 20 20 20 20 20 20 20 20  235',.          
1da0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1db0: 20 20 20 20 20 20 20 27 74 6f 70 27 3a 20 31 2c         'top': 1,
1dc0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1dd0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1de0: 20 20 27 61 6c 69 67 6e 27 3a 20 27 63 65 6e 74    'align': 'cent
1df0: 65 72 27 7d 29 0a 20 20 20 20 73 74 79 6c 65 5b  er'}).    style[
1e00: 27 6c 6f 73 73 65 73 5f 74 27 5d 20 3d 20 77 62  'losses_t'] = wb
1e10: 2e 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f  .add_format({'fo
1e20: 6e 74 5f 6e 61 6d 65 27 3a 20 27 42 61 63 6b 20  nt_name': 'Back 
1e30: 49 73 73 75 65 73 20 42 42 27 2c 20 0a 20 20 20  Issues BB', .   
1e40: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27 66                'f
1e60: 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 38 2c 0a 20  ont_size': 18,. 
1e70: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1e90: 27 63 6f 6c 6f 72 27 3a 20 27 23 46 46 30 30 30  'color': '#FF000
1ea0: 30 27 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  0',.            
1eb0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ec0: 20 20 20 20 20 27 74 6f 70 27 3a 20 31 2c 0a 20       'top': 1,. 
1ed0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ee0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1ef0: 27 61 6c 69 67 6e 27 3a 20 27 63 65 6e 74 65 72  'align': 'center
1f00: 27 7d 29 0a 20 20 20 20 73 74 79 6c 65 5b 27 73  '}).    style['s
1f10: 74 61 74 5f 6e 61 6d 65 27 5d 20 3d 20 77 62 2e  tat_name'] = wb.
1f20: 61 64 64 5f 66 6f 72 6d 61 74 28 7b 27 66 6f 6e  add_format({'fon
1f30: 74 5f 6e 61 6d 65 27 3a 20 27 4d 69 6c 6b 20 4d  t_name': 'Milk M
1f40: 75 73 74 61 63 68 65 20 42 42 27 2c 20 0a 20 20  ustache BB', .  
1f50: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f60: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 27                 '
1f70: 62 6f 6c 64 27 3a 20 27 74 72 75 65 27 2c 0a 20  bold': 'true',. 
1f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1f90: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1fa0: 27 66 6f 6e 74 5f 73 69 7a 65 27 3a 20 31 36 7d  'font_size': 16}
1fb0: 29 0a 20 20 20 20 73 74 79 6c 65 5b 27 73 74 61  ).    style['sta
1fc0: 74 5f 76 61 6c 27 5d 20 3d 20 77 62 2e 61 64 64  t_val'] = wb.add
1fd0: 5f 66 6f 72 6d 61 74 28 7b 27 66 6f 6e 74 5f 6e  _format({'font_n
1fe0: 61 6d 65 27 3a 20 27 42 61 63 6b 20 49 73 73 75  ame': 'Back Issu
1ff0: 65 73 20 42 42 27 2c 20 0a 20 20 20 20 20 20 20  es BB', .       
2000: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2010: 20 20 20 20 20 20 20 20 20 20 27 66 6f 6e 74 5f            'font_
2020: 73 69 7a 65 27 3a 20 31 38 2c 0a 20 20 20 20 20  size': 18,.     
2030: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
2040: 20 20 20 20 20 20 20 20 20 20 20 20 27 61 6c 69              'ali
2050: 67 6e 27 3a 20 27 72 69 67 68 74 27 7d 29 0a 20  gn': 'right'}). 
2060: 20 20 20 0a 20 20 20 20 77 73 2e 73 65 74 5f 63     .    ws.set_c
2070: 6f 6c 75 6d 6e 28 27 41 3a 41 27 2c 20 33 30 29  olumn('A:A', 30)
2080: 0a 20 20 20 20 0a 20 20 20 20 77 73 2e 77 72 69  .    .    ws.wri
2090: 74 65 28 27 41 31 27 2c 20 74 69 74 6c 65 2c 20  te('A1', title, 
20a0: 74 69 74 6c 65 5f 73 74 79 6c 65 29 0a 20 20 20  title_style).   
20b0: 20 77 73 2e 73 65 74 5f 6c 61 6e 64 73 63 61 70   ws.set_landscap
20c0: 65 28 29 0a 20 20 20 20 77 73 2e 66 69 74 5f 74  e().    ws.fit_t
20d0: 6f 5f 70 61 67 65 73 28 31 2c 20 31 29 0a 0a 20  o_pages(1, 1).. 
20e0: 20 20 20 23 20 43 6f 6c 75 6d 6e 20 68 65 61 64     # Column head
20f0: 69 6e 67 73 20 66 6f 72 20 65 61 63 68 20 72 6f  ings for each ro
2100: 75 6e 64 0a 20 20 20 20 66 6f 72 20 6e 20 69 6e  und.    for n in
2110: 20 72 61 6e 67 65 28 67 2e 63 75 72 72 65 6e 74   range(g.current
2120: 5f 72 6f 75 6e 64 28 29 29 3a 0a 20 20 20 20 20  _round()):.     
2130: 20 20 20 77 73 2e 77 72 69 74 65 28 32 2c 20 6e     ws.write(2, n
2140: 20 2b 20 31 2c 20 6e 20 2b 20 31 2c 20 63 6f 6c   + 1, n + 1, col
2150: 5f 68 65 61 64 69 6e 67 29 0a 20 20 20 20 0a 20  _heading).    . 
2160: 20 20 20 65 6e 64 5f 63 6f 6c 20 3d 20 67 2e 63     end_col = g.c
2170: 75 72 72 65 6e 74 5f 72 6f 75 6e 64 28 29 0a 20  urrent_round(). 
2180: 20 20 20 77 73 2e 73 65 74 5f 63 6f 6c 75 6d 6e     ws.set_column
2190: 28 31 2c 20 65 6e 64 5f 63 6f 6c 2c 20 35 29 0a  (1, end_col, 5).
21a0: 20 20 20 20 77 73 2e 73 65 74 5f 63 6f 6c 75 6d      ws.set_colum
21b0: 6e 28 65 6e 64 5f 63 6f 6c 20 2b 20 31 2c 20 65  n(end_col + 1, e
21c0: 6e 64 5f 63 6f 6c 20 2b 20 35 2c 20 31 30 29 0a  nd_col + 5, 10).
21d0: 0a 20 20 20 20 77 73 2e 77 72 69 74 65 28 32 2c  .    ws.write(2,
21e0: 20 65 6e 64 5f 63 6f 6c 20 2b 20 31 2c 20 22 54   end_col + 1, "T
21f0: 6f 74 61 6c 22 2c 20 63 6f 6c 5f 68 65 61 64 69  otal", col_headi
2200: 6e 67 29 0a 20 20 20 20 77 73 2e 77 72 69 74 65  ng).    ws.write
2210: 28 32 2c 20 65 6e 64 5f 63 6f 6c 20 2b 20 32 2c  (2, end_col + 2,
2220: 20 22 57 69 6e 73 22 2c 20 63 6f 6c 5f 68 65 61   "Wins", col_hea
2230: 64 69 6e 67 29 0a 20 20 20 20 77 73 2e 77 72 69  ding).    ws.wri
2240: 74 65 28 32 2c 20 65 6e 64 5f 63 6f 6c 20 2b 20  te(2, end_col + 
2250: 33 2c 20 22 4c 6f 73 73 65 73 22 2c 20 63 6f 6c  3, "Losses", col
2260: 5f 68 65 61 64 69 6e 67 29 0a 20 20 20 20 77 73  _heading).    ws
2270: 2e 77 72 69 74 65 28 32 2c 20 65 6e 64 5f 63 6f  .write(2, end_co
2280: 6c 20 2b 20 34 2c 20 22 42 75 6e 63 6f 73 22 2c  l + 4, "Buncos",
2290: 20 63 6f 6c 5f 68 65 61 64 69 6e 67 29 0a 20 20   col_heading).  
22a0: 20 20 77 73 2e 77 72 69 74 65 28 32 2c 20 65 6e    ws.write(2, en
22b0: 64 5f 63 6f 6c 20 2b 20 35 2c 20 22 52 6f 6c 6c  d_col + 5, "Roll
22c0: 73 22 2c 20 63 6f 6c 5f 68 65 61 64 69 6e 67 29  s", col_heading)
22d0: 0a 0a 20 20 20 20 23 20 57 72 69 74 65 20 70 6c  ..    # Write pl
22e0: 61 79 65 72 73 20 61 6e 64 20 74 68 65 69 72 20  ayers and their 
22f0: 73 63 6f 72 65 73 20 66 6f 72 20 65 61 63 68 20  scores for each 
2300: 72 6f 75 6e 64 0a 20 20 20 20 66 6f 72 20 6e 2c  round.    for n,
2310: 20 70 6c 61 79 65 72 20 69 6e 20 65 6e 75 6d 65   player in enume
2320: 72 61 74 65 28 67 2e 70 6c 61 79 65 72 73 29 3a  rate(g.players):
2330: 0a 20 20 20 20 20 20 20 20 72 6f 77 20 3d 20 6e  .        row = n
2340: 20 2b 20 33 0a 20 20 20 20 20 20 20 20 77 73 2e   + 3.        ws.
2350: 77 72 69 74 65 28 72 6f 77 2c 20 30 2c 20 70 6c  write(row, 0, pl
2360: 61 79 65 72 2e 6e 61 6d 65 2c 20 72 6f 77 5f 68  ayer.name, row_h
2370: 65 61 64 69 6e 67 29 0a 0a 20 20 20 20 20 20 20  eading)..       
2380: 20 66 6f 72 20 72 20 69 6e 20 72 61 6e 67 65 28   for r in range(
2390: 67 2e 63 75 72 72 65 6e 74 5f 72 6f 75 6e 64 28  g.current_round(
23a0: 29 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  )):.            
23b0: 63 6f 6c 20 3d 20 72 20 2b 20 31 0a 20 20 20 20  col = r + 1.    
23c0: 20 20 20 20 20 20 20 20 77 73 2e 77 72 69 74 65          ws.write
23d0: 28 72 6f 77 2c 20 63 6f 6c 2c 20 70 6c 61 79 65  (row, col, playe
23e0: 72 2e 72 6f 75 6e 64 5f 73 63 6f 72 65 73 5b 72  r.round_scores[r
23f0: 5d 2c 20 73 63 6f 72 65 5f 73 74 79 6c 65 29 0a  ], score_style).
2400: 20 20 20 20 20 20 20 20 0a 20 20 20 20 20 20 20          .       
2410: 20 23 20 64 65 72 69 76 65 20 6c 6f 73 73 65 73   # derive losses
2420: 20 66 72 6f 6d 20 77 69 6e 73 0a 20 20 20 20 20   from wins.     
2430: 20 20 20 6c 6f 73 73 65 73 20 3d 20 5b 69 6e 74     losses = [int
2440: 28 6e 6f 74 20 78 29 20 66 6f 72 20 78 20 69 6e  (not x) for x in
2450: 20 70 6c 61 79 65 72 2e 72 6f 75 6e 64 5f 77 69   player.round_wi
2460: 6e 73 5d 0a 0a 20 20 20 20 20 20 20 20 77 73 2e  ns]..        ws.
2470: 77 72 69 74 65 28 72 6f 77 2c 20 65 6e 64 5f 63  write(row, end_c
2480: 6f 6c 20 2b 20 31 2c 20 73 75 6d 28 70 6c 61 79  ol + 1, sum(play
2490: 65 72 2e 72 6f 75 6e 64 5f 73 63 6f 72 65 73 29  er.round_scores)
24a0: 2c 20 74 6f 74 61 6c 5f 73 74 79 6c 65 29 0a 20  , total_style). 
24b0: 20 20 20 20 20 20 20 77 73 2e 77 72 69 74 65 28         ws.write(
24c0: 72 6f 77 2c 20 65 6e 64 5f 63 6f 6c 20 2b 20 32  row, end_col + 2
24d0: 2c 20 73 75 6d 28 70 6c 61 79 65 72 2e 72 6f 75  , sum(player.rou
24e0: 6e 64 5f 77 69 6e 73 29 2c 20 74 6f 74 61 6c 5f  nd_wins), total_
24f0: 73 74 79 6c 65 29 0a 20 20 20 20 20 20 20 20 77  style).        w
2500: 73 2e 77 72 69 74 65 28 72 6f 77 2c 20 65 6e 64  s.write(row, end
2510: 5f 63 6f 6c 20 2b 20 33 2c 20 73 75 6d 28 6c 6f  _col + 3, sum(lo
2520: 73 73 65 73 29 2c 20 74 6f 74 61 6c 5f 73 74 79  sses), total_sty
2530: 6c 65 29 0a 20 20 20 20 20 20 20 20 77 73 2e 77  le).        ws.w
2540: 72 69 74 65 28 72 6f 77 2c 20 65 6e 64 5f 63 6f  rite(row, end_co
2550: 6c 20 2b 20 34 2c 20 73 75 6d 28 70 6c 61 79 65  l + 4, sum(playe
2560: 72 2e 72 6f 75 6e 64 5f 62 75 6e 63 6f 5f 63 6f  r.round_bunco_co
2570: 75 6e 74 73 29 2c 20 74 6f 74 61 6c 5f 73 74 79  unts), total_sty
2580: 6c 65 29 0a 20 20 20 20 20 20 20 20 77 73 2e 77  le).        ws.w
2590: 72 69 74 65 28 72 6f 77 2c 20 65 6e 64 5f 63 6f  rite(row, end_co
25a0: 6c 20 2b 20 35 2c 20 73 75 6d 28 70 6c 61 79 65  l + 5, sum(playe
25b0: 72 2e 72 6f 75 6e 64 5f 72 6f 6c 6c 5f 63 6f 75  r.round_roll_cou
25c0: 6e 74 73 29 2c 20 74 6f 74 61 6c 5f 73 74 79 6c  nts), total_styl
25d0: 65 29 0a 0a 20 20 20 20 20 20 20 20 65 78 63 65  e)..        exce
25e0: 6c 5f 73 63 6f 72 65 5f 73 68 65 65 74 28 77 62  l_score_sheet(wb
25f0: 2c 20 73 74 79 6c 65 2c 20 70 6c 61 79 65 72 2c  , style, player,
2600: 20 74 69 74 6c 65 29 0a 0a 20 20 20 20 65 6e 64   title)..    end
2610: 5f 72 6f 77 20 3d 20 33 20 2b 20 6c 65 6e 28 67  _row = 3 + len(g
2620: 2e 70 6c 61 79 65 72 73 29 0a 20 20 20 20 77 73  .players).    ws
2630: 2e 77 72 69 74 65 28 65 6e 64 5f 72 6f 77 20 2b  .write(end_row +
2640: 20 31 2c 20 30 2c 20 22 50 72 69 7a 65 73 22 2c   1, 0, "Prizes",
2650: 20 74 69 74 6c 65 5f 73 74 79 6c 65 29 0a 20 20   title_style).  
2660: 20 20 70 72 69 7a 65 6c 69 73 74 20 3d 20 67 2e    prizelist = g.
2670: 70 72 69 7a 65 73 28 29 0a 0a 20 20 20 20 66 6f  prizes()..    fo
2680: 72 20 6e 2c 20 28 70 72 69 7a 65 6e 61 6d 65 2c  r n, (prizename,
2690: 20 77 69 6e 6e 65 72 73 29 20 69 6e 20 65 6e 75   winners) in enu
26a0: 6d 65 72 61 74 65 28 70 72 69 7a 65 6c 69 73 74  merate(prizelist
26b0: 2e 69 74 65 6d 73 28 29 29 3a 0a 20 20 20 20 20  .items()):.     
26c0: 20 20 20 77 73 2e 77 72 69 74 65 28 65 6e 64 5f     ws.write(end_
26d0: 72 6f 77 20 2b 20 32 20 2b 20 6e 2c 20 30 2c 20  row + 2 + n, 0, 
26e0: 70 72 69 7a 65 6e 61 6d 65 2c 20 70 72 69 7a 65  prizename, prize
26f0: 6e 61 6d 65 5f 73 74 79 6c 65 29 0a 20 20 20 20  name_style).    
2700: 20 20 20 20 77 73 2e 77 72 69 74 65 28 65 6e 64      ws.write(end
2710: 5f 72 6f 77 20 2b 20 32 20 2b 20 6e 2c 20 31 2c  _row + 2 + n, 1,
2720: 20 77 69 6e 6e 65 72 73 2c 20 70 72 69 7a 65 77   winners, prizew
2730: 69 6e 6e 65 72 5f 73 74 79 6c 65 29 0a 20 20 20  inner_style).   
2740: 20 77 62 2e 63 6c 6f 73 65 28 29 0a 0a 64 65 66   wb.close()..def
2750: 20 65 78 63 65 6c 5f 73 63 6f 72 65 5f 73 68 65   excel_score_she
2760: 65 74 28 77 6f 72 6b 62 6f 6f 6b 2c 20 73 74 79  et(workbook, sty
2770: 6c 65 73 2c 20 70 6c 61 79 65 72 2c 20 74 69 74  les, player, tit
2780: 6c 65 29 3a 0a 20 20 20 20 77 73 20 3d 20 77 6f  le):.    ws = wo
2790: 72 6b 62 6f 6f 6b 2e 61 64 64 5f 77 6f 72 6b 73  rkbook.add_works
27a0: 68 65 65 74 28 70 6c 61 79 65 72 2e 6e 61 6d 65  heet(player.name
27b0: 29 0a 0a 20 20 20 20 77 73 2e 73 65 74 5f 63 6f  )..    ws.set_co
27c0: 6c 75 6d 6e 28 27 41 3a 41 27 2c 20 31 34 29 0a  lumn('A:A', 14).
27d0: 20 20 20 20 77 73 2e 73 65 74 5f 63 6f 6c 75 6d      ws.set_colum
27e0: 6e 28 27 42 3a 43 27 2c 20 31 33 29 0a 20 20 20  n('B:C', 13).   
27f0: 20 77 73 2e 73 65 74 5f 63 6f 6c 75 6d 6e 28 27   ws.set_column('
2800: 44 3a 44 27 2c 20 31 39 29 0a 20 20 20 20 77 73  D:D', 19).    ws
2810: 2e 73 65 74 5f 63 6f 6c 75 6d 6e 28 27 45 3a 46  .set_column('E:F
2820: 27 2c 20 31 32 29 0a 20 20 20 20 77 73 2e 73 65  ', 12).    ws.se
2830: 74 5f 70 6f 72 74 72 61 69 74 28 29 0a 20 20 20  t_portrait().   
2840: 20 77 73 2e 66 69 74 5f 74 6f 5f 70 61 67 65 73   ws.fit_to_pages
2850: 28 31 2c 20 31 29 0a 0a 20 20 20 20 77 73 2e 77  (1, 1)..    ws.w
2860: 72 69 74 65 28 27 41 31 27 2c 20 70 6c 61 79 65  rite('A1', playe
2870: 72 2e 6e 61 6d 65 2c 20 73 74 79 6c 65 73 5b 27  r.name, styles['
2880: 70 6c 61 79 65 72 5f 74 69 74 6c 65 27 5d 29 0a  player_title']).
2890: 20 20 20 20 77 73 2e 77 72 69 74 65 28 27 41 32      ws.write('A2
28a0: 27 2c 20 66 22 7b 74 69 74 6c 65 7d 20 53 63 6f  ', f"{title} Sco
28b0: 72 65 20 53 68 65 65 74 22 2c 20 73 74 79 6c 65  re Sheet", style
28c0: 73 5b 27 70 6c 61 79 65 72 5f 73 75 62 74 69 74  s['player_subtit
28d0: 6c 65 27 5d 29 0a 20 20 20 20 0a 20 20 20 20 63  le']).    .    c
28e0: 6f 6c 73 20 3d 20 5b 27 52 6f 75 6e 64 27 2c 20  ols = ['Round', 
28f0: 27 52 6f 6c 6c 73 27 2c 20 27 42 75 6e 63 6f 73  'Rolls', 'Buncos
2900: 3f 27 2c 20 27 54 65 61 6d 20 53 63 6f 72 65 27  ?', 'Team Score'
2910: 2c 20 27 57 69 6e 27 2c 20 27 4c 6f 73 73 27 5d  , 'Win', 'Loss']
2920: 0a 20 20 20 20 66 6f 72 20 6e 2c 20 63 6f 6c 20  .    for n, col 
2930: 69 6e 20 65 6e 75 6d 65 72 61 74 65 28 63 6f 6c  in enumerate(col
2940: 73 29 3a 0a 20 20 20 20 20 20 20 20 77 73 2e 77  s):.        ws.w
2950: 72 69 74 65 28 33 2c 20 6e 2c 20 63 6f 6c 2c 20  rite(3, n, col, 
2960: 73 74 79 6c 65 73 5b 27 73 63 6f 72 65 5f 63 6f  styles['score_co
2970: 6c 5f 68 65 61 64 27 5d 29 0a 0a 20 20 20 20 66  l_head'])..    f
2980: 6f 72 20 6e 20 69 6e 20 72 61 6e 67 65 28 67 2e  or n in range(g.
2990: 63 75 72 72 65 6e 74 5f 72 6f 75 6e 64 28 29 29  current_round())
29a0: 3a 0a 20 20 20 20 20 20 20 20 72 6f 77 20 3d 20  :.        row = 
29b0: 34 20 2b 20 6e 0a 20 20 20 20 20 20 20 20 77 73  4 + n.        ws
29c0: 2e 77 72 69 74 65 28 72 6f 77 2c 20 30 2c 20 6e  .write(row, 0, n
29d0: 20 2b 20 31 2c 20 73 74 79 6c 65 73 5b 27 73 63   + 1, styles['sc
29e0: 6f 72 65 5f 63 6f 6c 5f 68 65 61 64 27 5d 29 0a  ore_col_head']).
29f0: 20 20 20 20 20 20 20 20 77 73 2e 77 72 69 74 65          ws.write
2a00: 28 72 6f 77 2c 20 31 2c 20 70 6c 61 79 65 72 2e  (row, 1, player.
2a10: 72 6f 75 6e 64 5f 72 6f 6c 6c 5f 63 6f 75 6e 74  round_roll_count
2a20: 73 5b 6e 5d 2c 20 73 74 79 6c 65 73 5b 27 73 63  s[n], styles['sc
2a30: 6f 72 65 5f 6e 75 6d 27 5d 29 0a 20 20 20 20 20  ore_num']).     
2a40: 20 20 20 77 73 2e 77 72 69 74 65 28 72 6f 77 2c     ws.write(row,
2a50: 20 33 2c 20 70 6c 61 79 65 72 2e 72 6f 75 6e 64   3, player.round
2a60: 5f 73 63 6f 72 65 73 5b 6e 5d 2c 20 73 74 79 6c  _scores[n], styl
2a70: 65 73 5b 27 73 63 6f 72 65 5f 6e 75 6d 27 5d 29  es['score_num'])
2a80: 0a 0a 20 20 20 20 20 20 20 20 69 66 20 70 6c 61  ..        if pla
2a90: 79 65 72 2e 72 6f 75 6e 64 5f 62 75 6e 63 6f 5f  yer.round_bunco_
2aa0: 63 6f 75 6e 74 73 5b 6e 5d 20 3e 20 30 3a 0a 20  counts[n] > 0:. 
2ab0: 20 20 20 20 20 20 20 20 20 20 20 77 73 2e 77 72             ws.wr
2ac0: 69 74 65 28 72 6f 77 2c 20 32 2c 20 70 6c 61 79  ite(row, 2, play
2ad0: 65 72 2e 72 6f 75 6e 64 5f 62 75 6e 63 6f 5f 63  er.round_bunco_c
2ae0: 6f 75 6e 74 73 5b 6e 5d 2c 20 73 74 79 6c 65 73  ounts[n], styles
2af0: 5b 27 73 63 6f 72 65 5f 6e 75 6d 27 5d 29 0a 20  ['score_num']). 
2b00: 20 20 20 20 20 20 20 69 66 20 70 6c 61 79 65 72         if player
2b10: 2e 72 6f 75 6e 64 5f 77 69 6e 73 5b 6e 5d 20 3e  .round_wins[n] >
2b20: 20 30 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20   0:.            
2b30: 77 73 2e 77 72 69 74 65 28 72 6f 77 2c 20 34 2c  ws.write(row, 4,
2b40: 20 22 e2 9c 93 22 2c 20 73 74 79 6c 65 73 5b 27   "...", styles['
2b50: 77 69 6e 73 27 5d 29 0a 20 20 20 20 20 20 20 20  wins']).        
2b60: 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20 20 20  else:.          
2b70: 20 20 77 73 2e 77 72 69 74 65 28 72 6f 77 2c 20    ws.write(row, 
2b80: 35 2c 20 22 e2 9c 93 22 2c 20 73 74 79 6c 65 73  5, "...", styles
2b90: 5b 27 6c 6f 73 73 65 73 27 5d 29 0a 0a 20 20 20  ['losses'])..   
2ba0: 20 65 6e 64 5f 72 6f 77 20 3d 20 33 20 2b 20 67   end_row = 3 + g
2bb0: 2e 63 75 72 72 65 6e 74 5f 72 6f 75 6e 64 28 29  .current_round()
2bc0: 0a 0a 20 20 20 20 23 20 64 65 72 69 76 65 20 6c  ..    # derive l
2bd0: 6f 73 73 65 73 20 66 72 6f 6d 20 77 69 6e 73 0a  osses from wins.
2be0: 20 20 20 20 6c 6f 73 73 65 73 20 3d 20 5b 69 6e      losses = [in
2bf0: 74 28 6e 6f 74 20 78 29 20 66 6f 72 20 78 20 69  t(not x) for x i
2c00: 6e 20 70 6c 61 79 65 72 2e 72 6f 75 6e 64 5f 77  n player.round_w
2c10: 69 6e 73 5d 0a 20 20 20 20 77 73 2e 77 72 69 74  ins].    ws.writ
2c20: 65 28 65 6e 64 5f 72 6f 77 20 2b 20 31 2c 20 30  e(end_row + 1, 0
2c30: 2c 20 27 27 2c 20 73 74 79 6c 65 73 5b 27 73 63  , '', styles['sc
2c40: 6f 72 65 5f 74 6f 74 61 6c 27 5d 29 0a 20 20 20  ore_total']).   
2c50: 20 77 73 2e 77 72 69 74 65 28 65 6e 64 5f 72 6f   ws.write(end_ro
2c60: 77 20 2b 20 31 2c 20 31 2c 20 73 75 6d 28 70 6c  w + 1, 1, sum(pl
2c70: 61 79 65 72 2e 72 6f 75 6e 64 5f 72 6f 6c 6c 5f  ayer.round_roll_
2c80: 63 6f 75 6e 74 73 29 2c 20 73 74 79 6c 65 73 5b  counts), styles[
2c90: 27 73 63 6f 72 65 5f 74 6f 74 61 6c 27 5d 29 0a  'score_total']).
2ca0: 20 20 20 20 77 73 2e 77 72 69 74 65 28 65 6e 64      ws.write(end
2cb0: 5f 72 6f 77 20 2b 20 31 2c 20 32 2c 20 73 75 6d  _row + 1, 2, sum
2cc0: 28 70 6c 61 79 65 72 2e 72 6f 75 6e 64 5f 62 75  (player.round_bu
2cd0: 6e 63 6f 5f 63 6f 75 6e 74 73 29 2c 20 73 74 79  nco_counts), sty
2ce0: 6c 65 73 5b 27 73 63 6f 72 65 5f 74 6f 74 61 6c  les['score_total
2cf0: 27 5d 29 0a 20 20 20 20 77 73 2e 77 72 69 74 65  ']).    ws.write
2d00: 28 65 6e 64 5f 72 6f 77 20 2b 20 31 2c 20 33 2c  (end_row + 1, 3,
2d10: 20 73 75 6d 28 70 6c 61 79 65 72 2e 72 6f 75 6e   sum(player.roun
2d20: 64 5f 73 63 6f 72 65 73 29 2c 20 73 74 79 6c 65  d_scores), style
2d30: 73 5b 27 73 63 6f 72 65 5f 74 6f 74 61 6c 27 5d  s['score_total']
2d40: 29 0a 20 20 20 20 77 73 2e 77 72 69 74 65 28 65  ).    ws.write(e
2d50: 6e 64 5f 72 6f 77 20 2b 20 31 2c 20 34 2c 20 73  nd_row + 1, 4, s
2d60: 75 6d 28 70 6c 61 79 65 72 2e 72 6f 75 6e 64 5f  um(player.round_
2d70: 77 69 6e 73 29 2c 20 73 74 79 6c 65 73 5b 27 77  wins), styles['w
2d80: 69 6e 73 5f 74 27 5d 29 0a 20 20 20 20 77 73 2e  ins_t']).    ws.
2d90: 77 72 69 74 65 28 65 6e 64 5f 72 6f 77 20 2b 20  write(end_row + 
2da0: 31 2c 20 35 2c 20 73 75 6d 28 6c 6f 73 73 65 73  1, 5, sum(losses
2db0: 29 2c 20 73 74 79 6c 65 73 5b 27 6c 6f 73 73 65  ), styles['losse
2dc0: 73 5f 74 27 5d 29 0a 0a 20 20 20 20 73 74 61 74  s_t'])..    stat
2dd0: 73 20 3d 20 5b 27 4c 6f 6e 67 65 73 74 20 74 69  s = ['Longest ti
2de0: 6d 65 20 77 69 74 68 20 66 75 7a 7a 79 20 64 69  me with fuzzy di
2df0: 65 27 2c 0a 20 20 20 20 20 20 20 20 20 20 20 20  e',.            
2e00: 20 27 48 69 67 68 65 73 74 20 72 6f 6c 6c 20 73   'Highest roll s
2e10: 74 72 65 61 6b 27 2c 0a 20 20 20 20 20 20 20 20  treak',.        
2e20: 20 20 20 20 20 66 22 44 69 66 66 65 72 65 6e 63       f"Differenc
2e30: 65 20 66 72 6f 6d 20 61 76 65 72 61 67 65 20 73  e from average s
2e40: 63 6f 72 65 20 6f 66 20 7b 67 2e 61 76 65 72 61  core of {g.avera
2e50: 67 65 5f 74 6f 74 61 6c 5f 73 63 6f 72 65 28 29  ge_total_score()
2e60: 3a 2e 32 66 7d 22 2c 0a 20 20 20 20 20 20 20 20  :.2f}",.        
2e70: 20 20 20 20 20 66 22 44 69 66 66 65 72 65 6e 63       f"Differenc
2e80: 65 20 66 72 6f 6d 20 6d 65 64 69 61 6e 20 73 63  e from median sc
2e90: 6f 72 65 20 6f 66 20 7b 67 2e 6d 65 64 69 61 6e  ore of {g.median
2ea0: 5f 74 6f 74 61 6c 5f 73 63 6f 72 65 28 29 3a 2e  _total_score():.
2eb0: 32 66 7d 22 2c 0a 20 20 20 20 20 20 20 20 20 20  2f}",.          
2ec0: 20 20 20 22 41 76 65 72 61 67 65 20 25 20 6f 66     "Average % of
2ed0: 20 74 65 61 6d 20 73 63 6f 72 65 22 5d 0a 0a 20   team score"].. 
2ee0: 20 20 20 66 6f 72 20 6e 2c 20 73 74 61 74 20 69     for n, stat i
2ef0: 6e 20 65 6e 75 6d 65 72 61 74 65 28 73 74 61 74  n enumerate(stat
2f00: 73 29 3a 0a 20 20 20 20 20 20 20 20 77 73 2e 77  s):.        ws.w
2f10: 72 69 74 65 28 65 6e 64 5f 72 6f 77 20 2b 20 33  rite(end_row + 3
2f20: 20 2b 20 6e 2c 20 30 2c 20 73 74 61 74 2c 20 73   + n, 0, stat, s
2f30: 74 79 6c 65 73 5b 27 73 74 61 74 5f 6e 61 6d 65  tyles['stat_name
2f40: 27 5d 29 0a 20 20 20 20 0a 20 20 20 20 77 73 2e  ']).    .    ws.
2f50: 77 72 69 74 65 28 65 6e 64 5f 72 6f 77 20 2b 20  write(end_row + 
2f60: 33 2c 20 35 2c 20 66 22 7b 70 6c 61 79 65 72 2e  3, 5, f"{player.
2f70: 6d 61 78 5f 66 75 7a 7a 79 64 69 65 5f 73 74 72  max_fuzzydie_str
2f80: 65 61 6b 20 2f 2f 20 36 30 7d 3a 7b 70 6c 61 79  eak // 60}:{play
2f90: 65 72 2e 6d 61 78 5f 66 75 7a 7a 79 64 69 65 5f  er.max_fuzzydie_
2fa0: 73 74 72 65 61 6b 20 25 20 36 30 3a 30 32 7d 22  streak % 60:02}"
2fb0: 2c 0a 20 20 20 20 20 20 20 20 73 74 79 6c 65 73  ,.        styles
2fc0: 5b 27 73 74 61 74 5f 76 61 6c 27 5d 29 0a 20 20  ['stat_val']).  
2fd0: 20 20 77 73 2e 77 72 69 74 65 28 65 6e 64 5f 72    ws.write(end_r
2fe0: 6f 77 20 2b 20 34 2c 20 35 2c 20 70 6c 61 79 65  ow + 4, 5, playe
2ff0: 72 2e 6d 61 78 5f 73 74 72 65 61 6b 2c 20 73 74  r.max_streak, st
3000: 79 6c 65 73 5b 27 73 74 61 74 5f 76 61 6c 27 5d  yles['stat_val']
3010: 29 0a 20 20 20 20 77 73 2e 77 72 69 74 65 28 65  ).    ws.write(e
3020: 6e 64 5f 72 6f 77 20 2b 20 35 2c 20 35 2c 20 66  nd_row + 5, 5, f
3030: 22 7b 73 75 6d 28 70 6c 61 79 65 72 2e 72 6f 75  "{sum(player.rou
3040: 6e 64 5f 73 63 6f 72 65 73 29 20 2d 20 67 2e 61  nd_scores) - g.a
3050: 76 65 72 61 67 65 5f 74 6f 74 61 6c 5f 73 63 6f  verage_total_sco
3060: 72 65 28 29 3a 2e 32 66 7d 22 2c 20 73 74 79 6c  re():.2f}", styl
3070: 65 73 5b 27 73 74 61 74 5f 76 61 6c 27 5d 29 0a  es['stat_val']).
3080: 20 20 20 20 77 73 2e 77 72 69 74 65 28 65 6e 64      ws.write(end
3090: 5f 72 6f 77 20 2b 20 36 2c 20 35 2c 20 66 22 7b  _row + 6, 5, f"{
30a0: 73 75 6d 28 70 6c 61 79 65 72 2e 72 6f 75 6e 64  sum(player.round
30b0: 5f 73 63 6f 72 65 73 29 20 2d 20 67 2e 6d 65 64  _scores) - g.med
30c0: 69 61 6e 5f 74 6f 74 61 6c 5f 73 63 6f 72 65 28  ian_total_score(
30d0: 29 3a 2e 32 66 7d 22 2c 20 73 74 79 6c 65 73 5b  ):.2f}", styles[
30e0: 27 73 74 61 74 5f 76 61 6c 27 5d 29 0a 20 20 20  'stat_val']).   
30f0: 20 77 73 2e 77 72 69 74 65 28 65 6e 64 5f 72 6f   ws.write(end_ro
3100: 77 20 2b 20 37 2c 20 35 2c 20 66 22 7b 70 6c 61  w + 7, 5, f"{pla
3110: 79 65 72 2e 61 76 65 72 61 67 65 5f 63 6f 6e 74  yer.average_cont
3120: 72 69 62 5f 70 63 74 28 29 3a 2e 32 25 7d 22 2c  rib_pct():.2%}",
3130: 20 73 74 79 6c 65 73 5b 27 73 74 61 74 5f 76 61   styles['stat_va
3140: 6c 27 5d 29 0a                                   l']).