diff --git a/config.json b/config.json index 82a4174..25db9e3 100644 --- a/config.json +++ b/config.json @@ -226,6 +226,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "swift-scheduling", + "name": "Swift Scheduling", + "uuid": "51691c60-f878-4c1d-94e0-9e38e1e974d2", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "acronym", "name": "Acronym", diff --git a/exercises/practice/swift-scheduling/.docs/instructions.md b/exercises/practice/swift-scheduling/.docs/instructions.md new file mode 100644 index 0000000..6423a10 --- /dev/null +++ b/exercises/practice/swift-scheduling/.docs/instructions.md @@ -0,0 +1,50 @@ +# Instructions + +Your task is to convert delivery date descriptions to _actual_ delivery dates, based on when the meeting started. + +There are two types of delivery date descriptions: + +1. Fixed: a predefined set of words. +2. Variable: words that have a variable component, but follow a predefined set of patterns. + +## Fixed delivery date descriptions + +There are three fixed delivery date descriptions: + +- `"NOW"` +- `"ASAP"` (As Soon As Possible) +- `"EOW"` (End Of Week) + +The following table shows how to translate them: + +| Description | Meeting start | Delivery date | +| ----------- | ----------------------------- | ----------------------------------- | +| `"NOW"` | - | Two hours after the meeting started | +| `"ASAP"` | Before 13:00 | Today at 17:00 | +| `"ASAP"` | After or at 13:00 | Tomorrow at 13:00 | +| `"EOW"` | Monday, Tuesday, or Wednesday | Friday at 17:00 | +| `"EOW"` | Thursday or Friday | Sunday at 20:00 | + +## Variable delivery date descriptions + +There are two variable delivery date description patterns: + +- `"M"` (N-th month) +- `"Q"` (N-th quarter) + +| Description | Meeting start | Delivery date | +| ----------- | ------------------------- | --------------------------------------------------------- | +| `"M"` | Before N-th month | At 8:00 on the _first_ workday of this year's N-th month | +| `"M"` | After or in N-th month | At 8:00 on the _first_ workday of next year's N-th month | +| `"Q"` | Before or in N-th quarter | At 8:00 on the _last_ workday of this year's N-th quarter | +| `"Q"` | After N-th quarter | At 8:00 on the _last_ workday of next year's N-th quarter | + +~~~~exercism/note +A workday is a Monday, Tuesday, Wednesday, Thursday, or Friday. + +A year has four quarters, each with three months: +1. January/February/March +2. April/May/June +3. July/August/September +4. October/November/December. +~~~~ diff --git a/exercises/practice/swift-scheduling/.docs/introduction.md b/exercises/practice/swift-scheduling/.docs/introduction.md new file mode 100644 index 0000000..2322f81 --- /dev/null +++ b/exercises/practice/swift-scheduling/.docs/introduction.md @@ -0,0 +1,6 @@ +# Introduction + +This week, it is your turn to take notes in the department's planning meeting. +In this meeting, your boss will set delivery dates for all open work items. +Annoyingly, instead of specifying the _actual_ delivery dates, your boss will only _describe them_ in an abbreviated format. +As many of your colleagues won't be familiar with this corporate lingo, you'll need to convert these delivery date descriptions to actual delivery dates. diff --git a/exercises/practice/swift-scheduling/.meta/config.json b/exercises/practice/swift-scheduling/.meta/config.json new file mode 100644 index 0000000..4de5402 --- /dev/null +++ b/exercises/practice/swift-scheduling/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "jimmytty" + ], + "files": { + "solution": [ + "swift-scheduling.sql" + ], + "test": [ + "swift-scheduling_test.sql" + ], + "example": [ + ".meta/example.sql" + ] + }, + "blurb": "Convert delivery date descriptions to actual delivery dates.", + "source": "Erik Schierboom", + "source_url": "https://github.com/exercism/problem-specifications/pull/2536" +} diff --git a/exercises/practice/swift-scheduling/.meta/example.sql b/exercises/practice/swift-scheduling/.meta/example.sql new file mode 100644 index 0000000..b9b8f69 --- /dev/null +++ b/exercises/practice/swift-scheduling/.meta/example.sql @@ -0,0 +1,122 @@ +UPDATE "swift-scheduling" + SET result = + STRFTIME('%Y-%m-%dT%H:%M:%S', DATETIME(meeting_start, '+2 HOUR')) + WHERE date_description = 'NOW' +; + +UPDATE "swift-scheduling" + SET result = STRFTIME( + '%Y-%m-%dT%H:%M:%S', + IIF( + TIME(meeting_start) < TIME('13:00'), + DATETIME(meeting_start, 'START OF DAY', '+17 HOUR'), + DATETIME(meeting_start, '+1 DAY', 'START OF DAY', '+13 HOUR') + ) + ) + WHERE date_description = 'ASAP' +; + +UPDATE "swift-scheduling" + SET result = STRFTIME( + '%Y-%m-%dT%H:%M:%S', + IIF( + STRFTIME('%w', meeting_start) * 1 BETWEEN 1 AND 3, + DATETIME(meeting_start, 'WEEKDAY 5', 'START OF DAY', '+17 HOUR'), + DATETIME(meeting_start, 'WEEKDAY 0', 'START OF DAY', '+20 HOUR') + ) + ) + WHERE date_description = 'EOW' +; + +UPDATE "swift-scheduling" + SET result = ( + WITH cte (date_time) AS ( + SELECT + IIF( + STRFTIME('%m', meeting_start) * 1 < + REPLACE(date_description, 'D', '') * 1, + DATETIME( + meeting_start, + 'START OF YEAR', + PRINTF('+%d MONTH', REPLACE(date_description, 'D', '') - 1), + '+8 HOUR' + ), + DATETIME( + meeting_start, + 'START OF YEAR', + '+1 YEAR', + PRINTF('+%d MONTH', REPLACE(date_description, 'D', '') - 1), + '+8 HOUR' + ) + ) + ) + SELECT STRFTIME( + '%Y-%m-%dT%H:%M:%S', + IIF( + STRFTIME('%w', date_time) * 1 IN (6, 0), + DATETIME(date_time, 'WEEKDAY 1'), + date_time + ) + ) + FROM cte + ) + WHERE SUBSTRING(date_description, -1) = 'M'; + +DROP TABLE IF EXISTS quarters; +CREATE TEMPORARY TABLE quarters ( + quarter INTEGER NOT NULL, + month INTEGER UNIQUE NOT NULL +); +INSERT INTO quarters +VALUES (1, 1), (1, 2), (1, 3), + (2, 4), (2, 5), (2, 6), + (3, 7), (3, 8), (3, 9), + (4, 10), (4, 11), (4, 12); + +UPDATE "swift-scheduling" + SET result = ( + WITH cte (date_time) AS ( + SELECT + IIF( + (SELECT quarter <= SUBSTRING(date_description, 2, 1) * 1 + FROM quarters + WHERE month = STRFTIME('%m', meeting_start) * 1 + ), + DATETIME( + meeting_start, + 'START OF YEAR', + (SELECT PRINTF('+%d MONTH', month) + FROM quarters + WHERE quarter = SUBSTRING(date_description, 2, 1) * 1 + ORDER BY month DESC + LIMIT 1 + ), + '-1 DAY', + '+8 HOUR' + ), + DATETIME( + meeting_start, + 'START OF YEAR', + '+1 YEAR', + (SELECT PRINTF('+%d MONTH', month) + FROM quarters + WHERE quarter = SUBSTRING(date_description, 2, 1) * 1 + ORDER BY month DESC + LIMIT 1 + ), + '-1 DAY', + '+8 HOUR' + ) + ) + ) + SELECT STRFTIME( + '%Y-%m-%dT%H:%M:%S', + IIF( + STRFTIME('%w', date_time) * 1 IN (6, 0), + DATETIME(date_time, '-3 DAY', 'WEEKDAY 5'), + date_time + ) + ) + FROM cte + ) + WHERE SUBSTRING(date_description, 1, 1) = 'Q'; diff --git a/exercises/practice/swift-scheduling/.meta/tests.toml b/exercises/practice/swift-scheduling/.meta/tests.toml new file mode 100644 index 0000000..7cc3e41 --- /dev/null +++ b/exercises/practice/swift-scheduling/.meta/tests.toml @@ -0,0 +1,58 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[1d0e6e72-f370-408c-bc64-5dafa9c6da73] +description = "NOW translates to two hours later" + +[93325e7b-677d-4d96-b017-2582af879dc2] +description = "ASAP before one in the afternoon translates to today at five in the afternoon" + +[cb4252a3-c4c1-41f6-8b8c-e7269733cef8] +description = "ASAP at one in the afternoon translates to tomorrow at one in the afternoon" + +[6fddc1ea-2fe9-4c60-81f7-9220d2f45537] +description = "ASAP after one in the afternoon translates to tomorrow at one in the afternoon" + +[25f46bf9-6d2a-4e95-8edd-f62dd6bc8a6e] +description = "EOW on Monday translates to Friday at five in the afternoon" + +[0b375df5-d198-489e-acee-fd538a768616] +description = "EOW on Tuesday translates to Friday at five in the afternoon" + +[4afbb881-0b5c-46be-94e1-992cdc2a8ca4] +description = "EOW on Wednesday translates to Friday at five in the afternoon" + +[e1341c2b-5e1b-4702-a95c-a01e8e96e510] +description = "EOW on Thursday translates to Sunday at eight in the evening" + +[bbffccf7-97f7-4244-888d-bdd64348fa2e] +description = "EOW on Friday translates to Sunday at eight in the evening" + +[d651fcf4-290e-407c-8107-36b9076f39b2] +description = "EOW translates to leap day" + +[439bf09f-3a0e-44e7-bad5-b7b6d0c4505a] +description = "2M before the second month of this year translates to the first workday of the second month of this year" + +[86d82e83-c481-4fb4-9264-625de7521340] +description = "11M in the eleventh month translates to the first workday of the eleventh month of next year" + +[0d0b8f6a-1915-46f5-a630-1ff06af9da08] +description = "4M in the ninth month translates to the first workday of the fourth month of next year" + +[06d401e3-8461-438f-afae-8d26aa0289e0] +description = "Q1 in the first quarter translates to the last workday of the first quarter of this year" + +[eebd5f32-b16d-4ecd-91a0-584b0364b7ed] +description = "Q4 in the second quarter translates to the last workday of the fourth quarter of this year" + +[c920886c-44ad-4d34-a156-dc4176186581] +description = "Q3 in the fourth quarter translates to the last workday of the third quarter of next year" diff --git a/exercises/practice/swift-scheduling/create_fixture.sql b/exercises/practice/swift-scheduling/create_fixture.sql new file mode 100644 index 0000000..019234f --- /dev/null +++ b/exercises/practice/swift-scheduling/create_fixture.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS "swift-scheduling"; +CREATE TABLE "swift-scheduling" ( + meeting_start TEXT NOT NULL, -- datetime YYYY-MM-DDTHH:mm:ss + date_description TEXT NOT NULL, + result TEXT -- datetime YYYY-MM-DDTHH:mm:ss +); + +.mode csv +.import ./data.csv "swift-scheduling" diff --git a/exercises/practice/swift-scheduling/create_test_table.sql b/exercises/practice/swift-scheduling/create_test_table.sql new file mode 100644 index 0000000..af0a0c8 --- /dev/null +++ b/exercises/practice/swift-scheduling/create_test_table.sql @@ -0,0 +1,35 @@ +DROP TABLE IF EXISTS tests; +CREATE TABLE IF NOT EXISTS tests ( + -- uuid and description are taken from the test.toml file + uuid TEXT PRIMARY KEY, + description TEXT NOT NULL, + -- The following section is needed by the online test-runner + status TEXT DEFAULT 'fail', + message TEXT, + output TEXT, + test_code TEXT, + task_id INTEGER DEFAULT NULL, + -- Here are columns for the actual tests + meeting_start TEXT NOT NULL, -- datetime YYYY-MM-DDTHH:mm:ss + date_description TEXT NOT NULL, + expected TEXT NOT NULL +); + +INSERT INTO tests (uuid, description, meeting_start, date_description, expected) +VALUES + ('1d0e6e72-f370-408c-bc64-5dafa9c6da73','NOW translates to two hours later','2012-02-13T09:00:00','NOW','2012-02-13T11:00:00'), + ('93325e7b-677d-4d96-b017-2582af879dc2','ASAP before one in the afternoon translates to today at five in the afternoon','1999-06-03T09:45:00','ASAP','1999-06-03T17:00:00'), + ('cb4252a3-c4c1-41f6-8b8c-e7269733cef8','ASAP at one in the afternoon translates to tomorrow at one in the afternoon','2008-12-21T13:00:00','ASAP','2008-12-22T13:00:00'), + ('6fddc1ea-2fe9-4c60-81f7-9220d2f45537','ASAP after one in the afternoon translates to tomorrow at one in the afternoon','2008-12-21T14:50:00','ASAP','2008-12-22T13:00:00'), + ('25f46bf9-6d2a-4e95-8edd-f62dd6bc8a6e','EOW on Monday translates to Friday at five in the afternoon','2025-02-03T16:00:00','EOW','2025-02-07T17:00:00'), + ('0b375df5-d198-489e-acee-fd538a768616','EOW on Tuesday translates to Friday at five in the afternoon','1997-04-29T10:50:00','EOW','1997-05-02T17:00:00'), + ('4afbb881-0b5c-46be-94e1-992cdc2a8ca4','EOW on Wednesday translates to Friday at five in the afternoon','2005-09-14T11:00:00','EOW','2005-09-16T17:00:00'), + ('e1341c2b-5e1b-4702-a95c-a01e8e96e510','EOW on Thursday translates to Sunday at eight in the evening','2011-05-19T08:30:00','EOW','2011-05-22T20:00:00'), + ('bbffccf7-97f7-4244-888d-bdd64348fa2e','EOW on Friday translates to Sunday at eight in the evening','2022-08-05T14:00:00','EOW','2022-08-07T20:00:00'), + ('d651fcf4-290e-407c-8107-36b9076f39b2','EOW translates to leap day','2008-02-25T10:30:00','EOW','2008-02-29T17:00:00'), + ('439bf09f-3a0e-44e7-bad5-b7b6d0c4505a','2M before the second month of this year translates to the first workday of the second month of this year','2007-01-02T14:15:00','2M','2007-02-01T08:00:00'), + ('86d82e83-c481-4fb4-9264-625de7521340','11M in the eleventh month translates to the first workday of the eleventh month of next year','2013-11-21T15:30:00','11M','2014-11-03T08:00:00'), + ('0d0b8f6a-1915-46f5-a630-1ff06af9da08','4M in the ninth month translates to the first workday of the fourth month of next year','2019-11-18T15:15:00','4M','2020-04-01T08:00:00'), + ('06d401e3-8461-438f-afae-8d26aa0289e0','Q1 in the first quarter translates to the last workday of the first quarter of this year','2003-01-01T10:45:00','Q1','2003-03-31T08:00:00'), + ('eebd5f32-b16d-4ecd-91a0-584b0364b7ed','Q4 in the second quarter translates to the last workday of the fourth quarter of this year','2001-04-09T09:00:00','Q4','2001-12-31T08:00:00'), + ('c920886c-44ad-4d34-a156-dc4176186581','Q3 in the fourth quarter translates to the last workday of the third quarter of next year','2022-10-06T11:00:00','Q3','2023-09-29T08:00:00'); diff --git a/exercises/practice/swift-scheduling/data.csv b/exercises/practice/swift-scheduling/data.csv new file mode 100644 index 0000000..8e3db9a --- /dev/null +++ b/exercises/practice/swift-scheduling/data.csv @@ -0,0 +1,16 @@ +"2012-02-13T09:00:00","NOW","" +"1999-06-03T09:45:00","ASAP","" +"2008-12-21T13:00:00","ASAP","" +"2008-12-21T14:50:00","ASAP","" +"2025-02-03T16:00:00","EOW","" +"1997-04-29T10:50:00","EOW","" +"2005-09-14T11:00:00","EOW","" +"2011-05-19T08:30:00","EOW","" +"2022-08-05T14:00:00","EOW","" +"2008-02-25T10:30:00","EOW","" +"2007-01-02T14:15:00","2M","" +"2013-11-21T15:30:00","11M","" +"2019-11-18T15:15:00","4M","" +"2003-01-01T10:45:00","Q1","" +"2001-04-09T09:00:00","Q4","" +"2022-10-06T11:00:00","Q3","" diff --git a/exercises/practice/swift-scheduling/swift-scheduling.sql b/exercises/practice/swift-scheduling/swift-scheduling.sql new file mode 100644 index 0000000..6c3100d --- /dev/null +++ b/exercises/practice/swift-scheduling/swift-scheduling.sql @@ -0,0 +1,8 @@ +-- Schema: +-- CREATE TABLE "swift-scheduling" ( +-- meeting_start TEXT NOT NULL, -- datetime YYYY-MM-DDTHH:mm:ss +-- date_description TEXT NOT NULL, +-- result TEXT -- datetime YYYY-MM-DDTHH:mm:ss +-- ); +-- +-- Task: update swift-scheduling table and set the result based on the meeting_start and description. diff --git a/exercises/practice/swift-scheduling/swift-scheduling_test.sql b/exercises/practice/swift-scheduling/swift-scheduling_test.sql new file mode 100644 index 0000000..e272989 --- /dev/null +++ b/exercises/practice/swift-scheduling/swift-scheduling_test.sql @@ -0,0 +1,40 @@ +-- Create database: +.read ./create_fixture.sql + +-- Read user student solution and save any output as markdown in user_output.md: +.mode markdown +.output user_output.md +.read ./swift-scheduling.sql +.output + +-- Create a clean testing environment: +.read ./create_test_table.sql + +-- Comparison of user input and the tests updates the status for each test: +UPDATE tests +SET status = 'pass' +FROM (SELECT meeting_start, date_description, result FROM "swift-scheduling") AS actual +WHERE (actual.meeting_start, actual.date_description, actual.result) = (tests.meeting_start, tests.date_description, tests.expected); + +-- Update message for failed tests to give helpful information: +UPDATE tests +SET message = ( + 'Result for "' + || tests.meeting_start || ', ' || tests.date_description + || '"' + || ' is <' || COALESCE(actual.result, 'NULL') + || '> but should be <' || tests.expected || '>' +) +FROM (SELECT meeting_start, date_description, result FROM "swift-scheduling") AS actual +WHERE (actual.meeting_start, actual.date_description) = (tests.meeting_start, tests.date_description) AND tests.status = 'fail'; + +-- Save results to ./output.json (needed by the online test-runner) +.mode json +.once './output.json' +SELECT description, status, message, output, test_code, task_id +FROM tests; + +-- Display test results in readable form for the student: +.mode table +SELECT description, status, message +FROM tests;