def invite_user(admin_username, member_username, event_id): """ Invite a user to an event. Parameters: admin_username (str): username of event admin member_username (str): username of invitee event_id (int): unique ID of event Returns: None Exceptions: AuthError if any of: admin_username is not the event admin's username admin_username is not logged in InputError if any of: event_id does not exist member_username does not exist admin_username does not exist """ check_username(admin_username) check_event_id(event_id) check_is_admin(admin_username, event_id) check_logged_in(admin_username) check_username(member_username) event = data.events.get(event_id) event.member_usernames.add(member_username) event.availabilities[member_username] = Schedule(member_username)
def edit_event_deadline(admin_username, new_date, event_id): """ Edit an event's target deadline. Paramters: admin_username (str): username of event admin new_date (datetime.date): new event deadline date event_id (int): unique ID of event Exceptions: AuthError when any of: admin_username is not logged in admin_username is not the event admin InputError when any of: admin_username does not exist event_id does not exist new_date is a date in the past Returns: None """ check_username(admin_username) check_event_id(event_id) check_is_admin(admin_username, event_id) check_logged_in(admin_username) if new_date < date.today(): raise InputError("Invalid deadline") event = data.events.get(event_id) event.event_deadline = new_date
def remove_user(admin_username, member_username, event_id): """ Remove a user from an event Paramters: admin_username (str): username of event admin member_username (str): username of member being removed event_id (int): unique ID of event Exceptions: InputError when any of: admin_username does not exist member_username is not in the event with event_id member_username is admin_username event_id does not exist AuthError when any of: admin_username is not the event admin admin_username is not logged in Returns: None """ check_username(admin_username) check_event_id(event_id) check_is_admin(admin_username, event_id) check_logged_in(admin_username) check_username(member_username) check_is_member(member_username, event_id) if admin_username == member_username: raise InputError("Cannot remove self") event = data.events.get(event_id) event.member_usernames.remove(member_username) del event.availabilities[member_username]
def edit_event_length(admin_username, new_length, event_id): """ Edit an event's length. Paramters: admin_username (str): username of event admin new_length (int): new event length in hours event_id (int): unique ID of event Exceptions: AuthError when any of: admin_username is not logged in admin_username is not the event admin InputError when any of: new_length is 0 or longer than 14 * 24 (fortnight) event_id does not exist admin_username does not exist Returns: None """ check_username(admin_username) check_event_id(event_id) check_is_admin(admin_username, event_id) check_logged_in(admin_username) if not (MIN_EVENT <= new_length <= MAX_EVENT): raise InputError("Invalid event length") event = data.events.get(event_id) event.event_length = new_length
def leave_event(username, event_id): """ Leave an event. Parameters: username (str): username of event leaver event_id (int): unique ID of event Exceptions: InputError when any of: username does not exist event_id does not exist username is not a member of event username is the event admin AuthError when: username is not logged in Returns: None """ check_username(username) check_event_id(event_id) check_is_member(username, event_id) check_logged_in(username) event = data.events.get(event_id) if username == event.admin_username: raise InputError("Admin cannot leave event") event.member_usernames.remove(username) del event.availabilities[username]
def edit_availability_special(username, event_id, edit_mode, start, end): """ Set availability for a non-repeating specific time interval. Parameters: username (str): username of editor event_id (int): unique ID of event edit_mode (bool): True for available, False for unavailable start (datetime.datetime): start time end (datetime.datetime): end time (start and end are in intervals of 30 minutes) Exceptions: AuthError when any of: username is not logged in InputError when any of: event_id does not exist username does not exist username is not a member of event end is before or the same as start start or end is more than 60 days after event creation start or end is before the event creation time Returns: None """ check_username(username) check_event_id(event_id) check_is_member(username, event_id) check_logged_in(username) if end <= start: raise InputError("Invalid time range") event = data.events.get(event_id) if start < event.create_time or end < event.create_time: raise InputError("Start or end time is in the past") if (start > timedelta(days=60) + event.create_time or end > timedelta(days=60) + event.create_time): raise InputError("Start or end time is too late") start_index = (start.date() - event.create_time.date()).days end_index = (end.date() - event.create_time.date()).days schedule = event.availabilities[username].times current_interval = start.hour * 2 + start.minute // 30 current_day_index = start_index current = start while current < end: schedule[current_day_index][current_interval] = edit_mode current_interval += 1 if current_interval == INTERVALS: current_interval = 0 current_day_index += 1 current += timedelta(seconds=(60 * 30))
def create_event(username, title, members, event_length=None, event_deadline=None): """ Create an event with the given details. Parameters: username (str): username of event creator title (str): name of event members ([str]): list of usernames of additional event members event_length (int): event length in hours event_deadline (datetime.date): latest desired event date Returns: event_id (int): unique ID of new event Exceptions: AuthError if any of: the user is not logged in InputError if any of: username does not exist a username in the members list does not exist title is longer than 100 characters or empty event_length is less than 1 or greater than 14 * 24 (fortnight) event_deadline is a date in the past """ check_username(username) for u in members: check_username(u) check_logged_in(username) if not len(title) or len(title) > MAX_TITLE: raise InputError("Title length is invalid") if (event_length != None and (event_length < MIN_EVENT or event_length > MAX_EVENT)): raise InputError("Event length is invalid") if event_deadline and event_deadline < datetime.now().date(): raise InputError("Event deadline is invalid") new_event = Event(data.event_next_id, title, username) data.event_next_id += 1 for u in members: new_event.member_usernames.add(u) new_event.event_length = event_length new_event.event_deadline = event_deadline data.events[new_event.event_id] = new_event return new_event.event_id
def edit_availability_weekly(username, event_id, edit_mode, day, start, end): """ Add a weekly schedule of availabilities Parameters: username (str): username of editor event_id (int): unique ID of event edit_mode (bool): True for available, False for unavailable day (int): day of week in schedule, 0 is Mon, 6 is Sun start (datetime.time): start time in scheduled day of week end (datetime.time): end time in scheduled day of week (start and end are in intervals of 30 minutes) Exceptions: InputError when any of: username does not exist event_id does not exist day is not valid end is at or before start username is not member of event AuthError when any of: username is not logged in Returns: None """ check_username(username) check_event_id(event_id) check_is_member(username, event_id) check_logged_in(username) if not MON <= day <= SUN: raise InputError("Invalid week day") if end <= start: raise InputError("Invalid time interval") event = data.events.get(event_id) schedule = event.availabilities[username] offset = (day - event.create_time.weekday() + 7) % 7 start = start.hour * 2 + start.minute // 30 end = end.hour * 2 + end.minute // 30 for d in range(offset, MAX_DAYS, 7): for t in range(start, end): schedule.times[d][t] = edit_mode
def find_best_times(username, event_id): """ Find the best three closest time intervals for meeting, where 'best' is defined to be the date with the most members available. If the event length is set, the start of the best time intervals of that length will be found, otherwise a 3 hour interval will be assumed. If the event deadline is set, the best times before the deadline will be found, otherwise the maximum deadline of 60 days past the creation date. If not modified, the best times will be found within the default desired time range of the event. Parameters: username (str): username of user event_id (int): unique ID of event Exceptions: InputError when any of: username does not exist event_id does not exist username is not a member of event AuthError when any of: username is not logged in Returns: times ([datetime.datetime]): a list of the best times, from best to worst """ check_username(username) check_event_id(event_id) check_is_member(username, event_id) check_logged_in(username) event = data.events.get(event_id) schedules = [s.times for s in list(event.availabilities.values())] intersection = find_intersection(schedules) print(event.admin_username) for u in event.availabilities: print(u, event.availabilities[u].times[:9]) #print(intersection) best_intervals = find_best_intervals(intersection, CUTOFF, event) return best_intervals
def log_out(username): """ Log a user out if given valid username and if not already logged out. Paramters: username (str): username of logging out user Returns: None Exceptions: AuthError when one of: username exists but user is already logged out InputError when: username does not exist """ check_username(username) check_logged_in(username) data.users[username].logged_in = False
def event_details(username, event_id): """ Give details about the given event, specifically a list of event members, event creation date, event deadline, event length, event admin. Parameters: username (str): username of user requesting event details event_id (int): unique ID of event Exceptions: InputError when any of: username does not exist event_id does not exist username is not a member of event AuthError when: username is not logged in Returns: members ({str}): a set of event member usernames admin (str): username of event admin create_time (datetime.datetime): create time of event length (int): event length in hours deadline (datetime.date): event deadline """ check_username(username) check_event_id(event_id) check_is_member(username, event_id) check_logged_in(username) event = data.events.get(event_id) details = { "members": event.member_usernames, "admin": event.admin_username, "create_time": event.create_time, "length": event.event_length, "deadline": event.event_deadline, } return details
def edit_availability_daily(username, event_id, edit_mode, day): """ Set availability for a full day. Parameters: username (str): username of editor event_id (int): unique ID of event edit_mode (bool): True for available, False for unavailable day (datetime.date): day chosen Exceptions: AuthError when any of: username is not logged in InputError when any of: username does not exist event_id does not exist username is not part of the event day is a date before the event creation date day is a date beyond 60 days after event creation Returns: None """ check_username(username) check_event_id(event_id) check_is_member(username, event_id) check_logged_in(username) event = data.events.get(event_id) if day < event.create_time.date(): raise InputError("Date cannot be in the past") if day >= event.create_time.date() + timedelta(days=MAX_DAYS): raise InputError("Date is too far into future") schedule = event.availabilities[username].times offset = (day - event.create_time.date()).days schedule[offset] = [edit_mode for _ in range(INTERVALS)]