diff --git a/config.json b/config.json index f386ef39d6..970f791837 100644 --- a/config.json +++ b/config.json @@ -1085,6 +1085,20 @@ ], "difficulty": 3 }, + { + "slug": "global-meeting", + "name": "Global Meeting", + "uuid": "795edb33-ec92-43c5-8cd9-147af4d56f5d", + "practices": [], + "prerequisites": [ + "basics", + "bools", + "conditionals", + "dictionaries", + "loops" + ], + "difficulty": 4 + }, { "slug": "kindergarten-garden", "name": "Kindergarten Garden", diff --git a/exercises/practice/global-meeting/.docs/instructions.append.md b/exercises/practice/global-meeting/.docs/instructions.append.md new file mode 100644 index 0000000000..fe6af09d5f --- /dev/null +++ b/exercises/practice/global-meeting/.docs/instructions.append.md @@ -0,0 +1,55 @@ +# Instruction append +Here's an example of what's expected: +```python +>>> meeting_time("06/21/2023", { + 110: (5.5, "08:00 AM", "05:00 PM"), + 111: (-10, "12:00 PM", "09:00 PM"), + 112: (3, "04:00 AM", "01:00 PM"), + 113: (-4, "04:00 PM", "01:00 AM") + }) +{ + "03:00 AM": { + 110: "06/21/2023 08:30 AM", + 111: "06/20/2023 05:00 PM", + 112: "06/21/2023 06:00 AM", + 113: "06/20/2023 11:00 PM", + }, + "4:00 AM": { + 110: "06/21/2023 09:30 AM", + 111: "06/20/2023 06:00 PM", + 112: "06/21/2023 07:00 AM", + 113: "06/21/2023 12:00 AM", + }, +} +``` + +## Exception messages + +Sometimes it is necessary to [raise an exception](https://docs.python.org/3/tutorial/errors.html#raising-exceptions). +When you do this, you should always include a **meaningful error message** to indicate what the source of the error is. +This makes your code more readable and helps significantly with debugging. For situations where you know that the error source will be a certain type, you can choose to raise one of the [built in error types](https://docs.python.org/3/library/exceptions.html#base-classes), but should still include a meaningful message. + + + + +Admittedly, you're a little eccentric. +You might provide working hours that are more or less than 9 - in which case you want the program to call out your error: + +To raise a `ValueError` with a message, write the message as an argument to the `exception` type: +``` +>>> meeting_time({ + 201: [2, (5, 15)], + 202: [5, (13, 22)], + }) +ValueError: some employees are working for more or less than 9 hours +``` + +If there's no possible meeting period, then you have to reshuffle teams. +Until then, your code should raise an error: +``` +>>> meeting_time({ + 201: [5, (5, 14)], + 202: [2, (13, 22)], + }) +ValueError: there's no possible meeting time for the provided employees +``` \ No newline at end of file diff --git a/exercises/practice/global-meeting/.docs/instructions.md b/exercises/practice/global-meeting/.docs/instructions.md new file mode 100644 index 0000000000..213f0f9403 --- /dev/null +++ b/exercises/practice/global-meeting/.docs/instructions.md @@ -0,0 +1,17 @@ +# Instructions + +Your task is to find out a time in which a set of your employees are working so that you can have an hour-long meeting. + +Company policy allows employees to choose their own 9 hours of working time, inclusive of an hour break. +This is an important meeting, so if people need to attend during their break, the company will let them take an extra break/hour on another day within the month. + + +Given a collection of employee IDs with their time zones and working hours, return a collection of all possible meeting times, each of which should contain the local time and date for all employees listed. +Note that meetings should start "on the hour" in UTC - in other words, a meeting can't start at, 3:30, 12:10, or 17:45 UTC. +Local times, of course may vary. + +Local time zones are represented as [UTC offsets][UTC offset]. + +All possible meeting start times should be reported. + +[UTC offset]: https://en.wikipedia.org/wiki/UTC_offset diff --git a/exercises/practice/global-meeting/.docs/introduction.md b/exercises/practice/global-meeting/.docs/introduction.md new file mode 100644 index 0000000000..1b47370e4f --- /dev/null +++ b/exercises/practice/global-meeting/.docs/introduction.md @@ -0,0 +1,15 @@ +# Introduction + +You've decided to make your video game manufacturing company The CatnessĀ® fully remote: all employees work from home! +This has multiple advantages: after all, transit is annoying and exhausting, and everyone has their commute time back for more important activities (_like playing on their gaming consoles_). +Furthermore, people all over the world have heard about your wonderful company, and you've got lots of new and diverse talent working away at the latest edition of your flagship game _Mad Cat_. + +You're thrilled! +There's only one hitch. +To ensure that everyone is working towards the same goals and keeping to the release schedule, you need to have a weekly meeting. +It's tough to arrange a meeting across different timezones, and your first attempt was a ghastly failure. +Many crucial people spent time rubbing their eyes and not paying attention. +Worse, there were a lot of absences because employees miscalculated their local meeting start times. + +Your advisor tells you to calculate a timing suitable for everybody _and_ email employees with their local timings - but you barely passed high school math. +You panic as the date of release looms: but you've realized that you can write a program to do it for you! \ No newline at end of file diff --git a/exercises/practice/global-meeting/.meta/config.json b/exercises/practice/global-meeting/.meta/config.json new file mode 100644 index 0000000000..08a0276b92 --- /dev/null +++ b/exercises/practice/global-meeting/.meta/config.json @@ -0,0 +1,17 @@ + +{ + "authors": ["safwansamsudeen"], + "contributors": [], + "files": { + "solution": [ + "global_meeting.py" + ], + "test": [ + "global_meeting_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Find a time when a global team can have their meeting" +} diff --git a/exercises/practice/global-meeting/.meta/example.py b/exercises/practice/global-meeting/.meta/example.py new file mode 100644 index 0000000000..9d9a3a1d68 --- /dev/null +++ b/exercises/practice/global-meeting/.meta/example.py @@ -0,0 +1,46 @@ +from datetime import datetime, timedelta, timezone, time + + +def meeting_time(date_str, employees): + meeting_times = {} + + meeting_date = datetime.strptime(date_str, "%m/%d/%Y") + + for hour in range(24): + meeting_start_time = meeting_date.replace( + hour=hour, minute=0, second=0, tzinfo=timezone.utc + ) + meeting_end_time = meeting_start_time + timedelta(hours=1) + + employees_possible = {} + for emp_id, (utc_offset, emp_start_str, emp_end_str) in employees.items(): + emp_timezone = timezone(timedelta(hours=utc_offset)) + + start_datetime = datetime.combine( + meeting_date, + datetime.strptime(emp_start_str, "%I:%M %p").time(), + tzinfo=emp_timezone, + ).astimezone(timezone.utc) + end_datetime = datetime.combine( + meeting_date, + datetime.strptime(emp_end_str, "%I:%M %p").time(), + tzinfo=emp_timezone, + ).astimezone(timezone.utc) + + if end_datetime < start_datetime: + end_datetime = end_datetime + timedelta(days=1) + for i in range(-1, 2): + modified_start = start_datetime + timedelta(days=i) + modified_end = end_datetime + timedelta(days=i) + if ( + modified_start <= meeting_start_time + and modified_end >= meeting_end_time + ): + employees_possible[emp_id] = meeting_start_time.astimezone( + emp_timezone + ).strftime("%m/%d/%Y %I:%M %p") + + if len(employees_possible) == 4: + meeting_times[time(hour=hour).strftime("%I:%M %p")] = employees_possible + + return meeting_times diff --git a/exercises/practice/global-meeting/global_meeting.py b/exercises/practice/global-meeting/global_meeting.py new file mode 100644 index 0000000000..abb8cb2a8c --- /dev/null +++ b/exercises/practice/global-meeting/global_meeting.py @@ -0,0 +1,2 @@ +def meeting_time(date_str, employee_info): + pass diff --git a/exercises/practice/global-meeting/global_meeting_test.py b/exercises/practice/global-meeting/global_meeting_test.py new file mode 100644 index 0000000000..022d39eedd --- /dev/null +++ b/exercises/practice/global-meeting/global_meeting_test.py @@ -0,0 +1,35 @@ +import unittest + +from global_meeting import meeting_time + + +class GlobalMeetingTest(unittest.TestCase): + def test_different_working_times(self): + self.assertEqual( + meeting_time( + "06/21/2023", + { + 110: (5.5, "08:00 AM", "05:00 PM"), + 111: (-10, "12:00 PM", "09:00 PM"), + 112: (3, "04:00 AM", "01:00 PM"), + 113: (-4, "04:00 PM", "01:00 AM"), + }, + ), + { + "03:00 AM": { + 110: "06/21/2023 08:30 AM", + 111: "06/20/2023 05:00 PM", + 112: "06/21/2023 06:00 AM", + 113: "06/20/2023 11:00 PM", + }, + "04:00 AM": { + 110: "06/21/2023 09:30 AM", + 111: "06/20/2023 06:00 PM", + 112: "06/21/2023 07:00 AM", + 113: "06/21/2023 12:00 AM", + }, + }, + ) + + +unittest.main()