Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 106 additions & 56 deletions exercises/practice/high-scores/.meta/example.sql
Original file line number Diff line number Diff line change
@@ -1,69 +1,119 @@
-- store comma-separated list of scores of a game
UPDATE results
SET result = score_groups.scores
FROM (
SELECT game_id, GROUP_CONCAT(score) "scores"
FROM (
SELECT scores.game_id, score
FROM scores
INNER JOIN results USING (game_id)
WHERE results.property = 'scores'
ORDER BY scores.rowid
) scores_by_game_id
GROUP BY game_id
) score_groups
WHERE results.game_id = score_groups.game_id;
SET
result = score_groups.scores
FROM
(
SELECT
game_id,
GROUP_CONCAT(score) "scores"
FROM
(
SELECT
scores.game_id,
score
FROM
scores
INNER JOIN results USING (game_id)
WHERE
results.property = 'scores'
ORDER BY
scores.rowid
) scores_by_game_id
GROUP BY
game_id
) score_groups
WHERE
results.game_id = score_groups.game_id;

-- store the latest score by game
UPDATE results
SET result = latest_score.score
FROM (
SELECT scores.game_id, score
FROM scores
INNER JOIN (
SELECT scores.game_id, MAX(scores.rowid) "last_row"
FROM scores
INNER JOIN results USING (game_id)
WHERE results.property = 'latest'
GROUP BY scores.game_id
) latest USING (game_id)
WHERE scores.rowid = latest.last_row
) latest_score
WHERE results.game_id = latest_score.game_id;
SET
result = latest_score.score
FROM
(
SELECT
scores.game_id,
score
FROM
scores
INNER JOIN (
SELECT
scores.game_id,
MAX(scores.rowid) "last_row"
FROM
scores
INNER JOIN results USING (game_id)
WHERE
results.property = 'latest'
GROUP BY
scores.game_id
) latest USING (game_id)
WHERE
scores.rowid = latest.last_row
) latest_score
WHERE
results.game_id = latest_score.game_id;

-- the largest score by game
UPDATE results
SET result = best_score.best
FROM (
SELECT scores.game_id, max(score) "best"
FROM scores
INNER JOIN results USING (game_id)
WHERE results.property = 'personalBest'
GROUP BY scores.game_id
) best_score
WHERE results.game_id = best_score.game_id;
SET
result = best_score.best
FROM
(
SELECT
scores.game_id,
max(score) "best"
FROM
scores
INNER JOIN results USING (game_id)
WHERE
results.property = 'personalBest'
GROUP BY
scores.game_id
) best_score
WHERE
results.game_id = best_score.game_id;

-- for personalTopThree, sort scores descending by game
DROP TABLE IF EXISTS reversed;
CREATE TEMP TABLE reversed AS
SELECT scores.game_id, score
FROM scores
INNER JOIN results USING (game_id)
WHERE results.property = 'personalTopThree'
ORDER BY scores.game_id ASC, score DESC
;

CREATE TEMP TABLE reversed AS
SELECT
scores.game_id,
score
FROM
scores
INNER JOIN results USING (game_id)
WHERE
results.property = 'personalTopThree'
ORDER BY
scores.game_id ASC,
score DESC;

UPDATE results
SET result = top_three_scores.top_three
FROM (
SELECT reversed.game_id, GROUP_CONCAT(reversed.score) "top_three"
FROM reversed
INNER JOIN (
SELECT game_id, MIN(rowid) "first_row"
FROM reversed
GROUP BY game_id
) min_row USING (game_id)
WHERE reversed.rowid < min_row.first_row + 3
GROUP BY reversed.game_id
) top_three_scores
WHERE results.game_id = top_three_scores.game_id;
SET
result = top_three_scores.top_three
FROM
(
SELECT
reversed.game_id,
GROUP_CONCAT(reversed.score) "top_three"
FROM
reversed
INNER JOIN (
SELECT
game_id,
MIN(rowid) "first_row"
FROM
reversed
GROUP BY
game_id
) min_row USING (game_id)
WHERE
reversed.rowid < min_row.first_row + 3
GROUP BY
reversed.game_id
) top_three_scores
WHERE
results.game_id = top_three_scores.game_id;
13 changes: 4 additions & 9 deletions exercises/practice/high-scores/create_fixture.sql
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
DROP TABLE IF EXISTS "scores";
CREATE TABLE "scores" (
"game_id" TEXT,
"score" INT
);

CREATE TABLE "scores" ("game_id" TEXT, "score" INT);

DROP TABLE IF EXISTS "results";
CREATE TABLE "results" (
"game_id" TEXT,
"property" TEXT,
"result" TEXT
);

CREATE TABLE "results" ("game_id" TEXT, "property" TEXT, "result" TEXT);

.mode csv
.import ./data_scores.csv scores
Expand Down
1 change: 0 additions & 1 deletion exercises/practice/high-scores/high-scores.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
-- Schema:
-- CREATE TABLE "scores" ("game_id" TEXT, "score" INT);
-- CREATE TABLE "results" ("game_id" TEXT, "property" TEXT, "result" TEXT);

-- Task: Given the data in the "scores" table, update the "result" field in the "results" table.
131 changes: 99 additions & 32 deletions exercises/practice/high-scores/high-scores_test.sql
Original file line number Diff line number Diff line change
@@ -1,42 +1,109 @@
-- Setup test table and read in student solution:
.read ./test_setup.sql

-- Test cases:
-- Note: the strings below may contain literal tab, newline, carriage returns.

