|  |  |  | @ -2,13 +2,9 @@ | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | -behaviour(gen_server). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | -export([start_link/1, init/1, handle_cast/2, handle_call/3, add_teams/1]). | 
		
	
		
			
				|  |  |  |  | -export([start_link/1, init/1, handle_cast/2, handle_call/3]). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | -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}). | 
		
	
		
			
				|  |  |  |  | -record(state, {database_file = none, database = none}). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | start_link(DatabaseFile) -> | 
		
	
		
			
				|  |  |  |  |   gen_server:start_link({local, ?MODULE}, ?MODULE, [DatabaseFile], []). | 
		
	
	
		
			
				
					|  |  |  | @ -25,57 +21,88 @@ init([DatabaseFile]) -> | 
		
	
		
			
				|  |  |  |  |   end. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | init_db(Database) -> | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, genids, [{genid, text, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [genid]}]), | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, divisions, [{division, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                   {prac_size, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                   {prac_seed, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                   {qual_size, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                   {qual_seed, integer, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                                                   {psize, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                   {qsize, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                   {esize, integer, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [division]}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, teams, [{team, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                               {division, integer}, | 
		
	
		
			
				|  |  |  |  |                                               {alliance, integer}, | 
		
	
		
			
				|  |  |  |  |                                               {inspection, blob}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [team]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[division], divisions, [division], "ON DELETE RESTRICT"}}]), | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, matches, [{genid, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {round, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[division], divisions, [division], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, matches, [{division, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {type, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {number, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {red_1, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {red_2, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {blue_1, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                 {blue_2, text, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [genid, round, number]}, | 
		
	
		
			
				|  |  |  |  |                              {check, "round IN ('practice', 'qualification', 'elimination', 'final')"}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[genid], genids, [genid], "ON DELETE RESTRICT"}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[blue_1], teams, [team], "ON DELETE RESTRICT"}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[blue_2], teams, [team], "ON DELETE RESTRICT"}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[red_1], teams, [team], "ON DELETE RESTRICT"}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[red_2], teams, [team], "ON DELETE RESTRICT"}}]), | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, match_scores, [{genid, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {round, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [division, type, number]}, | 
		
	
		
			
				|  |  |  |  |                              {check, "type IN ('practice', 'qualification', 'elimination')"}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[division], divisions, [division], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[blue_1], teams, [team], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[blue_2], teams, [team], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[red_1], teams, [team], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[red_2], teams, [team], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, match_scores, [{division, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {type, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {number, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {instance, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {score, blob, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [genid, round, number, instance]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[genid, round, number], matches, [genid, round, number], "ON DELETE CASCADE"}}]), | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, match_states, [{genid, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {round, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [division, type, number, instance]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[division, type, number], matches, [division, type, number], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, match_states, [{division, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {type, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {number, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {time, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                      {state, blob, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [genid, round, number, time]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[genid, round, number], matches, [genid, round, number], "ON DELETE CASCADE"}}]), | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [division, type, number, time]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[division, type, number], matches, [division, type, number], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, finals, [{number, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                {red_1, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                {red_2, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                {blue_1, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                {blue_2, text, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [number]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[blue_1], teams, [team], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[blue_2], teams, [team], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[red_1], teams, [team], ""}}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[red_2], teams, [team], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, finals_scores, [{number, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {instance, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {score, blob, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [number, instance]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[number], finals, [number], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, finals_states, [{number, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {time, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {state, blob, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [number, time]}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[number], finals, [number], ""}}]), | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:create_table(Database, skills_scores, [{team, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {type, text, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {attempt, integer, [not_null]}, | 
		
	
		
			
				|  |  |  |  |                                                       {score, blob}], | 
		
	
		
			
				|  |  |  |  |                                                       {score, blob, [not_null]}], | 
		
	
		
			
				|  |  |  |  |                             [{primary_key, [team, type, attempt]}, | 
		
	
		
			
				|  |  |  |  |                              {check, "type IN ('driver', 'autonomous')"}, | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[team], teams, [team], "ON DELETE CASCADE"}}]), | 
		
	
		
			
				|  |  |  |  |                              {foreign_key, {[team], teams, [team], ""}}]), | 
		
	
		
			
				|  |  |  |  |   ok. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | first_error([]) -> ok; | 
		
	
		
			
				|  |  |  |  | first_error([ok | Rest]) -> first_error(Rest); | 
		
	
		
			
				|  |  |  |  | first_error([{rowid, _} | Rest]) -> first_error(Rest); | 
		
	
		
			
				|  |  |  |  | first_error([Error | _]) -> Error. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | delete_teams(Database, Teams) -> | 
		
	
		
			
				|  |  |  |  |   SQL = lists:append(["BEGIN; ", | 
		
	
		
			
				|  |  |  |  |                       lists:append([io_lib:format("DELETE FROM teams WHERE team = ~p; ", | 
		
	
	
		
			
				
					|  |  |  | @ -90,50 +117,36 @@ add_teams(Database, Teams) -> | 
		
	
		
			
				|  |  |  |  |                       "COMMIT;"]), | 
		
	
		
			
				|  |  |  |  |   first_error(sqlite3:sql_exec_script(Database, SQL)). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | first_error([]) -> ok; | 
		
	
		
			
				|  |  |  |  | first_error([ok | Rest]) -> first_error(Rest); | 
		
	
		
			
				|  |  |  |  | first_error([Error | _]) -> Error. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | delete_matches(Database, GenID) -> | 
		
	
		
			
				|  |  |  |  |   SQL = io_lib:format("DELETE FROM matches WHERE genid = ~p", [GenID]), | 
		
	
		
			
				|  |  |  |  | assign_divisions(Database, Teams) -> | 
		
	
		
			
				|  |  |  |  |   SQL = lists:append(["BEGIN; ", | 
		
	
		
			
				|  |  |  |  |                       lists:append([io_lib:format("UPDATE teams SET division = ~p WHERE team = '~s'; ", [Division, Team]) || {Team, Division} <- Teams]), | 
		
	
		
			
				|  |  |  |  |                       "COMMIT;"]), | 
		
	
		
			
				|  |  |  |  |   first_error(sqlite3:sql_exec_script(Database, SQL)). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | write_matches(Database, Type, Teams, Seed, Size, Round, Matches) -> | 
		
	
		
			
				|  |  |  |  |   GenID = schedule:make_genid(Type, Round, Teams, Seed, Size), | 
		
	
		
			
				|  |  |  |  | write_division_matches(Database, Division, Type, Matches) -> | 
		
	
		
			
				|  |  |  |  |   SQL = lists:append(["BEGIN; ", | 
		
	
		
			
				|  |  |  |  |                       io_lib:format("INSERT INTO genids(genid, type, size, seed) VALUES('~s', '~s', ~p, ~p); ", | 
		
	
		
			
				|  |  |  |  |                                     [GenID, atom_to_list(Type), Size, Seed]), | 
		
	
		
			
				|  |  |  |  |                       io_lib:format("DELETE FROM matches WHERE division = ~p AND type = '~s';", | 
		
	
		
			
				|  |  |  |  |                                     [Division, atom_to_list(Type)]), | 
		
	
		
			
				|  |  |  |  |                       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'); ", | 
		
	
		
			
				|  |  |  |  |                                        [GenID, atom_to_list(Round), N, B1, B2, R1, R2]) | 
		
	
		
			
				|  |  |  |  |                                       "INSERT INTO matches(division, type, number, blue_1, blue_2, red_1, red_2) VALUES (~p, '~s', ~p, '~s', '~s', '~s', '~s'); ", | 
		
	
		
			
				|  |  |  |  |                                        [Division, atom_to_list(Type), N, B1, B2, R1, R2]) | 
		
	
		
			
				|  |  |  |  |                                         || {N, [B1, B2, R1, R2]} <- lists:enumerate(Matches)]), | 
		
	
		
			
				|  |  |  |  |                       "COMMIT;"]), | 
		
	
		
			
				|  |  |  |  |   {first_error(sqlite3:sql_exec_script(Database, SQL)), GenID}. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
		
	
		
			
				|  |  |  |  | -define(TEST_CONFIG, #config{divisions = [#division{teams = ["A", "B", "C", "D"], practice = 4}]}). | 
		
	
		
			
				|  |  |  |  | set_test_config() -> | 
		
	
		
			
				|  |  |  |  |   gen_server:call(?MODULE, {set_config, ?TEST_CONFIG}). | 
		
	
		
			
				|  |  |  |  | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 
		
	
		
			
				|  |  |  |  |   first_error(sqlite3:sql_exec_script(Database, SQL)). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | add_teams(Teams) -> | 
		
	
		
			
				|  |  |  |  |   gen_server:call(?MODULE, {add_teams, Teams}). | 
		
	
		
			
				|  |  |  |  | index_of(Item, List) -> index_of(Item, List, 1). | 
		
	
		
			
				|  |  |  |  | index_of(Item, [Element | _], N) when Item == Element -> N; | 
		
	
		
			
				|  |  |  |  | index_of(Item, [_ | List], N) -> index_of(Item, List, N+1). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | new(DatabaseFile) -> | 
		
	
		
			
				|  |  |  |  |   gen_server:call(?MODULE, {new_db, DatabaseFile}). | 
		
	
		
			
				|  |  |  |  | first_empty([Num1, Num2 | Nums]) when Num2 == (Num1 + 1) -> first_empty([Num2 | Nums]); | 
		
	
		
			
				|  |  |  |  | first_empty([Num | _]) -> Num + 1. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | close() -> | 
		
	
		
			
				|  |  |  |  |   gen_server:call(?MODULE, close_db). | 
		
	
		
			
				|  |  |  |  | get_column(_, [], _) -> []; | 
		
	
		
			
				|  |  |  |  | get_column(_, _, []) -> []; | 
		
	
		
			
				|  |  |  |  | get_column(Name, Columns, Rows) -> | 
		
	
		
			
				|  |  |  |  |   Index = index_of(Name, Columns), | 
		
	
		
			
				|  |  |  |  |   [element(Index, Row) || Row <- Rows]. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 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) | 
		
	
	
		
			
				
					|  |  |  | @ -157,28 +170,59 @@ handle_call({load_db, DatabaseFile}, _, State) -> | 
		
	
		
			
				|  |  |  |  |                         {sqlite3:sql_exec(DB, "PRAGMA foreign_keys = ON;"), DB} | 
		
	
		
			
				|  |  |  |  |                    end, | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State#state{database_file = DatabaseFile, database = Database}}; | 
		
	
		
			
				|  |  |  |  | handle_call({delete_teams, Removed}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   Teams = lists:filter(fun(X) -> lists:member(X, Removed) =:= false end, State#state.teams), | 
		
	
		
			
				|  |  |  |  |   ok = delete_teams(State#state.database, Removed), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State#state{teams = Teams}}; | 
		
	
		
			
				|  |  |  |  | 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({add_teams, Teams}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   ok = add_teams(State#state.database, Teams), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State#state{teams = Teams}}; | 
		
	
		
			
				|  |  |  |  | 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, | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}; | 
		
	
		
			
				|  |  |  |  | handle_call({assign_divisions, Teams}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   ok = assign_divisions(State#state.database, Teams), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}; | 
		
	
		
			
				|  |  |  |  | handle_call({delete_teams, Removed}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   ok = delete_teams(State#state.database, Removed), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}; | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | handle_call({add_division, PSize, QSize, ESize}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   [{columns, Columns}, {rows, Rows}] = sqlite3:sql_exec(State#state.database, "SELECT division FROM divisions;"), | 
		
	
		
			
				|  |  |  |  |   Divisions = lists:sort(get_column("division", Columns, Rows)), | 
		
	
		
			
				|  |  |  |  |   NextDivision = first_empty([0 | Divisions]), | 
		
	
		
			
				|  |  |  |  |   {rowid, _} = sqlite3:sql_exec(State#state.database, | 
		
	
		
			
				|  |  |  |  |   io_lib:format("INSERT INTO divisions(division, psize, qsize, esize) VALUES(~p, ~p, ~p, ~p);", | 
		
	
		
			
				|  |  |  |  |                 [NextDivision, PSize, QSize, ESize])), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}; | 
		
	
		
			
				|  |  |  |  | handle_call({edit_division, Division, PSize, QSize, ESize}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:sql_exec(State#state.database, | 
		
	
		
			
				|  |  |  |  |                    io_lib:format( | 
		
	
		
			
				|  |  |  |  |                    "UPDATE divisions SET psize = ~p, qsize = ~p, esize = ~p WHERE division = ~p;", | 
		
	
		
			
				|  |  |  |  |                    [PSize, QSize, ESize, Division])), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}; | 
		
	
		
			
				|  |  |  |  | handle_call({delete_division, Division}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   ok = sqlite3:sql_exec(State#state.database, io_lib:format("DELETE FROM divisions WHERE division = ~p;", [Division])), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}; | 
		
	
		
			
				|  |  |  |  | handle_call({generate_division, Division, Round, Seed}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   Size = get_div_size(State#state.database, Division, Round), | 
		
	
		
			
				|  |  |  |  |   Teams = get_div_teams(State#state.database, Division), | 
		
	
		
			
				|  |  |  |  |   io:fwrite("Generating division ~p/~s with teams ~p, size ~p, and seed ~p~n", [Division, Round, Teams, Size, Seed]), | 
		
	
		
			
				|  |  |  |  |   Matches = schedule:create(Seed, Size, Teams), | 
		
	
		
			
				|  |  |  |  |   {ok, GenID} = write_matches(State#state.database, division, Teams, Seed, Size, Round, Matches), | 
		
	
		
			
				|  |  |  |  |   {reply, GenID, State}; | 
		
	
		
			
				|  |  |  |  | handle_call({delete_schedule, GenID}, _, State) -> | 
		
	
		
			
				|  |  |  |  |   ok = delete_matches(State#state.database, GenID), | 
		
	
		
			
				|  |  |  |  |   ok = write_division_matches(State#state.database, Division, Round, Matches), | 
		
	
		
			
				|  |  |  |  |   {reply, ok, State}. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | get_div_size(Database, Division, Round) -> | 
		
	
		
			
				|  |  |  |  |   Column = if Round =:= practice -> "psize"; | 
		
	
		
			
				|  |  |  |  |               Round =:= qualification -> "qsize" | 
		
	
		
			
				|  |  |  |  |            end, | 
		
	
		
			
				|  |  |  |  |   [{columns, Columns}, {rows, Rows}] = sqlite3:sql_exec(Database, io_lib:format("SELECT ~s FROM divisions WHERE division = ~p;", [Column, Division])), | 
		
	
		
			
				|  |  |  |  |   [Size] = get_column(Column, Columns, Rows), | 
		
	
		
			
				|  |  |  |  |   Size. | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | get_div_teams(Database, Division) -> | 
		
	
		
			
				|  |  |  |  |   [{columns, Columns}, {rows, Rows}] = sqlite3:sql_exec(Database, io_lib:format("SELECT team FROM teams WHERE division = ~p;", [Division])), | 
		
	
		
			
				|  |  |  |  |   get_column("team", Columns, Rows). | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | handle_cast(_, State) -> | 
		
	
		
			
				|  |  |  |  |   {noreply, State}. | 
		
	
	
		
			
				
					|  |  |  | 
 |