diff --git a/src/database.erl b/src/database.erl index e410e18..1a801e5 100644 --- a/src/database.erl +++ b/src/database.erl @@ -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}; diff --git a/src/erlk_app.erl b/src/erlk_app.erl index 290e7b7..2aec2e1 100644 --- a/src/erlk_app.erl +++ b/src/erlk_app.erl @@ -10,7 +10,14 @@ -export([start/2, stop/1]). start(_StartType, _StartArgs) -> - erlk_sup:start_link(). + DBPath = case os:getenv("ERLK_DB") of + false -> + ConfigRoot = os:getenv("HOME", "/etc"), + io_lib:format("~s/erlk.db", [ConfigRoot]); + Value -> Value + end, + + erlk_sup:start_link(DBPath). stop(_State) -> ok. diff --git a/src/erlk_sup.erl b/src/erlk_sup.erl index 3055527..95dc396 100644 --- a/src/erlk_sup.erl +++ b/src/erlk_sup.erl @@ -7,12 +7,12 @@ -behaviour(supervisor). --export([start_link/0]). +-export([start_link/1]). -export([init/1]). -start_link() -> - supervisor:start_link(?MODULE, []). +start_link(DBPath) -> + supervisor:start_link(?MODULE, [DBPath]). %% sup_flags() = #{strategy => strategy(), % optional %% intensity => non_neg_integer(), % optional @@ -24,14 +24,14 @@ start_link() -> %% type => worker(), % optional %% modules => modules()} % optional -init(_) -> +init(DBPath) -> SupFlags = #{strategy => rest_for_one}, ChildSpecs = [ #{id => schedule, start => {schedule, start_link, []} }, #{id => database, - start => {database, start_link, []} + start => {database, start_link, [DBPath]} }, #{id => mqtt, start => {mqtt, start_link, []}