aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Armstrong <jeff@approximatrix.com>2021-06-21 11:04:31 -0400
committerJeffrey Armstrong <jeff@approximatrix.com>2021-06-21 11:04:31 -0400
commit20091904b7bf4b2074b45e25c7eee0e56d19348b (patch)
tree5c31004eff65466c84ed88cde77cbc712ba04ea6
parentcd9283417a4b70335edf7ce0c5d15bfca111b807 (diff)
downloadlevitating-20091904b7bf4b2074b45e25c7eee0e56d19348b.tar.gz
levitating-20091904b7bf4b2074b45e25c7eee0e56d19348b.zip
Groups of instructions are now supported, allowing launching multiple jobs at once
-rw-r--r--captain/db.f90355
-rw-r--r--captain/external.f902
-rw-r--r--captain/launch.f9020
-rw-r--r--captain/levitating-captain.prj2
-rw-r--r--captain/queryutils.f909
-rw-r--r--captain/sql/create.sql3
-rw-r--r--captain/template.f902
-rw-r--r--captain/templates/home.html1
-rw-r--r--captain/templates/index.html1
-rw-r--r--captain/web.f90251
10 files changed, 630 insertions, 16 deletions
diff --git a/captain/db.f90 b/captain/db.f90
index 2cf8e4f..e4b4a4b 100644
--- a/captain/db.f90
+++ b/captain/db.f90
@@ -38,16 +38,27 @@ implicit none
character(1024)::database_file
type(c_ptr)::db
- type :: job
+ type :: work_pair
- integer::id
integer::instruction
integer::player
+
+ end type
+
+ type, extends(work_pair) :: job
+
+ integer::id
integer::status
character(32)::time
end type
+ type, extends(work_pair) :: group_entry
+
+ integer::group
+
+ end type
+
type :: task
integer::job
@@ -189,21 +200,48 @@ contains
end function get_player_names
- function get_instuctions_count()
+ function get_instructions_count()
implicit none
type(sqlite3_stmt)::stmt
- integer::get_instuctions_count
+ integer::get_instructions_count
- get_instuctions_count = 0
+ get_instructions_count = 0
if(stmt%prepare(db, "SELECT COUNT(*) FROM instructions") == SQLITE_OK) then
if(stmt%step() == SQLITE_ROW) then
- get_instuctions_count = stmt%column_int(0)
+ get_instructions_count = stmt%column_int(0)
end if
end if
call stmt%finalize()
- end function get_instuctions_count
+ end function get_instructions_count
+
+ function get_instruction_ids() result(res)
+ implicit none
+
+ type(sqlite3_stmt)::stmt
+ integer, dimension(:), pointer::res
+ integer::i,n
+
+ res => null()
+
+ n = get_instructions_count()
+ if(n > 0) then
+ allocate(res(n))
+ res = -1
+
+ if(stmt%prepare(db, "SELECT id, name FROM instructions ORDER BY name") == SQLITE_OK) then
+ i = 1
+ do while(stmt%step() == SQLITE_ROW .and. i <= n)
+ res(i) = stmt%column_int(0)
+ i = i + 1
+ end do
+ end if
+ call stmt%finalize()
+
+ end if
+
+ end function get_instruction_ids
function get_instruction_names() result(res)
implicit none
@@ -212,7 +250,7 @@ contains
character(len=PLAYER_NAME_LENGTH), dimension(:), pointer::res
integer::i,n
- n = get_instuctions_count()
+ n = get_instructions_count()
if(n > 0) then
allocate(res(n))
if(stmt%prepare(db, "SELECT name FROM instructions ORDER BY name") == SQLITE_OK) then
@@ -295,7 +333,7 @@ contains
type(sqlite3_stmt)::stmt
str = " "
-
+ Print *, id
if(stmt%prepare(db, "SELECT name FROM instructions WHERE id=?") == SQLITE_OK) then
if(stmt%bind_int(1, id) == SQLITE_OK) then
if(stmt%step() == SQLITE_ROW) then
@@ -776,4 +814,303 @@ contains
end subroutine scan_instructions_for_db
+ subroutine add_group_db(name)
+ implicit none
+
+ character(*), intent(in)::name
+
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "INSERT INTO groups(name) VALUES(?)") == SQLITE_OK) then
+ if(stmt%bind_text(1, name) == SQLITE_OK) then
+
+ call stmt%step_now()
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end subroutine add_group_db
+
+ subroutine get_group_name_db(id, name)
+ implicit none
+
+ integer, intent(in)::id
+ character(*), intent(out)::name
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "SELECT name FROM groups WHERE id=?") == SQLITE_OK) then
+ if(stmt%bind_int(1, id) == SQLITE_OK) then
+
+ if(stmt%step() == SQLITE_ROW) then
+ call stmt%column_text(0, name)
+ end if
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end subroutine get_group_name_db
+
+ function get_group_id_db(name)
+ implicit none
+
+ character(*), intent(in)::name
+ integer::get_group_id_db
+ type(sqlite3_stmt)::stmt
+
+ get_group_id_db = -1
+
+ if(stmt%prepare(db, "SELECT id FROM groups WHERE name=?") == SQLITE_OK) then
+ if(stmt%bind_text(1, name) == SQLITE_OK) then
+
+ if(stmt%step() == SQLITE_ROW) then
+ get_group_id_db = stmt%column_int(0)
+ end if
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end function get_group_id_db
+
+ subroutine delete_group_db(id)
+ implicit none
+
+ integer, intent(in)::id
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "DELETE FROM groups WHERE id=?") == SQLITE_OK) then
+ if(stmt%bind_int(1, id) == SQLITE_OK) then
+
+ call stmt%step_now()
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end subroutine delete_group_db
+
+ function get_group_count_db()
+ implicit none
+
+ integer::get_group_count_db
+ type(sqlite3_stmt)::stmt
+
+ get_group_count_db = 0
+
+ if(stmt%prepare(db, "SELECT COUNT(*) FROM groups") == SQLITE_OK) then
+ if(stmt%step() == SQLITE_ROW) then
+ get_group_count_db = stmt%column_int(0)
+ end if
+ end if
+ call stmt%finalize()
+
+ end function get_group_count_db
+
+ function get_groups_db() result(res)
+ implicit none
+
+ integer, dimension(:), pointer::res
+ type(sqlite3_stmt)::stmt
+ integer::i, n
+
+ res => null()
+ n = get_group_count_db()
+
+ if(n > 0) then
+
+ allocate(res(n))
+ res = -1
+
+ if(stmt%prepare(db, "SELECT id FROM groups") == SQLITE_OK) then
+ i = 0
+ do while(stmt%step() == SQLITE_ROW .AND. i <= n)
+ i = i + 1
+ res(i) = stmt%column_int(0)
+ end do
+ end if
+ call stmt%finalize()
+
+ end if
+
+ end function get_groups_db
+
+ function is_entry_in_group_db(group, instruction, player)
+ implicit none
+
+ integer, intent(in)::group, instruction, player
+ type(sqlite3_stmt)::stmt
+ logical::is_entry_in_group_db
+
+ is_entry_in_group_db = .FALSE.
+
+ if(stmt%prepare(db, &
+ "SELECT COUNT(*) FROM group_instructions WHERE group_id=? AND instruction=? AND player=?") == SQLITE_OK) &
+ then
+ if(stmt%bind_int(1, group) == SQLITE_OK .AND. &
+ stmt%bind_int(2, instruction) == SQLITE_OK .AND. &
+ stmt%bind_int(3, player) == SQLITE_OK) &
+ then
+
+ if(stmt%step() == SQLITE_ROW) then
+ is_entry_in_group_db = (stmt%column_int(0) > 0)
+ end if
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end function is_entry_in_group_db
+
+ subroutine add_entry_to_group_db(group, instruction, player)
+ implicit none
+
+ integer, intent(in)::group, instruction, player
+ type(sqlite3_stmt)::stmt
+
+ if(instruction >= 0 .AND. player >= 0 .AND. group >= 0 .AND. &
+ .NOT. is_entry_in_group_db(group, instruction, player)) &
+ then
+
+ if(stmt%prepare(db, "INSERT INTO group_instructions(group_id, instruction, player) VALUES(?, ?, ?)") == SQLITE_OK) then
+ if(stmt%bind_int(1, group) == SQLITE_OK .AND. &
+ stmt%bind_int(2, instruction) == SQLITE_OK .AND. &
+ stmt%bind_int(3, player) == SQLITE_OK) &
+ then
+
+ call stmt%step_now()
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end if
+
+ end subroutine add_entry_to_group_db
+
+ subroutine remove_entry_from_group_db(group, instruction, player)
+ implicit none
+
+ integer, intent(in)::group, instruction, player
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "DELETE FROM group_instructions WHERE group_id=? AND instruction=? AND player=?") == SQLITE_OK) then
+ if(stmt%bind_int(1, group) == SQLITE_OK .AND. &
+ stmt%bind_int(2, instruction) == SQLITE_OK .AND. &
+ stmt%bind_int(3, player) == SQLITE_OK) &
+ then
+
+ call stmt%step_now()
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end subroutine remove_entry_from_group_db
+
+ function get_group_entries_count_db(group)
+ implicit none
+
+ integer, intent(in)::group
+ integer::get_group_entries_count_db
+ type(sqlite3_stmt)::stmt
+
+ get_group_entries_count_db = 0
+
+ if(stmt%prepare(db, "SELECT COUNT(*) FROM group_instructions WHERE group_id=?") == SQLITE_OK) then
+ if(stmt%bind_int(1, group) == SQLITE_OK) then
+
+ if(stmt%step() == SQLITE_ROW) then
+ get_group_entries_count_db = stmt%column_int(0)
+ end if
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end function get_group_entries_count_db
+
+ function get_group_entries_db(group) result(res)
+ implicit none
+
+ integer, intent(in)::group
+ type(group_entry), dimension(:), pointer::res
+ type(sqlite3_stmt)::stmt
+ integer::i, n
+
+ res => null()
+
+ n = get_group_entries_count_db(group)
+ if(n > 0) then
+
+ allocate(res(n))
+ res%instruction = -1
+ res%player = -1
+ res%group = group
+
+ if(stmt%prepare(db, "SELECT instruction, player FROM group_instructions WHERE group_id=?") == SQLITE_OK) then
+ if(stmt%bind_int(1, group) == SQLITE_OK) then
+
+ i = 0
+ do while(stmt%step() == SQLITE_ROW .and. i <= n)
+ i = i + 1
+ res(i)%instruction = stmt%column_int(0)
+ res(i)%player = stmt%column_int(1)
+ end do
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end if
+
+ end function get_group_entries_db
+
+ function get_available_count_db()
+ implicit none
+
+ integer::get_available_count_db
+ type(sqlite3_stmt)::stmt
+
+ get_available_count_db = 0
+
+ if(stmt%prepare(db, "SELECT COUNT(*) FROM available") == SQLITE_OK) then
+ if(stmt%step() == SQLITE_ROW) then
+ get_available_count_db = stmt%column_int(0)
+ end if
+ end if
+ call stmt%finalize()
+
+ end function get_available_count_db
+
+ function get_available_work_pairs_db() result(res)
+ implicit none
+
+ type(work_pair), dimension(:), pointer::res
+ integer::n, i
+ type(sqlite3_stmt)::stmt
+
+ n = get_available_count_db()
+ res => null()
+
+ if(n > 0) then
+ allocate(res(n))
+ res%instruction = -1
+ res%player = -1
+
+ if(stmt%prepare(db, "SELECT instruction, player FROM available") == SQLITE_OK) then
+ i = 1
+ do while(stmt%step() == SQLITE_ROW .AND. i <= n)
+ res(i)%instruction = stmt%column_int(0)
+ res(i)%player = stmt%column_int(1)
+ i = i + 1
+ end do
+ end if
+ call stmt%finalize()
+
+ end if
+
+ end function get_available_work_pairs_db
+
end module captain_db
diff --git a/captain/external.f90 b/captain/external.f90
index 2a0bc23..edbe997 100644
--- a/captain/external.f90
+++ b/captain/external.f90
@@ -408,7 +408,7 @@ contains
character(len=3*PLAYER_NAME_LENGTH)::one_player
- n = get_instuctions_count()
+ n = get_instructions_count()
if(n == 0) then
diff --git a/captain/launch.f90 b/captain/launch.f90
index c397143..e889ccc 100644
--- a/captain/launch.f90
+++ b/captain/launch.f90
@@ -38,5 +38,25 @@ contains
end subroutine launch_instructions_on_player
+ subroutine launch_group(group)
+ use captain_db
+ implicit none
+
+ integer, intent(in)::group
+ type(group_entry), dimension(:), pointer::work
+ integer::i
+
+ work => get_group_entries_db(group)
+ if(associated(work)) then
+
+ do i=1, size(work)
+
+ call add_new_job(work(i)%instruction, work(i)%player)
+
+ end do
+
+ end if
+
+ end subroutine launch_group
end module remote_launch \ No newline at end of file
diff --git a/captain/levitating-captain.prj b/captain/levitating-captain.prj
index 4501070..392ac52 100644
--- a/captain/levitating-captain.prj
+++ b/captain/levitating-captain.prj
@@ -146,7 +146,7 @@
"Target":"levitating-captain",
"Fortran Options":{
"Use C Preprocessor":"false",
- "Runtime Diagnostics":"false",
+ "Runtime Diagnostics":"true",
"Floating Point Exception Trap":0,
"Cray Pointers":"false",
"Enable Coarrays":"false",
diff --git a/captain/queryutils.f90 b/captain/queryutils.f90
index 6faec80..4f3d805 100644
--- a/captain/queryutils.f90
+++ b/captain/queryutils.f90
@@ -56,20 +56,23 @@ implicit none
contains
subroutine query_component_parse(self, comptext)
+ use logging
implicit none
class(query_component), intent(out)::self
character(*), intent(in)::comptext
- character(len=:), allocatable::decoded
+ character(len=:), pointer::decoded
integer::i_in, i_out, i_equals, chnum
allocate(character(len=len_trim(comptext)) :: decoded)
+ decoded = " "
i_equals = 0
i_out = 1
i_in = 1
do while(i_in <= len_trim(comptext))
+
if(comptext(i_in:i_in) /= '%') then
decoded(i_out:i_out) = comptext(i_in:i_in)
if(comptext(i_in:i_in) == '=') then
@@ -207,6 +210,8 @@ contains
integer, intent(in)::i
character(len=:), pointer::res
+ res => null()
+
if(i <= self%component_count()) then
res => self%components(i)%value
end if
@@ -222,6 +227,8 @@ contains
integer::i
+ res => null()
+
do i = 1, self%component_count()
if(self%components(i)%has_key()) then
if(self%components(i)%key == trim(k)) then
diff --git a/captain/sql/create.sql b/captain/sql/create.sql
index c09d120..6457296 100644
--- a/captain/sql/create.sql
+++ b/captain/sql/create.sql
@@ -9,3 +9,6 @@ CREATE TABLE instructions(id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL);
CREATE TABLE available(instruction INTEGER, player INTEGER, FOREIGN KEY(instruction) REFERENCES instructions(id), FOREIGN KEY(player) REFERENCES players(id), UNIQUE(instruction, player));
+CREATE TABLE groups(id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL);
+
+CREATE TABLE group_instructions(group_id INTEGER, instruction INTEGER, player INTEGER, FOREIGN KEY(group_id) REFERENCES groups(id) ON DELETE CASCADE, FOREIGN KEY(instruction) REFERENCES instructions(id) ON DELETE CASCADE, FOREIGN KEY(player) REFERENCES players(id) ON DELETE CASCADE);
diff --git a/captain/template.f90 b/captain/template.f90
index ad4ea19..3ae3dae 100644
--- a/captain/template.f90
+++ b/captain/template.f90
@@ -281,7 +281,7 @@ contains
call self%variables(i)%assign(name, value)
- call write_log(name//"=|||"//trim(value)//"|||", LOG_INFO)
+ !call write_log(name//"=|||"//trim(value)//"|||", LOG_INFO)
end subroutine template_assign_string
diff --git a/captain/templates/home.html b/captain/templates/home.html
index a804d62..330fb0e 100644
--- a/captain/templates/home.html
+++ b/captain/templates/home.html
@@ -9,5 +9,6 @@
<li><a href="jobs.html">Jobs</a> - View pending and completed jobs along with results</li>
<li><a href="players.html">Players</a> - Manage players, including adding new players to the team</li>
<li><a href="instructions.html">Instructions</a> - Launch certain instruction sets or assign instructions to players</li>
+ <li><a href="groups.html">Groups</a> - Manage or launch a group of instructions, all at once</li>
<li><a href="about.html">About</a> - Learn more about this service</li>
</ul>
diff --git a/captain/templates/index.html b/captain/templates/index.html
index ae87e72..5d90ad4 100644
--- a/captain/templates/index.html
+++ b/captain/templates/index.html
@@ -16,6 +16,7 @@
<li><a href="{{ base_url }}/jobs.html">Jobs</a></li>
<li><a href="{{ base_url }}/players.html">Players</a></li>
<li><a href="{{ base_url }}/instructions.html">Instructions</a></li>
+ <li><a href="{{ base_url }}/groups.html">Groups</a></li>
<li><a href="{{ base_url }}/about.html">About</a></li>
</ul>
</div>
diff --git a/captain/web.f90 b/captain/web.f90
index ccd3df0..9254658 100644
--- a/captain/web.f90
+++ b/captain/web.f90
@@ -253,7 +253,7 @@ contains
character(len=:), pointer::one_player, scanlink
- n = get_instuctions_count()
+ n = get_instructions_count()
if(n == 0) then
@@ -291,6 +291,227 @@ contains
deallocate(scanlink)
end function generate_instructions_html
+
+ function generate_groups_html(req) result(res)
+ use captain_db
+ use server_response, only:request
+ implicit none
+
+ type(request)::req
+ character(len=:), pointer::res
+ integer, dimension(:), pointer::groups
+ character(128)::one_group
+ integer::n, i
+
+ character(len=:), pointer::one_link
+
+ n = get_group_count_db()
+
+ if(n == 0) then
+
+ allocate(character(len=1024) :: res)
+ res = "None Yet"
+
+ else
+
+ allocate(character(len=(n*(256+64) + 384)) :: res)
+
+ res = "<h2>Groups</h2>"//new_line(' ')//"<ul>"
+
+ groups => get_groups_db()
+ do i=1, n
+ call get_group_name_db(groups(i), one_group)
+ one_link => html_link("groups/"//trim(one_group)//".html", &
+ trim(one_group))
+
+ res = trim(res)//new_line(' ')//"<li>"//trim(one_link)//"</li>"
+ deallocate(one_link)
+ end do
+
+ res = trim(res)//new_line(' ')//"</ul>"
+ deallocate(groups)
+
+ end if
+
+ res = trim(res)//new_line(' ')//"<h2>Management</h2>"
+
+ res = trim(res)//new_line(' ')// &
+ '<form action="groups/add.html" method="POST"><label for="name">Name:</label>'// &
+ '<input name="name" id="name" /><input type="submit" value="Add"/></form>'
+
+ end function generate_groups_html
+
+ function generate_one_group_html(req) result(res)
+ use captain_db
+ use server_response, only:request
+ use request_utils
+ use query_utilities
+ use logging
+ use remote_launch, only: launch_group
+ implicit none
+
+ type(request)::req
+ character(len=:), pointer::res
+
+ type(query)::q
+
+ character(128)::group_name, instruction_name, player_name
+ integer::id
+
+ type(group_entry), dimension(:), pointer::entries
+ type(work_pair), dimension(:), pointer::all_entries
+ character(len=:), pointer::one_link, delete_link, play_link, qreq
+
+ character(128)::launch_msg
+
+ integer::i, j, n_instructions_group, n_instructions_total
+
+ call req%path_component(2, group_name)
+ i = index(group_name, ".html")
+ group_name(i:128) = ' '
+
+ id = get_group_id_db(trim(group_name))
+ entries => null()
+ all_entries => null()
+
+ launch_msg = " "
+
+ if(associated(req%query_string)) then
+
+ call q%init(req%query_string)
+ qreq => q%get_value("add")
+
+ if(associated(qreq)) then
+
+ call write_log("ADD: "//trim(qreq))
+
+ i = index(qreq, ',')
+ player_name = qreq(i+1:len_trim(qreq))
+ instruction_name = qreq(1:i-1)
+
+ i = get_instruction_id(trim(instruction_name))
+ j = get_player_id(trim(player_name))
+
+ call add_entry_to_group_db(id, i, j)
+
+ deallocate(qreq)
+
+ else
+
+ qreq => q%get_value("delete")
+
+ if(associated(qreq)) then
+
+ i = index(qreq, ',')
+ player_name = qreq(i+1:len(qreq))
+ instruction_name = qreq(1:i-1)
+
+ i = get_instruction_id(trim(instruction_name))
+ j = get_player_id(trim(player_name))
+
+ call remove_entry_from_group_db(id, i, j)
+
+ deallocate(qreq)
+
+ else if(trim(req%query_string) == "launch") then
+
+ call launch_group(id)
+ write(launch_msg, '(I4, 1X, A13)') get_group_entries_count_db(id), "jobs launched"
+
+ else if(trim(req%query_string) == "destroy") then
+
+ call delete_group_db(id)
+
+ end if
+
+ end if
+
+ call q%destroy()
+
+ end if
+
+ n_instructions_group = get_group_entries_count_db(id)
+ n_instructions_total = get_available_count_db()
+
+ allocate(character( len=(n_instructions_total*384 + 512) ) :: res)
+
+ res = "<h2>"//trim(group_name)//"</h2>"
+
+ if(n_instructions_group == 0) then
+
+ res = trim(res)//new_line(' ')//"<p><em>Contains no instructions.</em></p>"
+
+ else
+
+ if(len_trim(launch_msg) > 0) then
+ res = trim(res)//new_line(' ')//'<p><strong>'//trim(launch_msg)//'</strong></p>'
+ else
+ res = trim(res)//new_line(' ')//'<p><a href="'//req%page//'?launch">&#x1f680; Launch Now</a></p>'
+ end if
+
+ res = trim(res)//new_line(' ')//"<h3>Work to Be Performed</h3>"//new_line(' ')//"<ul>"
+
+ entries => get_group_entries_db(id)
+ do i = 1, n_instructions_group
+
+ call get_instruction_name(entries(i)%instruction, instruction_name)
+ call get_player_name(entries(i)%player, player_name)
+
+ one_link => html_link("../instructions/"//trim(instruction_name)//".html", trim(instruction_name))
+ play_link => html_link("../players/"//trim(player_name)//".html", trim(player_name))
+ delete_link => html_link(trim(group_name)//".html?delete="// &
+ trim(instruction_name)//","//trim(player_name), &
+ "<em>Remove</em>")
+
+ res = trim(res)//new_line(' ')//"<li>"//one_link//" on "//play_link//" - "//delete_link//"</li>"
+
+ deallocate(one_link)
+ deallocate(play_link)
+ deallocate(delete_link)
+
+ end do
+
+ res = trim(res)//new_line(' ')//"</ul>"
+
+ end if
+
+ if(n_instructions_total > 0) then
+
+ res = trim(res)//new_line(' ')//"<h3>Add Instructions</h3>"
+
+ all_entries => get_available_work_pairs_db()
+ if(associated(all_entries)) then
+
+ res = trim(res)//new_line(' ')//'<form action="'//trim(group_name)//'.html" method="GET">'// &
+ '<label for="add">Instruction:</label>'//new_line(' ')// &
+ '<select name="add" id="add">'
+
+ do i=1,n_instructions_total
+
+ if(associated(entries)) then
+ if(any(entries%player == all_entries(i)%player .AND. &
+ entries%instruction == all_entries(i)%instruction) ) &
+ then
+ cycle
+ end if
+ end if
+
+ call get_instruction_name(all_entries(i)%instruction, instruction_name)
+ call get_player_name(all_entries(i)%player, player_name)
+ res = trim(res)//new_line(' ')//'<option value="'//trim(instruction_name)//","//trim(player_name)//'">'// &
+ trim(instruction_name)//" on "//trim(player_name)//"</option>"
+
+ end do
+
+ res = trim(res)//new_line(' ')//'</select>'//'<input type="submit" value="Add"/></form>'
+ end if
+ end if
+
+ res = trim(res)//new_line(' ')//'<h3>Destroy This Group</h3>'//new_line(' ')// &
+ '<p><a href="'//req%page//'?destroy">&#x1f4a3; Destroy</a></p>'//new_line(' ')// &
+ '<p><em>This operation will not destroy any instructions</em></p>'
+
+ end function generate_one_group_html
function generate_players_html() result(res)
use captain_db
@@ -694,7 +915,19 @@ contains
call page%assign('title', trim(job_page_title))
contents => generate_one_job_html(req)
call page%assign('contents', contents)
-
+
+ else if(trim(req%location) == "/groups.html") then
+
+ call page%assign('title', 'Instruction Groups')
+ contents => generate_groups_html(req)
+ call page%assign('contents', contents)
+
+ else if(trim(first) == "groups") then
+
+ call page%assign('title', 'Instruction Group')
+ contents => generate_one_group_html(req)
+ call page%assign('contents', contents)
+
else
call page%assign('title', 'Not Found')
@@ -716,7 +949,7 @@ contains
end function request_templated
function handle_post(req) result(resp)
- use captain_db, only: add_player_db
+ use captain_db, only: add_player_db, add_group_db
use page_template
use config, only: template_filepath
use logging
@@ -757,6 +990,18 @@ contains
end if
+ else if(trim(category) == "groups") then
+
+ call req%path_component(2, second)
+
+ ! Add a group
+ if(trim(second) == "add.html") then
+
+ call add_group_db(posted%get_value("name"))
+ call page%assign('destination', 'groups.html')
+
+ end if
+
end if
! Handle the template