def main(): parser = ArgumentParser() parser.add_argument('--partreport', '-p', default=None, metavar='F', help='specify participant report file to use') parser.add_argument('--tbreport', '-t', default=None, metavar='F', help='specify trybooking report file to use') parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') args = parser.parse_args() config = load_config() teams = fetch_teams() fetch_participants(teams, args.partreport, args.verbose) tb = fetch_trybooking(config['tbmap'], args.tbreport, args.verbose) def match_names(fn1, fn2): if fn1.lower() == fn2.lower(): return True else: return False unpaid = [] paid = [] for t in teams.values(): for p in t.players: e = find_in_tb(tb, to_fullname(p['first name'], p['last name'])) if e is None: unpaid.append(p) else: paid.append(p) if paid: print('Paid: ({})'.format(len(paid))) for p in sorted( paid, key=lambda p: to_fullname(p['first name'], p['last name']) ): print(' {}'.format(to_fullname(p['first name'], p['last name']))) if unpaid: print('Unpaid: ({})'.format(len(unpaid))) for p in sorted( unpaid, key=lambda p: to_fullname(p['first name'], p['last name']) ): print(' {}'.format(to_fullname(p['first name'], p['last name']))) if tb['by-name']: print('Unknown: ({})'.format(len(tb['by-name']))) for fn, e in sorted(tb['by-name'].items(), key=lambda e: e[0]): print(' {}'.format(fn)) return 0
def main(): parser = ArgumentParser() parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') parser.add_argument('teams', nargs='*', help='limit checks to specified teams') args = parser.parse_args() teams = fetch_teams() if args.teams: newteams = {} for name in args.teams: if name not in teams: print('unknown team name: {}'.format(name), file=sys.stderr) sys.exit(1) newteams[name] = teams[name] teams = newteams for t in teams.values(): if args.verbose: print('{} [{}]:'.format(t.sname, t.edjba_id)) for label, attrs in descs: ident, name, dobstr, wwcnum, wwcname = map( lambda a: getattr(t, a), attrs ) dob = to_date(dobstr, '%Y-%m-%d %H:%M:%S.%f') res = wwc_check( WWCCheckPerson(ident, name, wwcnum, dob, wwcname), args.verbose ) # result is a WWCCheckStatus (IntEnum) and can be one of: # NONE, UNKNOWN, EMPTY, UNDER18, TEACHER, BADNUMBER, # FAILED, SUCCESS, EXPIRED, INVALID, BADRESPONSE if args.verbose: print('\t{}: {}\t\t- {}'.format(label, name, res)) if res.status not in ( WWCCheckStatus.NONE, WWCCheckStatus.UNKNOWN, WWCCheckStatus.SUCCESS, WWCCheckStatus.UNDER18, WWCCheckStatus.TEACHER, ): print( '{} [{}]: {} ({}): {}'.format( t.sname, t.edjba_id, name, label, res ), file=sys.stderr ) return 0
def main(): parser = ArgumentParser() parser.add_argument('--tmemail', action='store_true', help='just print team manager email addrs') parser.add_argument('--cemail', action='store_true', help='just print coach email addrs') parser.add_argument('--caddrs', action='store_true', help='just print coach names and addresses') parser.add_argument('--noresponse', action='store_true', help='print list of teams that have not responded') parser.add_argument('--csv', action='store_true', help='print info as csv instead of multi-line text') parser.add_argument('--terse', action='store_true', help='print one terse line instead of multi-line text') parser.add_argument('--verbose', action='store_true', help='be verbose about actions') parser.add_argument('--details', action='store_true', help='print more detail in multi-line text') parser.add_argument('--urls', action='store_true', help='print list of teams and urls') args = parser.parse_args() teams = fetch_teams(verbose=args.verbose) # info to print for a person p_fmt = '{} <{}>, {} [WWC: #{}, exp: {}]' def dateonly(s): if s is None: return None else: return sub(r' [0:\.]+$', '', s) if args.csv: print('Name,Id,Code,Age Group,Gender,Number,Grade,' 'Team Manager,Email,Mobile') first = True for t in teams.values(): if args.tmemail: print(t.tm_email) continue if args.cemail: if t.co_email: print(t.co_email) if t.ac_email: print(t.ac_email) continue if args.caddrs: if t.co_address: print('{}, {}'.format(t.co_name, t.co_address)) if t.ac_address: print('{}, {}'.format(t.ac_name, t.ac_address)) continue if args.noresponse and t.responded == 1: continue if args.csv: print('{},{},{},{:02d},{},{:02d},{},{},{},{}'.format( t.sname, t.edjba_id, t.edjba_code, t.age_group, t.gender, t.number, t.grade if t.grade else '', t.tm_name, t.tm_email, t.tm_mobile)) continue if args.terse: # snm = t.sname[:9] + '...' if len(t.sname) > 12 else t.sname # tmn = t.tm_name[:15] + '...' if len(t.tm_name) > 18 else t.tm_name # tme = t.tm_email[:22] + '...' if len(t.tm_email) > 25 \ # else t.tm_email print('{} {:12} {:20} {:40} {}'.format(t.edjba_code, t.sname, t.tm_name, t.tm_email, t.tm_mobile)) elif args.urls: print('{},{},{}'.format(t.sname, t.edjba_id, t.regurl)) else: if first: first = False else: print('') print(t.sname + ':') print(' Id: ' + t.edjba_id) if args.details: print(' Code: ' + t.edjba_code) if t.regurl: print(' URL: ' + t.regurl) if t.compats: print(' Compats: ' + t.compats) if t.grade: print(' Grade?: ' + t.grade) print(' T/M: ' + p_fmt.format(t.tm_name, t.tm_email, t.tm_mobile, t.tm_wwcnum, dateonly(t.tm_wwcexp))) if args.details: if t.co_name and t.co_name != 'Nothing': print(' C: ' + p_fmt.format(t.co_name, t.co_email, t.co_mobile, t.co_wwcnum, dateonly(t.co_wwcexp))) if t.ac_name and t.ac_name != 'Nothing': print(' A/C: ' + p_fmt.format(t.ac_name, t.ac_email, t.ac_mobile, t.ac_wwcnum, dateonly(t.ac_wwcexp))) return 0
def main(): parser = ArgumentParser() parser.add_argument('--club', '-c', default='Fairfield-Shooters', help='change club id') parser.add_argument('--summary', '-R', action='store_true', help='print results summary') parser.add_argument('--upcoming', '-F', action='store_true', help='print results summary') parser.add_argument('--html', '-H', action='store_true', help='print html instead of csv') parser.add_argument('--nrounds', '-n', type=int, default=0, metavar='N', help='specify report file to use') parser.add_argument('--report', '-r', default=None, metavar='F', help='specify report file to use') parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') args = parser.parse_args() teams = fetch_teams() def result(roundno, grade, team_name, score_for=None, score_against=None): t = find_team(teams, edjba_id=team_name) if t is None: print('team {} not found!'.format(team_name), file=sys.stderr) return if not hasattr(t, 'results'): t.results = OrderedDict() if score_for is None: value = None else: value = score_for, score_against if (roundno, grade) in t.results: raise RuntimeError('duplicate game: {}, {}'.format(roundno, grade)) t.results[roundno, grade] = value report_file = args.report if report_file is None: report_file, _ = latest_report('advanced_fixture') if report_file is None: raise RuntimeError('no advanced fixture report found!') if args.verbose: print('[advanced fixture report selected: {}]'.format(report_file), file=sys.stderr) if args.upcoming: print('grade,team1,team2') with open(report_file, 'r', newline='') as csvfile: reader = DictReader(csvfile) for r in reader: _gdate = date(*strptime(r['game date'], '%d/%m/%Y')[:3]) grade = r['grade'] roundno = r['round'] status = r['game status'] bye = r['bye'] team_a_name = r['team a'] team_b_name = r['team b'] _venue = r['venue'] if not r['time']: _gtime = time() else: _gtime = time(*strptime(r['time'], '%H:%M:%S')[3:5]) if status == 'UPCOMING': if args.upcoming: if team_a_name.startswith('Fairfield'): t = find_team(teams, edjba_id=team_a_name) xa = ' [' + t.name[9:] + ']' else: xa = '' if team_b_name.startswith('Fairfield'): t = find_team(teams, edjba_id=team_b_name) xb = ' [' + t.name[9:] + ']' else: xb = '' print('{},{}{},{}{}'.format( grade, team_a_name, xa, team_b_name, xb, )) continue if bye: result(roundno, grade, bye) else: team_a_score = r['team a score'] _team_a_result = r['team a result'] team_b_score = r['team b score'] _team_b_result = r['team b result'] if team_a_name.startswith(args.club): result(roundno, grade, team_a_name, team_a_score, team_b_score) if team_b_name.startswith(args.club): result(roundno, grade, team_b_name, team_b_score, team_a_score) results = [] for t in teams.values(): e = [t.sname, t.edjba_code, t.grade] rcnt = totfor = totag = totmarg = 0 for (r, _), v in t.results.items(): rcnt += 1 if args.nrounds > 0 and rcnt > args.nrounds: break if v is None: e.append('BYE') else: f, a = v if f and a: f = int(f) a = int(a) if f > a: s = 'W' elif f < a: s = 'L' else: s = 'D' e.append('{}{:02d}-{:02d}'.format(s, f, a)) totfor += f totag += a totmarg += f - a e.append('{:.2f}'.format(float(totfor * 100) / float(totag))) e.append('{:.2f}'.format(float(totmarg) / float(rcnt))) results.append(e) if args.summary: if args.html: print('<html><body><table>') for r in results: print('\t<tr>') print('\t\t<td>' + '</td><td>'.join(r) + '</td>') print('\t</tr>') print('</table></body></html>') else: for r in results: print(','.join(r)) return 0
def main(): parser = ArgumentParser() parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') parser.add_argument('--club', '-c', default='Fairfield-Shooters', help='change club id') parser.add_argument('xlsxfiles', nargs='+', help='xlsx file containing edjba fixtures') args = parser.parse_args() teams = fetch_teams() rounds = {} bye = datetime.strptime('00:00', '%H:%S').time() for xlsxfile in args.xlsxfiles: if args.verbose: print('processing file {}'.format(xlsxfile), file=sys.stderr) book = open_workbook(xlsxfile) sheet = book.sheet_by_index(0) rows = sheet.get_rows() _ = next(rows) for r in rows: grade, rdate, rnd, home, away, venue, crt, gtime = map( lambda c: c.value, r) clubmatches = [ home.startswith(args.club), away.startswith(args.club) ] if any(clubmatches): rounds.setdefault(str(rnd), []).append([ clubmatches, grade, xldate_as_datetime(rdate, book.datemode).date(), home, '' if away == 'Bye' else away, venue, crt, bye if away == 'Bye' else xldate_as_datetime( gtime, book.datemode).time(), ]) print('''<html> <head> <style> @media print { .pagebreak { clear: both; page-break-after: always; } } table tr td, table tr th { page-break-inside: avoid; } table, th, td { border: 1px solid black; border-collapse: collapse; } th, td { padding: 5px; font-size: small; } table.center { margin-left: auto; margin-right: auto; } h3 { text-align: center; } caption { display: table-caption; text-align: center; font-weight: bold; margin-top: 36px; margin-bottom: 36px; } </style> </head> <body>''') rcount = 0 for rnd, games in sorted(rounds.items(), key=itemgetter(0)): ngames = sum(2 if all(g[0]) else 1 for g in games) if args.verbose: print('Round {} - {} games'.format(rnd, ngames), file=sys.stderr) if ngames == 0: continue rcount += 1 rdate = games[0][2] dom = rdate.strftime('%d') while dom[0] == '0': dom = dom[1:] mon = rdate.strftime('%B') header = 'Round {} - {} {}'.format(rnd, mon, dom) if rcount > 1: print(' <div class="pagebreak"></div>') print(' <table class="center">') print(' <caption>{}</caption>'.format(escape(header, True))) print(' <tr>' '<th>Grade</th>' '<th>Home</th>' '<th>Away</th>' '<th>Time</th>' '<th>Venue</th>' '<th>Court</th>' '</tr>') n = 0 for (clubmatches, grade, rdate1, home, away, venue, crt, gtime) in sorted(games, key=itemgetter(7)): n += 1 if rdate1 != rdate: raise RuntimeError('differing Round dates ({}!={})'.format( rdate, rdate1)) if clubmatches[0]: home_team = find_team(teams, edjba_id=home) home += ' [<b>{}</b>]'.format(home_team.name[9:]) if clubmatches[1]: away_team = find_team(teams, edjba_id=away) away += ' [<b>{}</b>]'.format(away_team.name[9:]) print(' <tr>' '<td>{}</td>' '<td>{}</td>' '<td>{}</td>' '<td>{}</td>' '<td>{}</td>' '<td>{}</td>' '</tr>'.format( grade, home, away, 'BYE' if gtime is bye else gtime.strftime('%I:%M%p'), venue, crt, )) print(' </table>') print(' </body>') print('</html>') return 0
def main(): parser = ArgumentParser() parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') args = parser.parse_args() report_file, _ = latest_report('team_entries') if report_file is None: print('No team_entries reports.') sys.exit(1) print('[team_entries report selected: {}]'.format(report_file)) teams = fetch_teams() ilst = ('name', 'email', 'mobile') mismatches = { 'name': { 'megan fairbank': 'megan grimmer', 'nat power': 'natalie power', }, } with open(report_file, 'r', newline='') as csvfile: reader = DictReader(csvfile) for tent in reader: team_name = tent['team name'] if not team_name: if args.verbose: print('no team name in {}!'.format(tent)) continue t = find_team(teams, edjba_id=team_name) if t is None: if args.verbose: print('team not found for {}!'.format(team_name)) continue if hasattr(t, 'found'): raise RuntimeError('team appears twice in report!!') t.found = True grade = tent['allocated grade'] # if grade != t.grade: # print( # ' ***** team grade mismatch! ({}!={})'.format( # grade, t.grade # ) # ) print('{} [{}] ({}):'.format(t.sname, t.edjba_code, grade)) ttype = tent['team type'] if ttype != 'Club': print(' ***** team type not Club! ({})'.format(ttype)) tgen = tent['team gender'] if tgen.lower() != t.gender.lower(): print(' ***** team gender mismatch! ({})'.format(tgen)) # tm1info = [tent['team manager1 ' + k] for k in ilst] for k in ilst: v1 = tent['team manager1 ' + k] if v1: if k == 'mobile': v1 = '0' + v1 else: v1 = v1.lower() v2 = getattr(t, 'tm_' + k) if v2: v2 = v2.lower() if v1 != v2: mm = mismatches.get(k) if mm and mm.get(v1) == v2: pass else: print(' ***** team manager {} mismatch! ' '({}!={})'.format(k, v1, v2)) tm2info = [tent['team manager2 ' + k] for k in ilst] if any(tm2info): print(' ***** team has 2nd team manager! ({})'.format( tm2info)) for t in teams.values(): if not hasattr(t, 'found'): print('***** {} was not in report!'.format(t.name)) return 0
def main(): parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) parser.add_argument('--auth', '-a', action='store_true', help='authenticate to the email server') parser.add_argument('--coaches', '-c', action='store_true', help='send to coaches instead of team managers') parser.add_argument('--details', '-d', action='store_true', help='include coach and player details') parser.add_argument('--nocoach', '-N', action='store_true', help='do not include coach details') parser.add_argument('--dryrun', '-n', action='store_true', help='dont actually send email') parser.add_argument('--pause', '-p', action='store_true', help='pause for 5 secs between messages') parser.add_argument('--partreport', default=None, metavar='F', help='specify participants report file to use') parser.add_argument('--testing', '-t', action='store_true', help='just send one test email to a test address') parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') parser.add_argument('--writefiles', '-w', action='store_true', help='write to files instead of sending email') parser.add_argument('--tbreport', default=None, metavar='F', help='specify trybooking report file to use') parser.add_argument('--trybooking', '-T', action='store_true', help='check trybooking payment and include in details') parser.add_argument('--prepend', '-P', default=None, metavar='F', help='specify file to prepend to html body') parser.add_argument('--append', '-A', default=None, metavar='F', help='specify file to append to html body') parser.add_argument('--relay', '-R', default='smtp-relay.gmail.com:587', metavar='H[:P]', help='specify relay host and port') parser.add_argument('--fqdn', '-F', default=None, metavar='H', help='specify the fqdn for the EHLO request') args = parser.parse_args() config = load_config() if ':' in args.relay: smtp_host, smtp_port = args.relay.split(':') else: smtp_host = args.relay smtp_port = 587 if args.auth: if 'email_auth' in config: smtp_user, smtp_pass = config['email_auth'] else: smtp_user = input('SMTP User: '******'SMTP Password: '******'email_fqdn' in config: smtp_fqdn = config['email_fqdn'] if args.writefiles: smtp_class = SMTP_dummy else: smtp_class = SMTP admin_email = '*****@*****.**' testing_email = '*****@*****.**' subject_fmt = 'Registration info for {}' season_label = config.get('season', season.replace('-', ' ').title()) body_fmt = '''\ <html> <head> <style> .pt {} border: 1px solid black; margin-top: 1em; {} </style> </head> <body> <p><i>[automated email - send queries to: {}]</i></p> {}\ <table> <tr> <td>Season:</td><td> </td><td><b><tt>''' \ + season_label + '''</tt></b></td> </tr> <tr> <td></td><td></td><td></td> </tr> <tr> <td>Team Name:</td><td> </td><td><tt>{}</tt></td> </tr> <tr> <td>EDJBA Name:</td><td> </td><td><tt>{}</tt></td> </tr> <tr> <td>EDJBA Code:</td><td> </td><td><tt>{}</tt></td> </tr> {}{}{}\ <tr> <td>Rego Link:</td><td> </td><td><a href="{}"><tt>{}</tt></a></td> </tr> </table> {}{}\ <body> </html>''' teams = fetch_teams() if args.details: player_keys = [ ('last name', 'surname'), ('first name', 'firstname'), ('date of birth', 'd.o.b'), ('parent/guardian1 first name', 'parent firstname'), ('parent/guardian1 last name', 'parent surname'), ('parent/guardian1 mobile number', 'parent mobile'), ('parent/guardian1 email', 'parent email'), ] fetch_participants(teams, args.partreport, args.verbose) if args.trybooking: tbmap = config['tbmap'] tb = fetch_trybooking(tbmap, args.tbreport, args.verbose) if len(tb) == 0: raise RuntimeError('no trybooking data in {}'.format( args.tbreport)) # used this: # https://stackoverflow.com/a/60301124 with smtp_class(smtp_host, int(smtp_port), smtp_fqdn) as smtp: # smtp.set_debuglevel(99) if smtp_class is SMTP: smtp.starttls(context=create_default_context( purpose=Purpose.CLIENT_AUTH)) if args.auth: smtp.login(smtp_user, smtp_pass) for t in teams.values(): print('{} [{}, {}]:'.format(t.name, t.edjba_id, t.edjba_code), file=sys.stderr) recips = [] if args.coaches: if t.co_email: recips.append(t.co_email) if t.ac_email: recips.append(t.ac_email) else: recips.append(t.tm_email) if not recips: print('\tSKIPPING (no recipients).', file=sys.stderr) continue prepend_html = [] if args.prepend: with open(args.prepend, 'r') as fd: for line in fd.read().splitlines(): prepend_html.append('{}\n'.format(line)) pt = [] # player table if args.details: pt.append(' <table class="pt">\n') pt.append(' <thead>\n') pt.append(' <tr>\n') pt.append(' <th class="pt">#</th>\n') for _, h in player_keys: pt.append(' <th class="pt">{}</th>\n'.format( nesc(h.title()))) if args.trybooking: pt.append(' <th class="pt">{}</th>\n'.format( nesc('Ticket#'))) pt.append(' </tr>\n') pt.append(' </thead>\n') pt.append(' <tbody>\n') for n, p in enumerate(t.players): pt.append(' <tr>\n') pt.append(' <td class="pt">{}</td>\n'.format(n + 1)) for k, _ in player_keys: pt.append(' <td class="pt">{}</td>\n'.format( nesc(p[k]))) if args.trybooking: e = find_in_tb( tb, to_fullname(p['first name'], p['last name'])) pt.append(' <td class="pt">{}</td>\n'.format( 'unpaid' if e is None else nesc(e['Ticket Number'] ))) pt.append(' </tr>\n') pt.append(' </tbody>\n') pt.append(' </table>\n') append_html = [] if args.append: with open(args.append, 'r') as fd: for line in fd.read().splitlines(): append_html.append('{}\n'.format(line)) msg = MIMEText( body_fmt.format( '{', '}', nesc(admin_email), ''.join(prepend_html), nesc(t.name), nesc(t.edjba_id), nesc(t.edjba_code), person_tr('Team Manager', t.tm_name, t.tm_email, t.tm_mobile), person_tr('Coach', t.co_name, t.co_email, t.co_mobile) if args.details and not args.nocoach else '', person_tr('Asst Coach', t.ac_name, t.ac_email, t.ac_mobile) if args.details and not args.nocoach else '', nesc(t.regurl), nesc(t.regurl), ''.join(pt), ''.join(append_html), ), 'html', ) msg['From'] = admin_email msg['To'] = ', '.join(recips) msg['Cc'] = admin_email msg['Subject'] = subject_fmt.format(t.name) msg['Return-Path'] = admin_email print('\tsending to {}...'.format(recips), end='', file=sys.stderr) if args.testing: recips = [testing_email] else: recips.append(admin_email) try: if args.dryrun: print('\n*****|{}|{}|\n{}'.format(admin_email, recips, msg.as_string()), file=sys.stderr) else: smtp.sendmail(admin_email, recips, msg.as_string()) print('done.', file=sys.stderr) except KeyboardInterrupt: print('\nInterrupted!', file=sys.stderr) sys.exit(0) except SMTPException as e: if hasattr(e, 'smtp_error'): m = e.smtp_error else: m = repr(e) print('exception - {}'.format(m), file=sys.stderr) if args.testing: break if args.pause: sleep(5) if args.details and args.trybooking: if tb['by-name']: print('{} trybooking tickets unmatched'.format(len(tb['by-name'])), file=sys.stderr) for name, elist in tb['by-name'].items(): print('\t{} [{}]'.format( name, ','.join(e['Ticket Number'] for e in elist)), file=sys.stderr) if tb['by-tnum']: print('{} trybooking tickets unused'.format(len(tb['by-tnum'])), file=sys.stderr) for tnum, elist in tb['by-tnum'].items(): if len(elist) != 1: raise RuntimeError('huh? (1)') entry = elist[0] if entry['Ticket Number'] != tnum: raise RuntimeError('huh? (2)') name = to_fullname( entry['Ticket Data: Player First Name'], entry['Ticket Data: Player Family Name'], ) print('\t{} [{}]'.format(name, tnum), file=sys.stderr) return 0
def main(): parser = ArgumentParser() parser.add_argument('--report', '-r', default=None, metavar='FILE', help='specify report file to use') parser.add_argument('--verbose', '-v', action='store_true', help='print verbose messages') parser.add_argument('--younger', '-y', action='store_true', help='print players younger than their age group') args = parser.parse_args() config = load_config() teams = fetch_teams() fetch_participants(teams, args.report, args.verbose) def pcmp(what, sname, code, p, name, email, mobile, wwcnum, wwcexp): pname = p['first name'] + ' ' + p['last name'] if name is None: print('***** {:12} [{}] : {} name is None! ({})'.format( sname, code, what, pname)) elif name.strip().lower() != pname.strip().lower(): print('***** {:12} [{}] : {} name mismatch! ({}!={})'.format( sname, code, what, name, pname)) if email is None: print('***** {:12} [{}] : [{}] : {} email is None! ({})'.format( sname, code, pname, what, p['email'])) elif email.strip().lower() != p['email'].strip().lower(): print( '***** {:12} [{}] : [{}] : {} email mismatch! ({}!={})'.format( sname, code, pname, what, email, p['email'])) if mobile is None: print('***** {:12} [{}] : [{}] : {} mobile is None! ({})'.format( sname, code, pname, what, p['mobile number'])) else: pmobile = p['mobile number'].strip().lower() if not pmobile.startswith('0'): pmobile = '0' + pmobile if mobile.strip().lower() != pmobile: print('***** {:12} [{}] : [{}] : {} mobile mismatch! ' '({}!={})'.format(sname, code, pname, what, mobile, pmobile)) if wwcnum is None: print('***** {:12} [{}] : [{}] : {} wwcnum is None! ({})'.format( sname, code, pname, what, p['wwc number'])) else: pwwcnum = p['wwc number'].strip().lower() if pwwcnum.startswith('vit '): if len(pwwcnum) == 11 and pwwcnum[8] == '-': pwwcnum = pwwcnum[:8] + pwwcnum[9:] else: if len(pwwcnum) == 8: pwwcnum += '-01' elif (len(pwwcnum) == 10 and pwwcnum[8].isdigit() and pwwcnum[9].isdigit()): pwwcnum = pwwcnum[:8] + '-' + pwwcnum[8:] if wwcnum.strip().lower() != pwwcnum: print('***** {:12} [{}] : [{}] : {} wwc number mismatch! ' '({}!={})'.format(sname, code, pname, what, wwcnum, pwwcnum)) if wwcexp is None: print('***** {:12} [{}] : [{}] : {} wwcexp is None! ({})'.format( sname, code, pname, what, p['wwc expiry date'])) else: pwwcexp = p['wwc expiry date'].strip().lower() if not pwwcexp.endswith(' 00:00:00.000'): pwwcexp += ' 00:00:00.000' if wwcexp.strip().lower() != pwwcexp: print('***** {:12} [{}] : [{}] : {} wwcexp mismatch! ' '({}!={})'.format(sname, code, pname, what, wwcexp, pwwcexp)) for t in teams.values(): ag_start_s, ag_end_s = config['age_groups']['U{:d}'.format( t.age_group)] ag_start = to_date(ag_start_s) ag_end = to_date(ag_end_s) for p in t.players: dob = to_date(p['date of birth']) if dob < ag_start or (args.younger and ag_end and dob > ag_end): print('***** {:12} [{}] : {} - {}'.format( t.sname, t.edjba_code, to_fullname(p['first name'], p['last name']), p['date of birth'], )) # print('S={},E={},D={}'.format(ag_start, ag_end, dob)) if len(t.managers) == 0: print('***** {:12} [{}] : No Team Managers!'.format( t.sname, t.edjba_code)) else: pcmp('Team Manager', t.sname, t.edjba_code, t.managers[0], t.tm_name, t.tm_email, t.tm_mobile, t.tm_wwcnum, t.tm_wwcexp) if len(t.managers) > 1: print('***** {:12} [{}] : more than 1 team manager!'.format( t.sname, t.edjba_code)) n = 2 for m in t.managers[1:]: print('***** {:12} [{}] : T/M{} = {}'.format(n, m)) n += 1 if len(t.coaches) == 0: print('***** {:12} [{}] : No Coaches!'.format( t.sname, t.edjba_code)) else: pcmp('Coach', t.sname, t.edjba_code, t.coaches[0], t.co_name, t.co_email, t.co_mobile, t.co_wwcnum, t.co_wwcexp) if len(t.coaches) > 1: pcmp('Assistant Coach', t.sname, t.edjba_code, t.coaches[1], t.ac_name, t.ac_email, t.ac_mobile, t.ac_wwcnum, t.ac_wwcexp) if len(t.coaches) > 2: print('***** {:12} [{}] : more than 2 coaches!'.format( t.sname, t.edjba_code)) n = 3 for m in t.managers[1:]: print('***** {:12} [{}] : Coach{} = {}'.format(n, m)) n += 1 return 0