|
|
@ -69,21 +69,36 @@ init_db(Database) ->
|
|
|
|
{division, text},
|
|
|
|
{division, text},
|
|
|
|
{other, text}],
|
|
|
|
{other, text}],
|
|
|
|
[{primary_key, [field]},
|
|
|
|
[{primary_key, [field]},
|
|
|
|
{foreign_key, {[division], divisions, [division], "ON DELETE SET NULL"}},
|
|
|
|
% Clear divisions that are deleted
|
|
|
|
|
|
|
|
{foreign_key, {[division],
|
|
|
|
|
|
|
|
divisions,
|
|
|
|
|
|
|
|
[division],
|
|
|
|
|
|
|
|
"ON DELETE SET NULL
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
{check, "other IN ('testing', 'skills')"}]),
|
|
|
|
{check, "other IN ('testing', 'skills')"}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, teams, [{team, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, teams, [{team, text, [not_null]},
|
|
|
|
{division, text},
|
|
|
|
{division, text},
|
|
|
|
{inspection, blob}],
|
|
|
|
{inspection, blob}],
|
|
|
|
[{primary_key, [team]},
|
|
|
|
[{primary_key, [team]},
|
|
|
|
{foreign_key, {[division], divisions, [division], "ON DELETE SET NULL"}}]),
|
|
|
|
% Clear divisions that are deleted
|
|
|
|
|
|
|
|
{foreign_key, {[division],
|
|
|
|
|
|
|
|
divisions,
|
|
|
|
|
|
|
|
[division],
|
|
|
|
|
|
|
|
"ON DELETE SET NULL
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, matches, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, matches, [{division, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
|
{number, integer, [not_null]}],
|
|
|
|
{number, integer, [not_null]}],
|
|
|
|
[{primary_key, [division, type, number]},
|
|
|
|
[{primary_key, [division, type, number]},
|
|
|
|
{check, "type IN ('practice', 'qualification')"},
|
|
|
|
{check, "type IN ('practice', 'qualification')"},
|
|
|
|
{foreign_key, {[division], divisions, [division], "ON DELETE CASCADE"}}]),
|
|
|
|
% Delete matches when division deleted
|
|
|
|
|
|
|
|
{foreign_key, {[division],
|
|
|
|
|
|
|
|
divisions,
|
|
|
|
|
|
|
|
[division],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, match_states, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, match_states, [{division, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
@ -91,7 +106,12 @@ init_db(Database) ->
|
|
|
|
{tick, integer, [not_null]},
|
|
|
|
{tick, integer, [not_null]},
|
|
|
|
{state, text, [not_null]}],
|
|
|
|
{state, text, [not_null]}],
|
|
|
|
[{primary_key, [division, type, number, tick]},
|
|
|
|
[{primary_key, [division, type, number, tick]},
|
|
|
|
{foreign_key, {[division, type, number], matches, [division, type, number], "ON DELETE CASCADE"}}]),
|
|
|
|
% Delete states when match deleted
|
|
|
|
|
|
|
|
{foreign_key, {[division, type, number],
|
|
|
|
|
|
|
|
matches,
|
|
|
|
|
|
|
|
[division, type, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, match_teams, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, match_teams, [{division, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
@ -103,8 +123,18 @@ init_db(Database) ->
|
|
|
|
{check, "side IN ('red', 'blue')"},
|
|
|
|
{check, "side IN ('red', 'blue')"},
|
|
|
|
{check, "anum >= 1 AND anum <= 2"},
|
|
|
|
{check, "anum >= 1 AND anum <= 2"},
|
|
|
|
{check, "type IN ('practice', 'qualification')"},
|
|
|
|
{check, "type IN ('practice', 'qualification')"},
|
|
|
|
{foreign_key, {[division, type, number], matches, [division, type, number], "ON DELETE CASCADE"}},
|
|
|
|
% Delete team associations when match deleted
|
|
|
|
{foreign_key, {[team], teams, [team], ""}}]),
|
|
|
|
{foreign_key, {[division, type, number],
|
|
|
|
|
|
|
|
matches,
|
|
|
|
|
|
|
|
[division, type, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
|
|
|
|
% Restrict team from being deleted that's associated with a match
|
|
|
|
|
|
|
|
{foreign_key, {[team],
|
|
|
|
|
|
|
|
teams,
|
|
|
|
|
|
|
|
[team],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, match_scores, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, match_scores, [{division, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
@ -112,54 +142,103 @@ init_db(Database) ->
|
|
|
|
{history, integer, [not_null]},
|
|
|
|
{history, integer, [not_null]},
|
|
|
|
{uuid, integer, [not_null]}],
|
|
|
|
{uuid, integer, [not_null]}],
|
|
|
|
[{primary_key, [division, type, number, history]},
|
|
|
|
[{primary_key, [division, type, number, history]},
|
|
|
|
{foreign_key, {[uuid], scores, [uuid], "ON DELETE CASCADE"}},
|
|
|
|
% Restrict scores from being deleted that are referenced
|
|
|
|
|
|
|
|
{foreign_key, {[uuid],
|
|
|
|
|
|
|
|
scores,
|
|
|
|
|
|
|
|
[uuid],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
|
|
|
|
% Restrict matches from being deleted that are scored
|
|
|
|
{foreign_key, {[division, type, number],
|
|
|
|
{foreign_key, {[division, type, number],
|
|
|
|
matches,
|
|
|
|
matches,
|
|
|
|
[division, type, number],
|
|
|
|
[division, type, number],
|
|
|
|
"ON DELETE CASCADE"}}]),
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, brackets, [{division, text},
|
|
|
|
ok = sqlite3:create_table(Database, brackets, [{division, text},
|
|
|
|
|
|
|
|
{stage, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]}],
|
|
|
|
{number, integer, [not_null]}],
|
|
|
|
[{primary_key, [division, number]},
|
|
|
|
[{primary_key, [division, stage, number]},
|
|
|
|
{foreign_key, {[division], divisions, [division], "ON DELETE CASCADE"}}]),
|
|
|
|
% Delete brackets when division deleted
|
|
|
|
|
|
|
|
{foreign_key, {[division],
|
|
|
|
|
|
|
|
divisions,
|
|
|
|
|
|
|
|
[division],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, bracket_states, [{division, text},
|
|
|
|
ok = sqlite3:create_table(Database, bracket_states, [{division, text},
|
|
|
|
|
|
|
|
{stage, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{tick, integer, [not_null]},
|
|
|
|
{tick, integer, [not_null]},
|
|
|
|
{state, text, [not_null]}],
|
|
|
|
{state, text, [not_null]}],
|
|
|
|
[{primary_key, [division, number, tick]},
|
|
|
|
[{primary_key, [division, stage, number, tick]},
|
|
|
|
{foreign_key, {[division, number], brackets, [division, number], "ON DELETE CASCADE"}}]),
|
|
|
|
% Delete states when bracket deleted
|
|
|
|
|
|
|
|
{foreign_key, {[division, stage, number],
|
|
|
|
|
|
|
|
brackets,
|
|
|
|
|
|
|
|
[division, stage, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, elimination_alliances, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, elimination_alliances, [{division, text, [not_null]},
|
|
|
|
|
|
|
|
{stage, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{side, text, [not_null]},
|
|
|
|
{side, text, [not_null]},
|
|
|
|
{anum, integer, [not_null]}],
|
|
|
|
{anum, integer, [not_null]}],
|
|
|
|
[{primary_key, [division, number, side]},
|
|
|
|
[{primary_key, [division, stage, number, side]},
|
|
|
|
{check, "side IN ('red', 'blue')"},
|
|
|
|
{check, "side IN ('red', 'blue')"},
|
|
|
|
{foreign_key, {[division, number], brackets, [division, number], "ON DELETE CASCADE"}},
|
|
|
|
% Delete alliance associations when bracket deleted
|
|
|
|
{foreign_key, {[division, anum], alliances, [division, number], ""}}]),
|
|
|
|
{foreign_key, {[division, stage, number],
|
|
|
|
|
|
|
|
brackets,
|
|
|
|
|
|
|
|
[division, stage, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
|
|
|
|
% Restrict alliance from being deleted that's associated with a bracket
|
|
|
|
|
|
|
|
{foreign_key, {[division, anum],
|
|
|
|
|
|
|
|
alliances,
|
|
|
|
|
|
|
|
[division, number],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, finals_alliances, [{division, text},
|
|
|
|
ok = sqlite3:create_table(Database, finals_alliances, [{division, text},
|
|
|
|
|
|
|
|
{stage, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{side, text, [not_null]},
|
|
|
|
{side, text, [not_null]},
|
|
|
|
{adiv, text, [not_null]}],
|
|
|
|
{adiv, text, [not_null]}],
|
|
|
|
[{primary_key, [division, number, side]},
|
|
|
|
[{primary_key, [division, stage, number, side]},
|
|
|
|
{check, "side IN ('red', 'blue')"},
|
|
|
|
{check, "side IN ('red', 'blue')"},
|
|
|
|
{check, "division IS NULL"},
|
|
|
|
{check, "division IS NULL"},
|
|
|
|
{foreign_key, {[division, number], brackets, [division, number], "ON DELETE CASCADE"}},
|
|
|
|
% Delete alliance associations when bracket deleted
|
|
|
|
{foreign_key, {[adiv], winners, [division], ""}}]),
|
|
|
|
{foreign_key, {[division, stage, number],
|
|
|
|
|
|
|
|
brackets,
|
|
|
|
|
|
|
|
[division, stage, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
|
|
|
|
% Restrict winners from being deleted that's associated with a bracket
|
|
|
|
|
|
|
|
{foreign_key, {[adiv],
|
|
|
|
|
|
|
|
winners,
|
|
|
|
|
|
|
|
[division],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, bracket_scores, [{division, text},
|
|
|
|
ok = sqlite3:create_table(Database, bracket_scores, [{division, text},
|
|
|
|
|
|
|
|
{stage, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{instance, integer, [not_null]},
|
|
|
|
{instance, integer, [not_null]},
|
|
|
|
{history, integer, [not_null]},
|
|
|
|
{history, integer, [not_null]},
|
|
|
|
{uuid, integer, [not_null]}],
|
|
|
|
{uuid, integer, [not_null]}],
|
|
|
|
[{primary_key, [division, number, instance, history]},
|
|
|
|
[{primary_key, [division, number, instance, history]},
|
|
|
|
{foreign_key, {[uuid], scores, [uuid], "ON DELETE CASCADE"}},
|
|
|
|
% Restrict scores from being deleted that are referenced
|
|
|
|
{foreign_key, {[division, number],
|
|
|
|
{foreign_key, {[uuid],
|
|
|
|
|
|
|
|
scores,
|
|
|
|
|
|
|
|
[uuid],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
|
|
|
|
% Restrict brackets from being deleted that are scored
|
|
|
|
|
|
|
|
{foreign_key, {[division, stage, number],
|
|
|
|
brackets,
|
|
|
|
brackets,
|
|
|
|
[division, number],
|
|
|
|
[division, stage, number],
|
|
|
|
"ON DELETE CASCADE"}}]),
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, scores, [{uuid, integer, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, scores, [{uuid, integer, [not_null]},
|
|
|
|
{autonomous, integer, [not_null]},
|
|
|
|
{autonomous, integer, [not_null]},
|
|
|
@ -188,20 +267,40 @@ init_db(Database) ->
|
|
|
|
ok = sqlite3:create_table(Database, alliances, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, alliances, [{division, text, [not_null]},
|
|
|
|
{number, integer, [not_null]}],
|
|
|
|
{number, integer, [not_null]}],
|
|
|
|
[{primary_key, [division, number]},
|
|
|
|
[{primary_key, [division, number]},
|
|
|
|
{foreign_key, {[division], divisions, [division], "ON DELETE CASCADE"}}]),
|
|
|
|
% Delete alliances when deleting division
|
|
|
|
|
|
|
|
{foreign_key, {[division],
|
|
|
|
|
|
|
|
divisions,
|
|
|
|
|
|
|
|
[division],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, alliance_members, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, alliance_members, [{division, text, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{number, integer, [not_null]},
|
|
|
|
{anum, integer, [not_null]},
|
|
|
|
{anum, integer, [not_null]},
|
|
|
|
{team, text, [not_null]}],
|
|
|
|
{team, text, [not_null]}],
|
|
|
|
[{primary_key, [division, number, anum]},
|
|
|
|
[{primary_key, [division, number, anum]},
|
|
|
|
{foreign_key, {[division, number], alliances, [division, number], "ON DELETE CASCADE"}},
|
|
|
|
% Delete alliance members when deleting alliances
|
|
|
|
{foreign_key, {[team], teams, [team], "ON DELETE CASCADE"}}]),
|
|
|
|
{foreign_key, {[division, number],
|
|
|
|
|
|
|
|
alliances,
|
|
|
|
|
|
|
|
[division, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}},
|
|
|
|
|
|
|
|
% Restrict teams being deleted that are in alliances
|
|
|
|
|
|
|
|
{foreign_key, {[team],
|
|
|
|
|
|
|
|
teams,
|
|
|
|
|
|
|
|
[team],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, winners, [{division, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, winners, [{division, text, [not_null]},
|
|
|
|
{alliance, integer, [not_null]}],
|
|
|
|
{alliance, integer, [not_null]}],
|
|
|
|
[{primary_key, [division]},
|
|
|
|
[{primary_key, [division]},
|
|
|
|
{foreign_key, {[division, alliance], alliances, [division, number], "ON DELETE CASCADE"}}]),
|
|
|
|
% Restrict divisions from being deleted that have winners
|
|
|
|
|
|
|
|
{foreign_key, {[division, alliance],
|
|
|
|
|
|
|
|
alliances,
|
|
|
|
|
|
|
|
[division, number],
|
|
|
|
|
|
|
|
"ON DELETE CASCADE
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
|
|
|
|
|
|
|
|
ok = sqlite3:create_table(Database, skills_scores, [{team, text, [not_null]},
|
|
|
|
ok = sqlite3:create_table(Database, skills_scores, [{team, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
|
{type, text, [not_null]},
|
|
|
@ -213,7 +312,12 @@ init_db(Database) ->
|
|
|
|
{azone, integer, [not_null]}],
|
|
|
|
{azone, integer, [not_null]}],
|
|
|
|
[{primary_key, [team, type, attempt]},
|
|
|
|
[{primary_key, [team, type, attempt]},
|
|
|
|
{check, "type IN ('driver', 'autonomous')"},
|
|
|
|
{check, "type IN ('driver', 'autonomous')"},
|
|
|
|
{foreign_key, {[team], teams, [team], ""}}]),
|
|
|
|
% Prevent teams being deleted that have skills scores
|
|
|
|
|
|
|
|
{foreign_key, {[team],
|
|
|
|
|
|
|
|
teams,
|
|
|
|
|
|
|
|
[team],
|
|
|
|
|
|
|
|
"ON DELETE RESTRICT
|
|
|
|
|
|
|
|
ON UPDATE CASCADE"}}]),
|
|
|
|
ok.
|
|
|
|
ok.
|
|
|
|
|
|
|
|
|
|
|
|
delete_teams(Database, Teams) ->
|
|
|
|
delete_teams(Database, Teams) ->
|
|
|
@ -405,11 +509,7 @@ handle_call({generate_elimination, Division, Size}, _, State) ->
|
|
|
|
io_lib:format("DELETE FROM brackets WHERE division = '~s'; ", [Division]),
|
|
|
|
io_lib:format("DELETE FROM brackets WHERE division = '~s'; ", [Division]),
|
|
|
|
lists:append([io_lib:format("INSERT INTO alliances(division, number) VALUES('~s', ~p); ",
|
|
|
|
lists:append([io_lib:format("INSERT INTO alliances(division, number) VALUES('~s', ~p); ",
|
|
|
|
[Division, N])
|
|
|
|
[Division, N])
|
|
|
|
|| N <- lists:seq(1, Size)]),
|
|
|
|
|| N <- lists:seq(1, Size)])]),
|
|
|
|
lists:append([io_lib:format("INSERT INTO brackets(division, number)
|
|
|
|
|
|
|
|
VALUES('~s', ~p);",
|
|
|
|
|
|
|
|
[Division, N])
|
|
|
|
|
|
|
|
|| N <- lists:seq(1, Size-1)])]),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{reply, sql_begin(State#state.database, SQL), State};
|
|
|
|
{reply, sql_begin(State#state.database, SQL), State};
|
|
|
|
handle_call(generate_finals, _, State) ->
|
|
|
|
handle_call(generate_finals, _, State) ->
|
|
|
|