import argparse, datetime def date(s): try: return datetime.datetime.strptime(s, "%Y-%m-%d") except ValueError: raise argparse.ArgumentTypeError(f"Not a valid date: '{s}'. Date must be in format 'YYYY-MM-DD'") parser = argparse.ArgumentParser(description='Generate a P90X3 schedule in iCalendar format.') parser.add_argument('--start', type=date, default=datetime.date.today(), help='start date (YYYY-MM-DD) (default: today)') parser.add_argument('--variant', choices=["classic", "lean", "mass"], default="classic", help="calendar variant (default: classic)") parser.add_argument('--prefix', type=str, default='', help="prefix to add to all event names") parser.add_argument('--suffix', type=str, default='', help="suffix to add to all event names") args = parser.parse_args() TOTAL = "Total Synergistics" CVX = "CVX" AGILITY = "Agility X" TRIO = "Triometrics" CHALLENGE = "The Challenge" INCINERATOR = "Incinerator" WARRIOR = "The Warrior" MMX = "MMX" YOGA = "X3 Yoga" PILATES = "Pilates X" ISOMETRICS = "Isometrics" DYNAMIX = "Dynamix" ACCELERATOR = "Accelerator" DECELERATOR = "Decelerator" UPPER = "Eccentric Upper" LOWER = "Eccentric Lower" REST = "Rest or Dynamix" SCHEDULES = { "classic": [ TOTAL, AGILITY, YOGA, CHALLENGE, CVX, WARRIOR, REST, TOTAL, AGILITY, YOGA, CHALLENGE, CVX, WARRIOR, REST, TOTAL, AGILITY, YOGA, CHALLENGE, CVX, WARRIOR, REST, ISOMETRICS, DYNAMIX, ACCELERATOR, PILATES, CVX, YOGA, REST, UPPER, TRIO, YOGA, LOWER, INCINERATOR, MMX, REST, UPPER, TRIO, YOGA, LOWER, INCINERATOR, MMX, REST, UPPER, TRIO, YOGA, LOWER, INCINERATOR, MMX, REST, ISOMETRICS, DYNAMIX, ACCELERATOR, PILATES, CVX, YOGA, REST, DECELERATOR, AGILITY, CHALLENGE, YOGA, TRIO, TOTAL, REST, DECELERATOR, MMX, UPPER, TRIO, PILATES, LOWER, REST, DECELERATOR, AGILITY, CHALLENGE, YOGA, TRIO, TOTAL, REST, DECELERATOR, MMX, UPPER, TRIO, PILATES, LOWER, REST, ISOMETRICS, ACCELERATOR, PILATES, YOGA, DYNAMIX, REST, ], "lean": [ ACCELERATOR, WARRIOR, YOGA, CVX, ISOMETRICS, AGILITY, REST, ACCELERATOR, WARRIOR, YOGA, CVX, ISOMETRICS, AGILITY, REST, ACCELERATOR, WARRIOR, YOGA, CVX, ISOMETRICS, AGILITY, REST, ISOMETRICS, DYNAMIX, ACCELERATOR, PILATES, AGILITY, YOGA, REST, TRIO, WARRIOR, YOGA, MMX, INCINERATOR, CVX, REST, TRIO, WARRIOR, YOGA, MMX, INCINERATOR, CVX, REST, TRIO, WARRIOR, YOGA, MMX, INCINERATOR, CVX, REST, ISOMETRICS, DYNAMIX, ACCELERATOR, PILATES, DECELERATOR, YOGA, REST, DECELERATOR, MMX, LOWER, YOGA, TRIO, UPPER, REST, MMX, DECELERATOR, TRIO, PILATES, DECELERATOR, CVX, REST, DECELERATOR, MMX, LOWER, YOGA, TRIO, UPPER, REST, MMX, DECELERATOR, TRIO, PILATES, DECELERATOR, CVX, REST, ISOMETRICS, ACCELERATOR, PILATES, YOGA, DYNAMIX, REST, ], "mass": [ TOTAL, AGILITY, YOGA, CHALLENGE, PILATES, INCINERATOR, REST, TOTAL, AGILITY, YOGA, CHALLENGE, PILATES, INCINERATOR, REST, TOTAL, AGILITY, YOGA, CHALLENGE, PILATES, INCINERATOR, REST, ISOMETRICS, DYNAMIX, WARRIOR, PILATES, AGILITY, YOGA, REST, UPPER, LOWER, YOGA, UPPER, LOWER, MMX, REST, UPPER, LOWER, YOGA, UPPER, LOWER, MMX, REST, UPPER, LOWER, YOGA, UPPER, LOWER, MMX, REST, ISOMETRICS, DYNAMIX, WARRIOR, PILATES, DECELERATOR, YOGA, REST, UPPER, LOWER, YOGA, UPPER, LOWER, MMX, REST, TOTAL, AGILITY, YOGA, CHALLENGE, PILATES, INCINERATOR, REST, UPPER, LOWER, YOGA, UPPER, LOWER, MMX, REST, TOTAL, AGILITY, YOGA, CHALLENGE, PILATES, INCINERATOR, REST, ISOMETRICS, YOGA, DECELERATOR, UPPER, LOWER, REST, ] } prefix = '' if args.prefix == '' else args.prefix + ' ' suffix = '' if args.suffix == '' else ' ' + args.suffix print("BEGIN:VCALENDAR") print("VERSION:2.0") print("PRODID:-//jonb.io//p90x3iCalgen 1.0//EN") schedule = SCHEDULES[args.variant] date = args.start for workout in schedule: print("BEGIN:VEVENT") print(f'SUMMARY:{prefix}{workout}{suffix}') formattedDate = date.strftime("%Y%m%d") print(f'DTSTART:{formattedDate}') print(f'DTEND:{formattedDate}') print(f'DTSTAMP:') print("END:VEVENT") date = date + datetime.timedelta(days=1) print("END:VCALENDAR")