-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpokesector_database.sql
More file actions
145 lines (126 loc) · 5.95 KB
/
Copy pathpokesector_database.sql
File metadata and controls
145 lines (126 loc) · 5.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
-- ============================================================================
-- POKÉSECTOR 35 — SCRIPT SQL PARA POSTGRESQL (VERSIÓN FINAL)
-- ============================================================================
-- Este archivo crea todas las tablas necesarias para el backend.
-- Incluye borrado lógico (soft delete) de usuarios.
-- ============================================================================
-- Eliminar tablas si existen (útil para limpiar la BD durante desarrollo)
DROP TABLE IF EXISTS captured_pokemon CASCADE;
DROP TABLE IF EXISTS ranking CASCADE;
DROP TABLE IF EXISTS game_slots CASCADE;
DROP TABLE IF EXISTS users CASCADE;
-- ============================================================================
-- TABLA 1: USERS
-- ============================================================================
-- Almacena los jugadores registrados del sistema.
-- username es único porque actúa como identificador.
-- role: 'user' para jugadores normales, 'admin' para administradores.
-- deleted_at: NULL si usuario estáactivo. Fecha si esá eliminado (borrado lógico).
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(15) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(10) NOT NULL DEFAULT 'user' CHECK (role IN ('user', 'admin')),
deleted_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================================
-- TABLA 2: GAME_SLOTS
-- ============================================================================
-- Almacena las partidas guardadas de cada usuario (máximo 3 slots por usuario).
-- Solo los usuarios REGISTRADOS pueden guardar partidas aquí.
-- Los anónimos guardan en localStorage (NO en BD).
CREATE TABLE game_slots (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
slot_number INTEGER NOT NULL CHECK (slot_number IN (1, 2, 3)),
explorer VARCHAR(50) NOT NULL,
explorer_name VARCHAR(30),
color VARCHAR(7) NOT NULL,
difficulty_id VARCHAR(20) NOT NULL,
hp INTEGER NOT NULL DEFAULT 10,
pokeball INTEGER NOT NULL DEFAULT 20,
position_r INTEGER NOT NULL DEFAULT 0,
position_c INTEGER NOT NULL DEFAULT 0,
is_game_over BOOLEAN NOT NULL DEFAULT FALSE,
is_goal BOOLEAN NOT NULL DEFAULT FALSE,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, slot_number)
);
-- ============================================================================
-- TABLA 3: CAPTURED_POKEMON
-- ============================================================================
-- Almacena cada captura individual realizada por el usuario registrado.
CREATE TABLE captured_pokemon (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
slot_id INTEGER REFERENCES game_slots(id) ON DELETE SET NULL,
pokemon_id INTEGER NOT NULL,
pokemon_name VARCHAR(50) NOT NULL,
is_global BOOLEAN NOT NULL DEFAULT FALSE,
captured_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================================
-- TABLA 4: RANKING
-- ============================================================================
-- Almacena UNA entrada por partida completada (al llegar a meta o perder).
CREATE TABLE ranking (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
captured_count INTEGER NOT NULL,
escaped_count INTEGER NOT NULL,
difficulty_id VARCHAR(20) NOT NULL,
completed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================================
-- TABLA 5: REFRESH_TOKENS
-- ============================================================================
-- Almacena los refresh tokens para renovar access tokens.
CREATE TABLE refresh_tokens (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token VARCHAR(500) NOT NULL UNIQUE,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id);
-- ============================================================================
-- TABLA 6: GAME_REPLAY
-- ============================================================================
-- Almacena el replay completo de una partida completada (array de movimientos).
-- Los movimientos se recopilan en localStorage mientras se juega.
-- Al terminar la partida, se guarda el array completo de movimientos aquí.
-- Útil para análisis de datos, mapas de calor y mejora de mapas.
CREATE TABLE game_replay (
id SERIAL PRIMARY KEY,
slot_id INTEGER REFERENCES game_slots(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
movements JSON NOT NULL,
completed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_game_replay_user_id ON game_replay(user_id);
CREATE INDEX idx_game_replay_slot_id ON game_replay(slot_id);
-- ============================================================================
-- VIEW: RANKING_VIEW
-- ============================================================================
-- Vista que combina datos de ranking + usuarios para mostrar el ranking.
-- Muestra: usuario, pokémon capturados, pokémon escapados, dificultad y fecha.
-- Se usa para mostrar el ranking en la pantalla del juego.
-- El porcentaje de captura se calcula en el backend (JavaScript), no aquí.
-- Para el proyecto con React:
-- Más Pokémon capturados por dificultad
-- Mejor % captura/encuentros por dificultad (mínimo de 10 encuentro por partida)
CREATE VIEW ranking_view AS
SELECT
r.id,
r.user_id,
u.username,
r.captured_count,
r.escaped_count,
r.difficulty_id,
r.completed_at
FROM ranking r
JOIN users u ON r.user_id = u.id
WHERE u.deleted_at IS NULL
AND (r.captured_count + r.escaped_count) >= 10
ORDER BY r.difficulty_id, r.captured_count DESC;