|
|
|
@ -2,19 +2,27 @@
|
|
|
|
|
|
|
|
|
|
-behaviour(gen_server).
|
|
|
|
|
|
|
|
|
|
-export([start_link/0, init/1, handle_cast/2, handle_call/3, add_teams/1]).
|
|
|
|
|
-export([start_link/1, init/1, handle_cast/2, handle_call/3, add_teams/1]).
|
|
|
|
|
|
|
|
|
|
-export([set_test_config/0, new/1, load/1]).
|
|
|
|
|
-export([set_test_config/0, new/1, close/0]).
|
|
|
|
|
|
|
|
|
|
-record(division, {teams = [], practice = 0, qualification = 0}).
|
|
|
|
|
-record(config, {divisions = []}).
|
|
|
|
|
-record(state, {database_file = none, database = none, teams = [], config = none}).
|
|
|
|
|
|
|
|
|
|
start_link() ->
|
|
|
|
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
|
|
|
|
start_link(DatabaseFile) ->
|
|
|
|
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [DatabaseFile], []).
|
|
|
|
|
|
|
|
|
|
init([]) ->
|
|
|
|
|
{ok, #state{}}.
|
|
|
|
|
init([DatabaseFile]) ->
|
|
|
|
|
Exists = filelib:is_regular(DatabaseFile),
|
|
|
|
|
if Exists =:= true ->
|
|
|
|
|
{ok, DB} = sqlite3:open(schedule_db, [{file, DatabaseFile}]),
|
|
|
|
|
ok = sqlite3:sql_exec(DB, "PRAGMA foreign_keys = ON;"),
|
|
|
|
|
{ok, #state{database_file = DatabaseFile, database = DB}};
|
|
|
|
|
true ->
|
|
|
|
|
io:format("Failed to load database ~s~n", [DatabaseFile]),
|
|
|
|
|
{ok, #state{database_file = none, database = none}}
|
|
|
|
|
end.
|
|
|
|
|
|
|
|
|
|
init_db(Database) ->
|
|
|
|
|
ok = sqlite3:create_table(Database, genids, [{genid, text, [not_null]},
|
|
|
|
@ -66,16 +74,16 @@ init_db(Database) ->
|
|
|
|
|
|
|
|
|
|
delete_teams(Database, Teams) ->
|
|
|
|
|
SQL = lists:append(["BEGIN; ",
|
|
|
|
|
lists:append([io_lib:format("DELETE FROM teams WHERE name = ~p; ",
|
|
|
|
|
[Team]) || Team <- Teams]),
|
|
|
|
|
"COMMIT;"]),
|
|
|
|
|
lists:append([io_lib:format("DELETE FROM teams WHERE name = ~p; ",
|
|
|
|
|
[Team]) || Team <- Teams]),
|
|
|
|
|
"COMMIT;"]),
|
|
|
|
|
first_error(sqlite3:sql_exec_script(Database, SQL)).
|
|
|
|
|
|
|
|
|
|
add_teams(Database, Teams) ->
|
|
|
|
|
SQL = lists:append(["BEGIN; ",
|
|
|
|
|
lists:append([io_lib:format("INSERT INTO teams(name) VALUES('~s') ON CONFLICT(name) DO NOTHING; ",
|
|
|
|
|
[Team]) || Team <- Teams]),
|
|
|
|
|
"COMMIT;"]),
|
|
|
|
|
lists:append([io_lib:format("INSERT INTO teams(name) VALUES('~s') ON CONFLICT(name) DO NOTHING; ",
|
|
|
|
|
[Team]) || Team <- Teams]),
|
|
|
|
|
"COMMIT;"]),
|
|
|
|
|
first_error(sqlite3:sql_exec_script(Database, SQL)).
|
|
|
|
|
|
|
|
|
|
first_error([]) -> ok;
|
|
|
|
@ -93,7 +101,7 @@ write_matches(Database, Type, Teams, Seed, Size, Round, Matches) ->
|
|
|
|
|
[GenID, atom_to_list(Type), Size, Seed]),
|
|
|
|
|
lists:append([io_lib:format(
|
|
|
|
|
"INSERT INTO matches(genid, round, number, blue_1, blue_2, red_1, red_2)
|
|
|
|
|
VALUES ('~s', '~s', ~p, '~s', '~s', '~s', '~s'); ",
|
|
|
|
|
VALUES ('~s', '~s', ~p, '~s', '~s', '~s', '~s'); ",
|
|
|
|
|
[GenID, atom_to_list(Round), N, B1, B2, R1, R2])
|
|
|
|
|
|| {N, [B1, B2, R1, R2]} <- lists:enumerate(Matches)]),
|
|
|
|
|
"COMMIT;"]),
|
|
|
|
@ -111,11 +119,17 @@ add_teams(Teams) ->
|
|
|
|
|
new(DatabaseFile) ->
|
|
|
|
|
gen_server:call(?MODULE, {new_db, DatabaseFile}).
|
|
|
|
|
|
|
|
|
|
load(DatabaseFile) ->
|
|
|
|
|
gen_server:call(?MODULE, {load_db, DatabaseFile}).
|
|
|
|
|
close() ->
|
|
|
|
|
gen_server:call(?MODULE, close_db).
|
|
|
|
|
|
|
|
|
|
handle_call({set_config, Config}, _, State) when is_record(Config, config) ->
|
|
|
|
|
{reply, ok, State#state{config = Config}};
|
|
|
|
|
handle_call(close_db, _, State) ->
|
|
|
|
|
if State#state.database =:= none -> {reply, ok, State};
|
|
|
|
|
true ->
|
|
|
|
|
ok = sqlite3:close(State#state.database),
|
|
|
|
|
{reply, ok, State#state{database = none, database_file = none}}
|
|
|
|
|
end;
|
|
|
|
|
handle_call({new_db, DatabaseFile}, _, State) ->
|
|
|
|
|
ok = if State#state.database =:= none -> ok;
|
|
|
|
|
true -> sqlite3:close(State#state.database)
|
|
|
|
@ -150,11 +164,11 @@ handle_call({new_schedule, Division, Round, Seed}, _, State) ->
|
|
|
|
|
DivInfo = lists:nth(Division, State#state.config#config.divisions),
|
|
|
|
|
Teams = DivInfo#division.teams,
|
|
|
|
|
Size = case Round of
|
|
|
|
|
practice when DivInfo#division.practice =/= 0 ->
|
|
|
|
|
DivInfo#division.practice;
|
|
|
|
|
qualification when DivInfo#division.qualification =/= 0->
|
|
|
|
|
DivInfo#division.qualification
|
|
|
|
|
end,
|
|
|
|
|
practice when DivInfo#division.practice =/= 0 ->
|
|
|
|
|
DivInfo#division.practice;
|
|
|
|
|
qualification when DivInfo#division.qualification =/= 0->
|
|
|
|
|
DivInfo#division.qualification
|
|
|
|
|
end,
|
|
|
|
|
Matches = schedule:create(Seed, Size, Teams),
|
|
|
|
|
{ok, GenID} = write_matches(State#state.database, division, Teams, Seed, Size, Round, Matches),
|
|
|
|
|
{reply, GenID, State};
|
|
|
|
|