INSERT INTO tests (name, uuid,
function, input, expected)
VALUES
('List of scores', '1035eb93-2208-4c22-bab8-fef06769a73c',
'scores', '30,50,20,70', '30,50,20,70'),
('Latest score', '6aa5dbf5-78fa-4375-b22c-ffaa989732d2',
'latest', '100,0,90,30',30),
('Personal best', 'b661a2e1-aebf-4f50-9139-0fb817dd12c6',
'personalBest', '40,100,70',100),
('Personal top three from a list of scores', '3d996a97-c81c-4642-9afc-80b80dc14015',
'personalTopThree', '10,30,90,30,100,20,10,0,30,40,40,70,70', '100,90,70'),
('Personal top highest to lowest', '1084ecb5-3eb4-46fe-a816-e40331a4e83a',
'personalTopThree', '20,10,30', '30,20,10'),
('Personal top when there is a tie', 'e6465b6b-5a11-4936-bfe3-35241c4f4f16',
'personalTopThree', '40,20,40,30', '40,40,30'),
('Personal top when there are less than 3', 'f73b02af-c8fd-41c9-91b9-c86eaa86bce2',
'personalTopThree', '30,70', '70,30'),
('Personal top when there is only one', '16608eae-f60f-4a88-800e-aabce5df2865',
'personalTopThree', '40', '40'),
('Latest score after personal top scores', '2df075f9-fec9-4756-8f40-98c52a11504f',
'latest', '70,50,20,30', '30'),
('Scores after personal top scores', '809c4058-7eb1-4206-b01e-79238b9b71bc',
'scores', '30,50,20,70', '30,50,20,70'),
('Latest score after personal best', 'ddb0efc0-9a86-4f82-bc30-21ae0bdc6418',
'latest', '20,70,15,25,30', '30'),
('Scores after personal best', '6a0fd2d1-4cc4-46b9-a5bb-2fb667ca2364',
'scores', '20,70,15,25,30', '20,70,15,25,30');
INSERT INTO
tests (name, uuid, function, input, expected)
VALUES
(
'List of scores',
'1035eb93-2208-4c22-bab8-fef06769a73c',
'scores',
'30,50,20,70',
'30,50,20,70'
),
(
'Latest score',
'6aa5dbf5-78fa-4375-b22c-ffaa989732d2',
'latest',
'100,0,90,30',
30
),
(
'Personal best',
'b661a2e1-aebf-4f50-9139-0fb817dd12c6',
'personalBest',
'40,100,70',
100
),
(
'Personal top three from a list of scores',
'3d996a97-c81c-4642-9afc-80b80dc14015',
'personalTopThree',
'10,30,90,30,100,20,10,0,30,40,40,70,70',
'100,90,70'
),
(
'Personal top highest to lowest',
'1084ecb5-3eb4-46fe-a816-e40331a4e83a',
'personalTopThree',
'20,10,30',
'30,20,10'
),
(
'Personal top when there is a tie',
'e6465b6b-5a11-4936-bfe3-35241c4f4f16',
'personalTopThree',
'40,20,40,30',
'40,40,30'
),
(
'Personal top when there are less than 3',
'f73b02af-c8fd-41c9-91b9-c86eaa86bce2',
'personalTopThree',
'30,70',
'70,30'
),
(
'Personal top when there is only one',
'16608eae-f60f-4a88-800e-aabce5df2865',
'personalTopThree',
'40',
'40'
),
(
'Latest score after personal top scores',
'2df075f9-fec9-4756-8f40-98c52a11504f',
'latest',
'70,50,20,30',
'30'
),
(
'Scores after personal top scores',
'809c4058-7eb1-4206-b01e-79238b9b71bc',
'scores',
'30,50,20,70',
'30,50,20,70'
),
(
'Latest score after personal best',
'ddb0efc0-9a86-4f82-bc30-21ae0bdc6418',
'latest',
'20,70,15,25,30',
'30'
),
(
'Scores after personal best',
'6a0fd2d1-4cc4-46b9-a5bb-2fb667ca2364',
'scores',
'20,70,15,25,30',
'20,70,15,25,30'
);

-- Comparison of user input and the tests updates the status for each test:
UPDATE tests
SET status = 'pass'
FROM (SELECT game_id, result FROM results) AS actual
WHERE (actual.game_id, actual.result) = (tests.uuid, tests.expected);
SET
status = 'pass'
FROM
(
SELECT
game_id,
result
FROM
results
) AS actual
WHERE
(actual.game_id, actual.result) = (tests.uuid, tests.expected);

-- Write results and debug info:
.read ./test_reporter.sql
41 changes: 30 additions & 11 deletions exercises/practice/high-scores/test_reporter.sql
Original file line number Diff line number Diff line change
@@ -1,20 +1,39 @@
-- Update message for failed tests to give helpful information:
UPDATE tests
SET message = (
'Result for "' || tests.name || '"'
|| ' is <' || COALESCE(actual.result, 'NULL')
|| '> but should be <' || tests.expected || '>'
)
FROM (SELECT game_id, result FROM results) AS actual
WHERE actual.game_id = tests.uuid AND tests.status = 'fail';
SET
message = (
'Result for "' || tests.name || '"' || ' is <' || COALESCE(actual.result, 'NULL') || '> but should be <' || tests.expected || '>'
)
FROM
(
SELECT
game_id,
result
FROM
results
) AS actual
WHERE
actual.game_id = tests.uuid
AND tests.status = 'fail';

-- Save results to ./output.json (needed by the online test-runner)
.mode json
.once './output.json'
SELECT name, status, message, output, test_code, task_id
FROM tests;
SELECT
name,
status,
message,
output,
test_code,
task_id
FROM
tests;

-- Display test results in readable form for the student:
.mode table
SELECT name, status, message
FROM tests;
SELECT
name,
status,
message
FROM
tests;
Loading