|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE puzzles ( |
|
|
puzzle_number INT PRIMARY KEY, |
|
|
|
|
|
|
|
|
answer_word VARCHAR(100) NOT NULL, |
|
|
|
|
|
|
|
|
difficulty VARCHAR(20), |
|
|
category VARCHAR(50), |
|
|
|
|
|
|
|
|
puzzle_date DATE NOT NULL UNIQUE, |
|
|
|
|
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
|
|
|
CONSTRAINT positive_puzzle_number CHECK (puzzle_number > 0) |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_puzzle_date ON puzzles(puzzle_date); |
|
|
|
|
|
COMMENT ON TABLE puzzles IS '์ผ์ผ ํผ์ฆ ์ ๋ณด - ์ ๋ต ๋จ์ด'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE guess_records ( |
|
|
|
|
|
id BIGSERIAL PRIMARY KEY, |
|
|
|
|
|
|
|
|
session_id VARCHAR(100) NOT NULL, |
|
|
puzzle_number INT NOT NULL, |
|
|
|
|
|
|
|
|
pitch DECIMAL(5, 2), |
|
|
rhythm DECIMAL(5, 2), |
|
|
energy DECIMAL(5, 2), |
|
|
pronunciation DECIMAL(5, 2), |
|
|
transcript TEXT, |
|
|
user_text TEXT, |
|
|
overall DECIMAL(5, 2), |
|
|
advice TEXT, |
|
|
|
|
|
|
|
|
is_correct BOOLEAN DEFAULT FALSE, |
|
|
|
|
|
|
|
|
guess_timestamp BIGINT NOT NULL, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
|
|
|
CONSTRAINT pitch_range CHECK (pitch IS NULL OR (pitch >= 0 AND pitch <= 100)), |
|
|
CONSTRAINT rhythm_range CHECK (rhythm IS NULL OR (rhythm >= 0 AND rhythm <= 100)), |
|
|
CONSTRAINT energy_range CHECK (energy IS NULL OR (energy >= 0 AND energy <= 100)), |
|
|
CONSTRAINT pronunciation_range CHECK (pronunciation IS NULL OR (pronunciation >= 0 AND pronunciation <= 100)), |
|
|
CONSTRAINT overall_range CHECK (overall IS NULL OR (overall >= 0 AND overall <= 100)) |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX idx_guess_session ON guess_records(session_id); |
|
|
CREATE INDEX idx_guess_puzzle ON guess_records(puzzle_number); |
|
|
CREATE INDEX idx_guess_created ON guess_records(created_at); |
|
|
CREATE INDEX idx_guess_correct ON guess_records(is_correct); |
|
|
CREATE INDEX idx_guess_overall ON guess_records(overall); |
|
|
|
|
|
COMMENT ON TABLE guess_records IS '์ฌ์ฉ์ ์ถ์ธก ๊ธฐ๋ก - AI ๋ถ์ ๊ฒฐ๊ณผ๋ง ์ ์ฅ (์์ฑ ํ์ผ ์์)'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE OR REPLACE VIEW daily_statistics AS |
|
|
SELECT |
|
|
p.puzzle_date, |
|
|
|
|
|
|
|
|
COUNT(DISTINCT gr.session_id) as participants, |
|
|
|
|
|
|
|
|
COUNT(DISTINCT CASE WHEN gr.is_correct = true THEN gr.session_id END) as winners, |
|
|
|
|
|
|
|
|
ROUND( |
|
|
CASE |
|
|
WHEN COUNT(DISTINCT gr.session_id) > 0 |
|
|
THEN (COUNT(DISTINCT CASE WHEN gr.is_correct = true THEN gr.session_id END)::NUMERIC |
|
|
/ COUNT(DISTINCT gr.session_id) * 100) |
|
|
ELSE 0 |
|
|
END, |
|
|
1 |
|
|
) as success_rate, |
|
|
|
|
|
|
|
|
COUNT(*) as total_attempts, |
|
|
|
|
|
|
|
|
ROUND( |
|
|
CASE |
|
|
WHEN COUNT(DISTINCT gr.session_id) > 0 |
|
|
THEN COUNT(*)::NUMERIC / COUNT(DISTINCT gr.session_id) |
|
|
ELSE 0 |
|
|
END, |
|
|
1 |
|
|
) as avg_attempts_per_user |
|
|
|
|
|
FROM puzzles p |
|
|
LEFT JOIN guess_records gr ON p.puzzle_number = gr.puzzle_number |
|
|
GROUP BY p.puzzle_date |
|
|
ORDER BY p.puzzle_date DESC; |
|
|
|
|
|
COMMENT ON VIEW daily_statistics IS '๋ ์ง๋ณ ์ ์ฒด ๊ฒ์ ํต๊ณ - ๋์๋ณด๋์ฉ'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE OR REPLACE VIEW overall_statistics AS |
|
|
SELECT |
|
|
|
|
|
COUNT(DISTINCT session_id) as total_participants, |
|
|
|
|
|
|
|
|
COUNT(DISTINCT CASE WHEN is_correct = true THEN session_id END) as total_winners, |
|
|
|
|
|
|
|
|
ROUND( |
|
|
CASE |
|
|
WHEN COUNT(DISTINCT session_id) > 0 |
|
|
THEN (COUNT(DISTINCT CASE WHEN is_correct = true THEN session_id END)::NUMERIC |
|
|
/ COUNT(DISTINCT session_id) * 100) |
|
|
ELSE 0 |
|
|
END, |
|
|
1 |
|
|
) as overall_success_rate, |
|
|
|
|
|
|
|
|
COUNT(*) as total_attempts, |
|
|
|
|
|
|
|
|
(SELECT COUNT(*) FROM puzzles) as total_puzzles, |
|
|
|
|
|
|
|
|
ROUND( |
|
|
CASE |
|
|
WHEN COUNT(DISTINCT session_id) > 0 |
|
|
THEN COUNT(*)::NUMERIC / COUNT(DISTINCT session_id) |
|
|
ELSE 0 |
|
|
END, |
|
|
1 |
|
|
) as avg_attempts_per_user |
|
|
|
|
|
FROM guess_records; |
|
|
|
|
|
COMMENT ON VIEW overall_statistics IS '์ ์ฒด ๋์ ๊ฒ์ ํต๊ณ - ๋์๋ณด๋์ฉ'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE OR REPLACE VIEW user_statistics AS |
|
|
WITH |
|
|
daily_activity AS ( |
|
|
SELECT |
|
|
gr.session_id, |
|
|
p.puzzle_date, |
|
|
COUNT(*) as attempts, |
|
|
MAX(CASE WHEN gr.is_correct = true THEN 1 ELSE 0 END) as won |
|
|
FROM guess_records gr |
|
|
JOIN puzzles p ON gr.puzzle_number = p.puzzle_number |
|
|
GROUP BY gr.session_id, p.puzzle_date |
|
|
), |
|
|
streaks AS ( |
|
|
SELECT |
|
|
session_id, |
|
|
puzzle_date, |
|
|
won, |
|
|
puzzle_date - (ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY puzzle_date))::int AS play_streak_group |
|
|
FROM daily_activity |
|
|
), |
|
|
current_play_streak AS ( |
|
|
SELECT |
|
|
session_id, |
|
|
COUNT(*) as play_streak |
|
|
FROM streaks |
|
|
WHERE play_streak_group = ( |
|
|
SELECT play_streak_group |
|
|
FROM streaks s2 |
|
|
WHERE s2.session_id = streaks.session_id |
|
|
ORDER BY puzzle_date DESC |
|
|
LIMIT 1 |
|
|
) |
|
|
GROUP BY session_id |
|
|
), |
|
|
win_streaks AS ( |
|
|
SELECT |
|
|
session_id, |
|
|
COUNT(*) as win_streak |
|
|
FROM ( |
|
|
SELECT |
|
|
session_id, |
|
|
puzzle_date, |
|
|
won, |
|
|
SUM(CASE WHEN won = 0 THEN 1 ELSE 0 END) |
|
|
OVER (PARTITION BY session_id ORDER BY puzzle_date DESC) as loss_count |
|
|
FROM daily_activity |
|
|
) ws |
|
|
WHERE loss_count = 0 AND won = 1 |
|
|
GROUP BY session_id |
|
|
) |
|
|
SELECT |
|
|
da.session_id, |
|
|
COUNT(DISTINCT da.puzzle_date) as total_plays, |
|
|
SUM(da.attempts) as total_attempts, |
|
|
SUM(da.won) as wins, |
|
|
ROUND( |
|
|
CASE |
|
|
WHEN COUNT(DISTINCT da.puzzle_date) > 0 |
|
|
THEN (SUM(da.won)::NUMERIC / COUNT(DISTINCT da.puzzle_date) * 100) |
|
|
ELSE 0 |
|
|
END, |
|
|
1 |
|
|
) as win_rate, |
|
|
COALESCE(cps.play_streak, 0) as play_streak, |
|
|
COALESCE(ws.win_streak, 0) as win_streak |
|
|
FROM daily_activity da |
|
|
LEFT JOIN current_play_streak cps ON da.session_id = cps.session_id |
|
|
LEFT JOIN win_streaks ws ON da.session_id = ws.session_id |
|
|
GROUP BY da.session_id, cps.play_streak, ws.win_streak; |
|
|
|
|
|
COMMENT ON VIEW user_statistics IS '๊ฐ๋ณ ์ฌ์ฉ์ ๊ฒ์ ํต๊ณ'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INSERT INTO puzzles (puzzle_number, answer_word, puzzle_date, difficulty, category) |
|
|
VALUES |
|
|
(1, 'Tralalero Tralala', '2024-11-24', 'easy', 'meme'), |
|
|
(2, 'Wingardium Leviosa', '2024-11-25', 'medium', 'movie'), |
|
|
(3, 'Baby shark, doo doo doo doo doo doo', '2024-11-26', 'hard', 'song'); |
|
|
|