docs(reference): import Dune: Awakening server-manager references
All checks were successful
CI / backend-types (push) Successful in 10s
CI / frontend-build (push) Successful in 15s
CI / agent-tests (push) Successful in 39s
CI / integration (push) Successful in 22s

Phase 2 references for the host-agent Dune adapter, moved out of volatile /tmp
into docs/reference-repos/ (per Commander). Three upstream projects, .git +
node_modules + compiled binaries stripped (16MB source). Nested AI-instruction
files (.claude/, CLAUDE.md) removed so they don't pollute Corrosion sessions.

- icehunter/    dune-admin (Go+React) — 4 control planes; SETUP_DOCKER.md is the
                closest analog to our agent's Dune docker control plane (compose
                lifecycle, docker logs, RabbitMQ-via-exec, dune Postgres schema)
- adainrivers/  Rust/Tauri desktop — SSH+k8s BattleGroup control, maintenance
                daemon, in-game admin console (Rust idiom reference)
- the4rchangel/ Node web UI replacing battlegroup.bat — matches the Commander's
                Hyper-V self-host path + game-config schema

See docs/reference-repos/README.md for the full index + how we use each.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-06-11 21:08:05 -04:00
parent 0715492ddf
commit 651a35d4be
1334 changed files with 238971 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
-- landsraad_cast_vote(in_term_id bigint, in_player_id bigint, in_decree_name text) -> void
-- oid: 58399 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_cast_vote(in_term_id bigint, in_player_id bigint, in_decree_name text)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
term_winning_faction_id SMALLINT = NULL;
elected_decree_id BIGINT = NULL;
player_guild_id BIGINT = NULL;
guild_faction_id SMALLINT = NULL;
voting_decree_id BIGINT = NULL;
voting_influence INTEGER = 0;
guild_ids_json JSON = NULL;
BEGIN
LOCK TABLE landsraad_decree_votes IN EXCLUSIVE MODE;
SELECT term.winning_faction_id, term.elected_decree_id FROM landsraad_decree_term AS term WHERE term.term_id = in_term_id INTO term_winning_faction_id, elected_decree_id;
IF term_winning_faction_id IS NULL THEN
RAISE EXCEPTION 'Cannot insert landsraad vote, term % has no winning faction yet', in_term_id;
END IF;
IF elected_decree_id IS NOT NULL THEN
RAISE EXCEPTION 'Cannot insert landsraad vote, term % already has an elected decree', in_term_id;
END IF;
SELECT guilds.guild_id, guilds.guild_faction FROM guild_members
JOIN guilds ON guild_members.guild_id = guilds.guild_id WHERE guild_members.player_id = in_player_id INTO player_guild_id, guild_faction_id;
IF player_guild_id IS NULL THEN
RAISE EXCEPTION 'Cannot insert landsraad vote, player % not in guild', in_player_id;
END IF;
IF guild_faction_id != term_winning_faction_id THEN
RAISE EXCEPTION 'Cannot insert landsraad vote, guild % not alligned to winning faction %', player_guild_id, term_winning_faction_id;
END IF;
IF is_player_guild_admin(in_player_id, player_guild_id) = FALSE THEN
RAISE EXCEPTION 'Cannot insert landsraad vote, player % is not guild admin of guild %', in_player_id, player_guild_id;
END IF;
IF EXISTS (SELECT FROM landsraad_decree_votes AS votes WHERE votes.guild_id = player_guild_id) THEN
RAISE WARNING 'Cannot insert landsraad vote, guild % has voted already', player_guild_id;
RETURN;
END IF;
SELECT decrees.id FROM landsraad_decree_rotation AS rotation
INNER JOIN landsraad_decrees AS decrees ON rotation.decree_id = decrees.id
WHERE decrees.decree_name = in_decree_name INTO voting_decree_id;
IF voting_decree_id IS NULL THEN
RAISE EXCEPTION 'Cannot insert landsraad vote, decree % not for election', in_decree_name;
END IF;
SELECT FLOOR(landsraad_load_guild_contribution(in_term_id, player_guild_id, term_winning_faction_id))::INTEGER INTO voting_influence;
IF voting_influence IS NULL THEN
RAISE WARNING 'Cannot insert landsraad vote, guild % has no contribution', player_guild_id;
RETURN;
END IF;
INSERT INTO landsraad_decree_votes VALUES(voting_decree_id, player_guild_id, in_player_id, voting_influence);
SELECT json_agg(player_guild_id) INTO guild_ids_json;
PERFORM pg_notify('landsraad_notify_channel', format('guild_vote_changed#{"GuildIds": %s}', guild_ids_json));
END $function$

View File

@@ -0,0 +1,12 @@
-- landsraad_change_term_end_time(end_term_id bigint, new_end_time timestamp without time zone, in_test_term boolean) -> void
-- oid: 58400 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_change_term_end_time(end_term_id bigint, new_end_time timestamp without time zone, in_test_term boolean)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
LOCK TABLE landsraad_decree_term IN EXCLUSIVE MODE;
UPDATE landsraad_decree_term SET test_term = in_test_term WHERE term_id = end_term_id AND test_term = false;
UPDATE landsraad_decree_term SET end_time = new_end_time AT TIME ZONE 'UTC' WHERE term_id = end_term_id;
END $function$

View File

@@ -0,0 +1,25 @@
-- landsraad_check_task_completion() -> trigger
-- oid: 58401 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_check_task_completion()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
task_completed BOOLEAN = FALSE;
BEGIN
-- if a faction reached the tasks's goal amount set the task as completed
WITH faction_progress AS (SELECT landsraad_task_faction_contributions.task_id, SUM(landsraad_task_faction_contributions.amount) AS amount FROM landsraad_task_faction_contributions
WHERE landsraad_task_faction_contributions.task_id = NEW.task_id AND faction_id = NEW.faction_id GROUP BY faction_id, landsraad_task_faction_contributions.task_id)
SELECT COALESCE (faction_progress.amount, 0) >= landsraad_tasks.goal_amount
FROM landsraad_tasks LEFT JOIN faction_progress ON landsraad_tasks.id = faction_progress.task_id
WHERE landsraad_tasks.id = NEW.task_id
INTO task_completed;
IF task_completed THEN
UPDATE landsraad_tasks SET completed = TRUE, winning_faction_id = NEW.faction_id, completion_time = NOW() WHERE id = NEW.task_id AND completed = FALSE;
PERFORM pg_notify('landsraad_notify_channel', 'state_changed');
END IF;
RETURN NULL;
END $function$

View File

@@ -0,0 +1,32 @@
-- landsraad_check_term_won() -> trigger
-- oid: 58402 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_check_term_won()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
row_completed BIGINT[] = NULL;
column_completed BIGINT[] = NULL;
diagonal_1_completed BIGINT[] = NULL;
diagonal_2_completed BIGINT[] = NULL;
sysselraad_amount INTEGER = 0;
BEGIN
-- check for sysselrad rule (a row, a column or a diagonal completed by a faction)
WITH board AS (SELECT task.id as task_id, task.winning_faction_id, task.board_index / 5 AS row, task.board_index % 5 AS col, task.sysselraad FROM landsraad_tasks task WHERE task.term_id = NEW.term_id)
SELECT
(SELECT array_agg(board.task_id) FROM board WHERE board.row = ANY(SELECT board.row FROM board WHERE board.winning_faction_id = NEW.winning_faction_id GROUP BY (board.row) HAVING COUNT(board.col) = 5)),
(SELECT array_agg(board.task_id) FROM board WHERE board.col = ANY(SELECT board.col FROM board WHERE board.winning_faction_id = NEW.winning_faction_id GROUP BY (board.col) HAVING COUNT(board.row) = 5)),
(SELECT CASE WHEN COUNT(board.winning_faction_id) = 5 THEN array_agg(board.task_id) END FROM ( VALUES (0, 0), (1, 1), (2, 2), (3, 3), (4, 4) ) AS t(row, col) JOIN board ON board.row = t.row AND board.col = t.col WHERE board.winning_faction_id = NEW.winning_faction_id),
(SELECT CASE WHEN COUNT(board.winning_faction_id) = 5 THEN array_agg(board.task_id) END FROM ( VALUES (0, 4), (1, 3), (2, 2), (3, 1), (4, 0) ) AS t(row, col) JOIN board ON board.row = t.row AND board.col = t.col WHERE board.winning_faction_id = NEW.winning_faction_id),
(SELECT COUNT(*) FROM board WHERE board.sysselraad)
INTO row_completed, column_completed, diagonal_1_completed, diagonal_2_completed, sysselraad_amount;
IF sysselraad_amount = 0 AND (row_completed IS NOT NULL OR column_completed IS NOT NULL OR diagonal_1_completed IS NOT NULL OR diagonal_2_completed IS NOT NULL) THEN
UPDATE landsraad_tasks SET sysselraad = TRUE WHERE id = ANY(row_completed || column_completed || diagonal_1_completed || diagonal_2_completed);
UPDATE landsraad_decree_term SET winning_faction_id = NEW.winning_faction_id WHERE term_id = NEW.term_id AND winning_faction_id IS NULL;
PERFORM pg_notify('landsraad_notify_channel', 'state_changed');
END IF;
RETURN NULL;
END $function$

View File

@@ -0,0 +1,21 @@
-- landsraad_collect_task_telemetry_for_faction(in_term_id bigint, in_faction_name text) -> TABLE(task_telemetry dune.landsraadtermtasktelemetry[])
-- oid: 58403 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_collect_task_telemetry_for_faction(in_term_id bigint, in_faction_name text)
RETURNS TABLE(task_telemetry dune.landsraadtermtasktelemetry[])
LANGUAGE plpgsql
AS $function$
DECLARE
current_faction_id SMALLINT = NULL;
BEGIN
SELECT id FROM factions WHERE factions.name = in_faction_name INTO current_faction_id;
RETURN query SELECT ARRAY_AGG((in_faction_name, landsraad_tasks.house_name, task_reveal.revealed, (CASE WHEN winning_faction_id = current_faction_id THEN TRUE ELSE FALSE END), task_progress.participant_count, CAST(landsraad_tasks.board_index AS INTEGER), landsraad_tasks.completion_time)::LandsraadTermTaskTelemetry)
FROM landsraad_tasks
LEFT JOIN landsraad_task_reveal_state task_reveal
ON task_reveal.task_id = landsraad_tasks.id AND task_reveal.faction_id = current_faction_id
LEFT JOIN LATERAL (
SELECT COUNT(DISTINCT ltpc.player_id) AS participant_count FROM landsraad_task_player_contributions ltpc WHERE ltpc.task_id = landsraad_tasks.id and ltpc.faction_id = current_faction_id GROUP BY task_id
) AS task_progress ON true
WHERE landsraad_tasks.term_id = in_term_id;
END $function$

View File

@@ -0,0 +1,20 @@
-- landsraad_collect_term_telemetry(in_term_id bigint, in_faction_names text[]) -> TABLE(term_telemetry dune.landsraadtermtelemetry[], task_telemetry dune.landsraadtermtasktelemetry[])
-- oid: 58404 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_collect_term_telemetry(in_term_id bigint, in_faction_names text[])
RETURNS TABLE(term_telemetry dune.landsraadtermtelemetry[], task_telemetry dune.landsraadtermtasktelemetry[])
LANGUAGE plpgsql
AS $function$
DECLARE
faction_name TEXT = NULL;
term_telemetry LandsraadTermTelemetry[];
task_telemetry LandsraadTermTaskTelemetry[];
BEGIN
FOREACH faction_name IN ARRAY in_faction_names
LOOP
term_telemetry = ARRAY_APPEND(term_telemetry, landsraad_collect_term_telemetry_for_faction(in_term_id, faction_name));
task_telemetry = ARRAY_CAT(task_telemetry, landsraad_collect_task_telemetry_for_faction(in_term_id, faction_name));
END LOOP;
RETURN query SELECT term_telemetry, task_telemetry;
END $function$

View File

@@ -0,0 +1,54 @@
-- landsraad_collect_term_telemetry_for_faction(in_term_id bigint, in_faction_name text) -> dune.landsraadtermtelemetry
-- oid: 58405 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_collect_term_telemetry_for_faction(in_term_id bigint, in_faction_name text)
RETURNS dune.landsraadtermtelemetry
LANGUAGE plpgsql
AS $function$
DECLARE
current_faction_id SMALLINT = NULL;
winning_faction_id SMALLINT = NULL;
start_time TIMESTAMPTZ = NULL;
end_time TIMESTAMPTZ = NULL;
sysselraad_count INTEGER = NULL;
term_result TEXT = NULL;
faction_won BOOLEAN = FALSE;
participants_num_faction INTEGER = NULL;
tasks_completed INTEGER = NULL;
tasks_revealed INTEGER = NULL;
BEGIN
SELECT id FROM factions WHERE factions.name = in_faction_name INTO current_faction_id;
SELECT term.winning_faction_id, term.start_time, term.end_time FROM landsraad_decree_term AS term WHERE term_id = in_term_id INTO winning_faction_id, start_time, end_time;
IF winning_faction_id IS NULL THEN
term_result = 'TIE';
ELSE
SELECT COUNT(id) FROM landsraad_tasks WHERE term_id = in_term_id AND sysselraad = true INTO sysselraad_count;
IF sysselraad_count = 5 THEN
term_result = 'SYSSELRAAD';
ELSE
term_result = 'TASK_COUNT';
END IF;
END IF;
IF winning_faction_id = current_faction_id THEN
faction_won = true;
END IF;
SELECT COUNT(DISTINCT player_id) FROM landsraad_task_player_contributions LEFT JOIN landsraad_tasks ON
landsraad_task_player_contributions.task_id = landsraad_tasks.id
WHERE landsraad_tasks.term_id = in_term_id AND landsraad_task_player_contributions.faction_id = current_faction_id
INTO participants_num_faction;
SELECT COUNT(id) FROM landsraad_tasks WHERE landsraad_tasks.term_id = in_term_id
AND landsraad_tasks.winning_faction_id = current_faction_id AND landsraad_tasks.completed = true
INTO tasks_completed;
SELECT COUNT(DISTINCT landsraad_tasks.id) FROM landsraad_task_reveal_state LEFT JOIN landsraad_tasks ON
landsraad_task_reveal_state.task_id = landsraad_tasks.id
WHERE landsraad_tasks.term_id = in_term_id AND landsraad_task_reveal_state.faction_id = current_faction_id AND landsraad_task_reveal_state.revealed = true
INTO tasks_revealed;
RETURN (in_faction_name, term_result, faction_won, participants_num_faction, tasks_completed, tasks_revealed, start_time, end_time)::LandsraadTermTelemetry;
END $function$

View File

@@ -0,0 +1,18 @@
-- landsraad_collect_vote_telemetry(in_term_id bigint, in_winning_faction_id integer) -> TABLE(guild_id bigint, decree_name text, voting_influence integer)
-- oid: 58406 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_collect_vote_telemetry(in_term_id bigint, in_winning_faction_id integer)
RETURNS TABLE(guild_id bigint, decree_name text, voting_influence integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query SELECT guild_contribution.guild_id, landsraad_decrees.decree_name, FLOOR(SUM(guild_contribution.amount))::INTEGER
FROM landsraad_tasks AS tasks
INNER JOIN landsraad_task_guild_contributions AS guild_contribution
ON guild_contribution.task_id = tasks.id AND guild_contribution.faction_id = tasks.winning_faction_id AND tasks.term_id = in_term_id AND guild_contribution.faction_id = in_winning_faction_id
LEFT JOIN landsraad_decree_votes
ON landsraad_decree_votes.guild_id = guild_contribution.guild_id
LEFT JOIN landsraad_decrees
ON landsraad_decree_votes.decree_id = landsraad_decrees.id
GROUP BY (guild_contribution.guild_id, landsraad_decrees.decree_name);
END $function$

View File

@@ -0,0 +1,56 @@
-- landsraad_collect_votes(in_term_id bigint) -> TABLE(elected_decree text, winning_faction_name text, available_decrees text[], guild_votes dune.landsraadguildvotetelemetry[])
-- oid: 58407 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_collect_votes(in_term_id bigint)
RETURNS TABLE(elected_decree text, winning_faction_name text, available_decrees text[], guild_votes dune.landsraadguildvotetelemetry[])
LANGUAGE plpgsql
AS $function$
DECLARE
has_elected_decree BOOL = FALSE;
has_winning_faction BOOL = FALSE;
winning_decree_id BIGINT = NULL;
winning_decree_name TEXT = NULL;
winning_faction_name TEXT = NULL;
winning_faction_id INT = NULL;
available_decrees TEXT[];
vote_telemetry LandsraadGuildVoteTelemetry[];
BEGIN
LOCK TABLE landsraad_decree_term, landsraad_decree_rotation, landsraad_decree_votes IN EXCLUSIVE MODE;
SELECT CASE WHEN landsraad_decree_term.elected_decree_id IS NULL THEN FALSE ELSE TRUE END,
CASE WHEN landsraad_decree_term.winning_faction_id IS NULL THEN FALSE ELSE TRUE END
FROM landsraad_decree_term WHERE term_id = in_term_id INTO has_elected_decree, has_winning_faction;
IF has_winning_faction IS FALSE THEN
RETURN query SELECT NULL, NULL, available_decrees, vote_telemetry;
RETURN;
END IF;
SELECT factions.name, term.winning_faction_id FROM landsraad_decree_term AS term LEFT JOIN factions ON term.winning_faction_id = factions.id WHERE term.term_id = in_term_id INTO winning_faction_name, winning_faction_id;
SELECT ARRAY_AGG(landsraad_decrees.decree_name) FROM landsraad_decree_rotation INNER JOIN landsraad_decrees ON landsraad_decree_rotation.decree_id = landsraad_decrees.id INTO available_decrees;
SELECT ARRAY_AGG((guild_id, decree_name, voting_influence)::LandsraadGuildVoteTelemetry) FROM landsraad_collect_vote_telemetry(in_term_id, winning_faction_id) INTO vote_telemetry;
-- Only resolve votes if the latest term has no elected decree
IF has_elected_decree IS FALSE THEN
WITH
votes AS (SELECT decree_id, SUM(influence) AS amount FROM landsraad_decree_votes GROUP BY decree_id),
max_votes AS (SELECT MAX(amount) AS amount FROM votes)
UPDATE landsraad_decree_term
SET elected_decree_id =
CASE WHEN (SELECT amount FROM max_votes) IS NOT NULL THEN
(SELECT decree_id FROM votes WHERE amount = (SELECT amount FROM max_votes) ORDER BY RANDOM() LIMIT 1)
ELSE
(SELECT decree_id FROM landsraad_decree_rotation ORDER BY RANDOM() LIMIT 1)
END
WHERE term_id = in_term_id
returning elected_decree_id INTO winning_decree_id;
ELSE
SELECT term.elected_decree_id FROM landsraad_decree_term term ORDER BY term_id DESC LIMIT 1 INTO winning_decree_id;
END IF;
SELECT decree_name FROM landsraad_decrees WHERE id = winning_decree_id INTO winning_decree_name;
RETURN query SELECT winning_decree_name, winning_faction_name, available_decrees, vote_telemetry;
END $function$

View File

@@ -0,0 +1,26 @@
-- landsraad_determine_winner(in_term_id bigint) -> text
-- oid: 58408 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_determine_winner(in_term_id bigint)
RETURNS text
LANGUAGE plpgsql
AS $function$
DECLARE
has_winning_faction BOOLEAN = FALSE;
winning_faction_name TEXT = NULL;
BEGIN
SELECT CASE WHEN winning_faction_id IS NULL THEN FALSE ELSE TRUE END FROM landsraad_decree_term WHERE term_id = in_term_id INTO has_winning_faction;
-- only set winning faction if not set already (sysselraad has been secured)
IF NOT has_winning_faction THEN
WITH tasks_completed_by_faction AS (SELECT winning_faction_id AS faction, COUNT(id) AS num_tasks FROM landsraad_tasks WHERE term_id = in_term_id AND winning_faction_id IS NOT NULL GROUP BY (winning_faction_id)),
winner_count AS (SELECT COUNT(faction) AS amount FROM tasks_completed_by_faction WHERE num_tasks = (SELECT MAX(num_tasks) FROM tasks_completed_by_faction) GROUP BY(num_tasks)),
winner AS (SELECT faction FROM tasks_completed_by_faction ORDER BY num_tasks DESC LIMIT 1)
UPDATE landsraad_decree_term SET winning_faction_id = CASE WHEN winner_count.amount = 1 THEN winner.faction ELSE NULL END FROM winner, winner_count;
PERFORM pg_notify('landsraad_notify_channel', 'state_changed');
END IF;
SELECT factions.name FROM landsraad_decree_term AS term LEFT JOIN factions ON term.winning_faction_id = factions.id WHERE term.term_id = in_term_id INTO winning_faction_name;
RETURN winning_faction_name;
END $function$

View File

@@ -0,0 +1,10 @@
-- landsraad_force_end_term(end_term_id bigint) -> void
-- oid: 58409 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_force_end_term(end_term_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
PERFORM landsraad_change_term_end_time(end_term_id, now() AT TIME ZONE 'UTC', false);
END $function$

View File

@@ -0,0 +1,13 @@
-- landsraad_has_term_of_task_ended(in_task_id bigint) -> boolean
-- oid: 58410 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_has_term_of_task_ended(in_task_id bigint)
RETURNS boolean
LANGUAGE plpgsql
AS $function$
DECLARE
term_ended BOOLEAN = FALSE;
BEGIN
SELECT NOW() > term.end_time FROM landsraad_tasks AS task LEFT JOIN landsraad_decree_term AS term ON task.term_id = term.term_id WHERE task.id = in_task_id INTO term_ended;
RETURN term_ended;
END $function$

View File

@@ -0,0 +1,30 @@
-- landsraad_initialize_system(number_of_weeks_term_retention integer, number_of_nominated_decrees integer, in_end_time timestamp without time zone, in_test_term boolean, faction_names text[], decrees dune.landsraaddecree[], tasks dune.landsraadtask[], task_rewards dune.landsraadtaskreward[]) -> TABLE(term_id bigint, reigning_faction_name text, active_decree_name text, winning_faction_name text, elected_decree_name text, start_time timestamp without time zone, end_time timestamp without time zone)
-- oid: 58411 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_initialize_system(number_of_weeks_term_retention integer, number_of_nominated_decrees integer, in_end_time timestamp without time zone, in_test_term boolean, faction_names text[], decrees dune.landsraaddecree[], tasks dune.landsraadtask[], task_rewards dune.landsraadtaskreward[])
RETURNS TABLE(term_id bigint, reigning_faction_name text, active_decree_name text, winning_faction_name text, elected_decree_name text, start_time timestamp without time zone, end_time timestamp without time zone)
LANGUAGE plpgsql
AS $function$
DECLARE
current_term_id BIGINT = NULL;
BEGIN
LOCK TABLE landsraad_decree_term, landsraad_decree_rotation, landsraad_decrees, landsraad_decree_votes IN EXCLUSIVE MODE;
CALL landsraad_update_decrees(decrees);
CALL landsraad_update_factions(faction_names);
SELECT term.term_id FROM landsraad_decree_term term ORDER BY term.term_id DESC LIMIT 1 INTO current_term_id;
IF FOUND THEN
RETURN query SELECT term.term_id, reigning_faction.name, active_decree.decree_name, winning_faction.name, elected_decree.decree_name, (term.start_time AT TIME ZONE 'UTC')::TIMESTAMP, (term.end_time AT TIME ZONE 'UTC')::TIMESTAMP
FROM landsraad_decree_term term
LEFT JOIN factions reigning_faction ON term.reigning_faction_id = reigning_faction.id
LEFT JOIN landsraad_decrees active_decree ON term.active_decree_id = active_decree.id
LEFT JOIN factions winning_faction ON term.winning_faction_id = winning_faction.id
LEFT JOIN landsraad_decrees elected_decree ON term.elected_decree_id = elected_decree.id
WHERE term.term_id = current_term_id;
ELSE
RETURN query SELECT term.term_id, term.reigning_faction_name, term.active_decree_name, term.winning_faction_name, term.elected_decree_name, term.start_time, term.end_time
FROM landsraad_initialize_term(number_of_weeks_term_retention, number_of_nominated_decrees, in_end_time, in_test_term, tasks, task_rewards) AS term;
END IF;
END $function$

View File

@@ -0,0 +1,41 @@
-- landsraad_initialize_term(number_of_weeks_term_retention integer, number_of_nominated_decrees integer, in_end_time timestamp without time zone, in_test_term boolean, tasks dune.landsraadtask[], task_rewards dune.landsraadtaskreward[]) -> TABLE(term_id bigint, reigning_faction_name text, active_decree_name text, winning_faction_name text, elected_decree_name text, start_time timestamp without time zone, end_time timestamp without time zone)
-- oid: 58412 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_initialize_term(number_of_weeks_term_retention integer, number_of_nominated_decrees integer, in_end_time timestamp without time zone, in_test_term boolean, tasks dune.landsraadtask[], task_rewards dune.landsraadtaskreward[])
RETURNS TABLE(term_id bigint, reigning_faction_name text, active_decree_name text, winning_faction_name text, elected_decree_name text, start_time timestamp without time zone, end_time timestamp without time zone)
LANGUAGE plpgsql
AS $function$
DECLARE
reigning_faction_id SMALLINT = NULL;
active_decree_id BIGINT = NULL;
last_active_decree_id BIGINT = NULL;
current_term_id BIGINT = NULL;
BEGIN
LOCK TABLE landsraad_decrees, landsraad_decree_term, landsraad_decree_rotation, landsraad_decree_votes IN EXCLUSIVE MODE;
-- read winning faction, elected and active decree from previous term
SELECT term.winning_faction_id, term.elected_decree_id, term.active_decree_id INTO reigning_faction_id, active_decree_id, last_active_decree_id FROM landsraad_decree_term term ORDER BY term.term_id DESC LIMIT 1;
-- insert new term
INSERT INTO landsraad_decree_term (reigning_faction_id, active_decree_id, start_time, end_time, test_term) VALUES(reigning_faction_id, active_decree_id, now(), in_end_time AT TIME ZONE 'UTC', in_test_term) RETURNING landsraad_decree_term.term_id INTO current_term_id;
-- cleanup old terms, except for previous one
DELETE FROM landsraad_decree_term term WHERE term.end_time < (now() - MAKE_INTERVAL(weeks => number_of_weeks_term_retention)) AND term.term_id < current_term_id - 1;
-- insert tasks for new term
CALL landsraad_insert_tasks(current_term_id, tasks, task_rewards);
-- insert decrees for voting
CALL landsraad_nominate_decrees_for_voting(last_active_decree_id, number_of_nominated_decrees);
-- clean expired landsraad contracts
PERFORM journey_story_node_cooldown_delete_expired(now() at time zone 'utc');
RETURN query SELECT term.term_id, reigning_faction.name, active_decree.decree_name, winning_faction.name, elected_decree.decree_name, (term.start_time AT TIME ZONE 'UTC')::TIMESTAMP, (term.end_time AT TIME ZONE 'UTC')::TIMESTAMP
FROM landsraad_decree_term term
LEFT JOIN factions reigning_faction ON term.reigning_faction_id = reigning_faction.id
LEFT JOIN landsraad_decrees active_decree ON term.active_decree_id = active_decree.id
LEFT JOIN factions winning_faction ON term.winning_faction_id = winning_faction.id
LEFT JOIN landsraad_decrees elected_decree ON term.elected_decree_id = elected_decree.id
WHERE term.term_id = current_term_id;
END $function$

View File

@@ -0,0 +1,49 @@
-- landsraad_insert_task_progress(in_term_id bigint, in_player_id bigint, in_guild_id bigint, in_house_name text, in_faction_progress integer, in_guild_progress real, in_player_progress real, in_timestamp timestamp without time zone) -> void
-- oid: 58413 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_insert_task_progress(in_term_id bigint, in_player_id bigint, in_guild_id bigint, in_house_name text, in_faction_progress integer, in_guild_progress real, in_player_progress real, in_timestamp timestamp without time zone)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
guild_id BIGINT = NULL;
faction_id BIGINT = NULL;
faction_name TEXT = NULL;
progress_id BIGINT = NULL;
BEGIN
IF in_player_id IS NULL THEN
-- use guild_id
SELECT guilds.guild_id, factions.id, factions.name FROM guild_members
INNER JOIN guilds ON guild_members.guild_id = guilds.guild_id
LEFT JOIN factions ON guilds.guild_faction = factions.id
WHERE guild_members.guild_id = in_guild_id INTO guild_id, faction_id, faction_name;
ELSE
-- use player_id
SELECT guilds.guild_id, factions.id, factions.name FROM guild_members
INNER JOIN guilds ON guild_members.guild_id = guilds.guild_id
LEFT JOIN factions ON guilds.guild_faction = factions.id
WHERE guild_members.player_id = in_player_id INTO guild_id, faction_id, faction_name;
END IF;
IF guild_id IS NULL THEN
RAISE EXCEPTION 'Cannot insert landsraad task progress, player % not in guild', in_player_id;
END IF;
IF faction_id IS NULL OR faction_name = 'None' THEN
RAISE EXCEPTION 'Cannot insert landsraad task progress, guild % not aligned to faction', guild_id;
END IF;
INSERT INTO landsraad_task_progress (faction_id, task_id, faction_progress, guild_progress, player_progress, timestamp)
SELECT faction_id, tasks.id, in_faction_progress, in_guild_progress, in_player_progress, in_timestamp AT TIME ZONE 'UTC'
FROM landsraad_tasks AS tasks
WHERE tasks.term_id = in_term_id AND tasks.house_name = in_house_name
RETURNING id INTO progress_id;
IF in_player_id IS NOT NULL THEN
INSERT INTO landsraad_task_progress_player (progress_id, player_id) VALUES (progress_id, in_player_id);
END IF;
INSERT INTO landsraad_task_progress_guild (progress_id, guild_id) VALUES (progress_id, guild_id);
END $function$

View File

@@ -0,0 +1,15 @@
-- landsraad_insert_task_progress_batched(in_term_id bigint, in_task_progress dune.landsraadtaskprogress[]) -> void
-- oid: 58414 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_insert_task_progress_batched(in_term_id bigint, in_task_progress dune.landsraadtaskprogress[])
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
task_progress record = NULL;
BEGIN
FOREACH task_progress IN ARRAY in_task_progress
LOOP
PERFORM landsraad_insert_task_progress(in_term_id, task_progress.player_id, task_progress.guild_id ,task_progress.house_name, task_progress.faction_progress, task_progress.guild_progress, task_progress.player_progress, task_progress.timestamp);
END LOOP;
END $function$

View File

@@ -0,0 +1,23 @@
-- landsraad_insert_task_progress_faction(in_term_id bigint, in_faction_name text, in_house_name text, in_faction_progress integer, in_guild_progress real, in_player_progress real) -> void
-- oid: 58415 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_insert_task_progress_faction(in_term_id bigint, in_faction_name text, in_house_name text, in_faction_progress integer, in_guild_progress real, in_player_progress real)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
player_id BIGINT = NULL;
guild_id BIGINT = NULL;
BEGIN
SELECT guild_members.player_id, guilds.guild_id FROM guilds
LEFT JOIN factions ON guilds.guild_faction = factions.id
RIGHT JOIN guild_members ON guild_members.guild_id = guilds.guild_id
WHERE factions.name = in_faction_name
ORDER BY random() LIMIT 1 INTO player_id, guild_id;
IF player_id IS NULL THEN
RAISE EXCEPTION 'Cannot insert landsraad task progress for faction %, no guild member found', in_faction_name;
END IF;
PERFORM landsraad_insert_task_progress(in_term_id, player_id, guild_id, in_house_name, in_faction_progress, in_guild_progress, in_player_progress, now() AT TIME ZONE 'UTC');
END $function$

View File

@@ -0,0 +1,29 @@
-- landsraad_insert_task_progress_random(in_term_id bigint, in_faction_names text[], in_num_rows integer) -> void
-- oid: 58416 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_insert_task_progress_random(in_term_id bigint, in_faction_names text[], in_num_rows integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
player_id BIGINT = NULL;
guild_id BIGINT = NULL;
house_name TEXT = NULL;
random_amount INTEGER = NULL;
BEGIN
FOR r IN 1..in_num_rows
LOOP
SELECT guild_members.player_id, guilds.guild_id FROM guilds
LEFT JOIN factions ON guilds.guild_faction = factions.id
RIGHT JOIN guild_members ON guild_members.guild_id = guilds.guild_id
WHERE factions.name = ANY(in_faction_names)
ORDER BY random() LIMIT 1 INTO player_id, guild_id;
SELECT tasks.house_name FROM landsraad_tasks tasks
WHERE tasks.term_id = in_term_id
ORDER BY random() LIMIT 1 INTO house_name;
SELECT (floor(random() * 5) + 1)::INTEGER * 10 INTO random_amount;
IF player_id IS NOT NULL AND house_name IS NOT NULL THEN
PERFORM landsraad_insert_task_progress(in_term_id, player_id, guild_id, house_name, random_amount * 10, (random_amount * 0.1)::REAL, (random_amount * 10)::REAL, now() AT TIME ZONE 'UTC');
END IF;
END LOOP;
END $function$

View File

@@ -0,0 +1,31 @@
-- landsraad_load_current_rotation(in_term_id bigint) -> TABLE(decree_name text, received_votes integer, open_votes integer)
-- oid: 58418 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_current_rotation(in_term_id bigint)
RETURNS TABLE(decree_name text, received_votes integer, open_votes integer)
LANGUAGE plpgsql
AS $function$
DECLARE
open_votes INTEGER = 0;
BEGIN
WITH open_guild_votes AS (
SELECT guild_contribution.guild_id, FLOOR(SUM(guild_contribution.amount))::INTEGER AS voting_influence
FROM landsraad_tasks AS tasks
INNER JOIN landsraad_task_guild_contributions AS guild_contribution
ON guild_contribution.task_id = tasks.id AND guild_contribution.faction_id = tasks.winning_faction_id
LEFT JOIN landsraad_decree_votes
ON guild_contribution.guild_id = landsraad_decree_votes.guild_id
WHERE tasks.term_id = in_term_id AND tasks.winning_faction_id = (SELECT winning_faction_id FROM landsraad_decree_term WHERE term_id = in_term_id)
AND landsraad_decree_votes.guild_id IS NULL
GROUP BY (guild_contribution.guild_id, guild_contribution.faction_id)
)
SELECT SUM(voting_influence)::INTEGER FROM open_guild_votes INTO open_votes;
RETURN query (
SELECT decrees.decree_name, SUM(decree_votes.influence)::INTEGER AS received_votes, open_votes
FROM landsraad_decree_rotation AS rotation
INNER JOIN landsraad_decrees AS decrees ON rotation.decree_id = decrees.id
LEFT JOIN landsraad_decree_votes AS decree_votes ON decree_votes.decree_id = rotation.decree_id
GROUP BY rotation.decree_id, decrees.decree_name
);
END $function$

View File

@@ -0,0 +1,55 @@
-- landsraad_load_current_term() -> TABLE(term_id bigint, reigning_faction_name text, active_decree_name text, winning_faction_name text, elected_decree_name text, start_time timestamp without time zone, end_time timestamp without time zone, tasks dune.landsraadtask[], term_task_rewards dune.landsraadtaskreward[], winner_history text[], testterm boolean)
-- oid: 58419 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_current_term()
RETURNS TABLE(term_id bigint, reigning_faction_name text, active_decree_name text, winning_faction_name text, elected_decree_name text, start_time timestamp without time zone, end_time timestamp without time zone, tasks dune.landsraadtask[], term_task_rewards dune.landsraadtaskreward[], winner_history text[], testterm boolean)
LANGUAGE plpgsql
AS $function$
DECLARE
current_term_id BIGINT = NULL;
reigning_faction_name TEXT = NULL;
active_decree_name TEXT = NULL;
winning_faction_name TEXT = NULL;
elected_decree_name TEXT = NULL;
start_time TIMESTAMP = NULL;
end_time TIMESTAMP = NULL;
test_term BOOL = NULL;
term_tasks LandsraadTask[];
term_task_rewards LandsraadTaskReward[];
term_winner_history TEXT[];
BEGIN
SELECT term.term_id, reigning_faction.name, active_decree.decree_name, winning_faction.name, elected_decree.decree_name, (term.start_time AT TIME ZONE 'UTC')::TIMESTAMP, (term.end_time AT TIME ZONE 'UTC')::TIMESTAMP, term.test_term
INTO current_term_id, reigning_faction_name, active_decree_name, winning_faction_name, elected_decree_name, start_time, end_time, test_term
FROM landsraad_decree_term AS term
LEFT JOIN factions AS reigning_faction ON term.reigning_faction_id = reigning_faction.id
LEFT JOIN landsraad_decrees AS active_decree ON term.active_decree_id = active_decree.id
LEFT JOIN factions AS winning_faction ON term.winning_faction_id = winning_faction.id
LEFT JOIN landsraad_decrees AS elected_decree ON term.elected_decree_id = elected_decree.id
ORDER BY term.start_time DESC LIMIT 1;
SELECT ARRAY_AGG((tasks.board_index, tasks.house_name, tasks.completed, COALESCE(factions_winner.name, ''), tasks.sysselraad, tasks.goal_amount)::LandsraadTask)
INTO term_tasks
FROM landsraad_tasks AS tasks
LEFT JOIN factions AS factions_winner ON tasks.winning_faction_id = factions_winner.id
WHERE tasks.term_id = current_term_id;
WITH task_rewards AS (
SELECT tasks.house_name AS house_name, rewards.threshold AS threshold, rewards.template_id AS template_id, rewards.amount AS amount
FROM landsraad_task_rewards AS rewards
LEFT JOIN landsraad_tasks AS tasks ON rewards.task_id = tasks.id
WHERE tasks.term_id = current_term_id ORDER BY rewards.task_id ASC, rewards.threshold ASC
)
SELECT ARRAY_AGG((house_name, threshold, template_id, amount)::LandsraadTaskReward) FROM task_rewards INTO term_task_rewards;
SELECT ARRAY_AGG(winning_factions.name::TEXT)
INTO term_winner_history
FROM
(SELECT factions.name
FROM landsraad_decree_term
LEFT JOIN factions ON landsraad_decree_term.reigning_faction_id = factions.id
ORDER BY landsraad_decree_term.term_id DESC) AS winning_factions;
IF current_term_id IS NOT NULL THEN
RETURN query SELECT current_term_id, reigning_faction_name, active_decree_name, winning_faction_name, elected_decree_name, start_time, end_time, term_tasks, term_task_rewards, term_winner_history, test_term;
END IF;
END $function$

View File

@@ -0,0 +1,17 @@
-- landsraad_load_guild_contribution(in_term_id bigint, in_guild_id bigint, in_faction_id bigint) -> TABLE(voting_influence real)
-- oid: 58420 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_guild_contribution(in_term_id bigint, in_guild_id bigint, in_faction_id bigint)
RETURNS TABLE(voting_influence real)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query (
SELECT SUM(guild_contribution.amount)::REAL
FROM landsraad_tasks AS tasks
INNER JOIN landsraad_task_guild_contributions AS guild_contribution
ON guild_contribution.task_id = tasks.id
WHERE tasks.term_id = in_term_id AND guild_contribution.guild_id = in_guild_id AND guild_contribution.faction_id = in_faction_id
GROUP BY (guild_contribution.guild_id, guild_contribution.faction_id)
);
END $function$

View File

@@ -0,0 +1,24 @@
-- landsraad_load_guild_contributions(in_term_id bigint, in_num_guilds integer, in_faction_names text[]) -> TABLE(faction_name text, guild_name text, voting_influence real)
-- oid: 58421 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_guild_contributions(in_term_id bigint, in_num_guilds integer, in_faction_names text[])
RETURNS TABLE(faction_name text, guild_name text, voting_influence real)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query (
SELECT factions.name, top_guilds.guild_name, top_guilds.influence FROM factions
CROSS JOIN LATERAL (
SELECT guilds.guild_name as guild_name, SUM(guild_contribution.amount)::REAL AS influence
FROM landsraad_tasks AS tasks
INNER JOIN landsraad_task_guild_contributions AS guild_contribution
ON guild_contribution.task_id = tasks.id AND guild_contribution.faction_id = factions.id
JOIN guilds
ON guild_contribution.guild_id = guilds.guild_id
WHERE tasks.term_id = in_term_id
GROUP BY (guilds.guild_id, guilds.guild_name)
ORDER BY influence DESC LIMIT in_num_guilds
) AS top_guilds
WHERE factions.name = ANY(in_faction_names)
);
END $function$

View File

@@ -0,0 +1,28 @@
-- landsraad_load_guild_vote(in_term_id bigint, in_player_id bigint) -> TABLE(decree_name text, voting_influence real)
-- oid: 58422 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_guild_vote(in_term_id bigint, in_player_id bigint)
RETURNS TABLE(decree_name text, voting_influence real)
LANGUAGE plpgsql
AS $function$
DECLARE
term_winning_faction_id SMALLINT = NULL;
player_guild_id BIGINT = NULL;
guild_faction_id SMALLINT = NULL;
BEGIN
SELECT guilds.guild_id, guilds.guild_faction FROM guild_members JOIN guilds ON guild_members.guild_id = guilds.guild_id WHERE guild_members.player_id = in_player_id INTO player_guild_id, guild_faction_id;
RETURN query (
SELECT
CASE WHEN player_guild_id IS NOT NULL AND guild_faction_id IS NOT NULL THEN
(SELECT COALESCE(decrees.decree_name, '') FROM landsraad_decree_votes AS votes LEFT JOIN landsraad_decrees AS decrees ON votes.decree_id = decrees.id WHERE votes.guild_id = player_guild_id)
ELSE
''
END,
CASE WHEN player_guild_id IS NOT NULL AND guild_faction_id IS NOT NULL THEN
(SELECT landsraad_load_guild_contribution(in_term_id, player_guild_id, guild_faction_id))
ELSE
0
END
);
END $function$

View File

@@ -0,0 +1,10 @@
-- landsraad_load_house_rewards(in_player_id bigint) -> TABLE(house_name text, template_id text, amount integer, last_updated timestamp without time zone)
-- oid: 58423 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_house_rewards(in_player_id bigint)
RETURNS TABLE(house_name text, template_id text, amount integer, last_updated timestamp without time zone)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query (SELECT rewards.house_name, rewards.template_id, rewards.amount, (rewards.last_updated AT TIME ZONE 'UTC')::TIMESTAMP FROM landsraad_house_rewards AS rewards WHERE player_id = in_player_id AND rewards.amount > 0);
END $function$

View File

@@ -0,0 +1,15 @@
-- landsraad_load_player_contributions(in_term_id bigint, in_player_ids bigint[]) -> TABLE(player_id bigint, board_index smallint, amount integer)
-- oid: 58424 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_player_contributions(in_term_id bigint, in_player_ids bigint[])
RETURNS TABLE(player_id bigint, board_index smallint, amount integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query (
SELECT contributions.player_id, tasks.board_index, FLOOR(SUM(contributions.amount))::INTEGER FROM landsraad_task_player_contributions AS contributions
INNER JOIN landsraad_tasks AS tasks ON contributions.task_id = tasks.id
WHERE tasks.term_id = in_term_id AND contributions.player_id = ANY(in_player_ids)
GROUP BY contributions.player_id, tasks.board_index
);
END $function$

View File

@@ -0,0 +1,18 @@
-- landsraad_load_task_faction_progress(in_term_id bigint) -> TABLE(task_board_index integer, faction_name text, progress integer)
-- oid: 58425 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_task_faction_progress(in_term_id bigint)
RETURNS TABLE(task_board_index integer, faction_name text, progress integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query SELECT CAST(faction_progress.board_index AS INTEGER), faction_progress.name, CAST(faction_progress.progress AS INTEGER) FROM
(SELECT tasks.id, tasks.board_index, factions.name, SUM(faction_contribution.amount) AS progress
FROM landsraad_tasks tasks
INNER JOIN landsraad_task_faction_contributions faction_contribution
ON faction_contribution.task_id = tasks.id
LEFT JOIN factions factions
ON factions.id = faction_contribution.faction_id
WHERE tasks.term_id = in_term_id
GROUP BY (tasks.id, tasks.board_index, factions.name)) AS faction_progress;
END $function$

View File

@@ -0,0 +1,16 @@
-- landsraad_load_task_faction_reveal_state(in_term_id bigint) -> TABLE(task_board_index integer, faction_name text, reveal_state boolean, time_stamp timestamp without time zone)
-- oid: 58426 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_task_faction_reveal_state(in_term_id bigint)
RETURNS TABLE(task_board_index integer, faction_name text, reveal_state boolean, time_stamp timestamp without time zone)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query SELECT CAST(tasks.board_index AS INTEGER), factions.name, reveal_state.revealed, (reveal_state.timestamp AT TIME ZONE 'UTC')::TIMESTAMP
FROM landsraad_tasks tasks
INNER JOIN landsraad_task_reveal_state reveal_state
ON reveal_state.task_id = tasks.id
INNER JOIN factions factions
ON factions.id = reveal_state.faction_id
WHERE tasks.term_id = in_term_id;
END $function$

View File

@@ -0,0 +1,20 @@
-- landsraad_load_term_progress(in_term_id bigint, in_num_guilds integer, in_faction_names text[], in_player_ids bigint[]) -> TABLE(faction_progress dune.landsraadtaskfactionprogress[], faction_reveal_state dune.landsraadtaskfactionrevealstate[], guild_contributions dune.landsraadguildcontribution[], player_contributions dune.landsraadplayercontribution[])
-- oid: 58427 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_load_term_progress(in_term_id bigint, in_num_guilds integer, in_faction_names text[], in_player_ids bigint[])
RETURNS TABLE(faction_progress dune.landsraadtaskfactionprogress[], faction_reveal_state dune.landsraadtaskfactionrevealstate[], guild_contributions dune.landsraadguildcontribution[], player_contributions dune.landsraadplayercontribution[])
LANGUAGE plpgsql
AS $function$
DECLARE
term_faction_progress LandsraadTaskFactionProgress[];
term_faction_reveal_state LandsraadTaskFactionRevealState[];
term_guild_contributions LandsraadGuildContribution[];
term_player_contributions LandsraadPlayerContribution[];
BEGIN
SELECT ARRAY_AGG((task_board_index, faction_name, progress)::LandsraadTaskFactionProgress) FROM landsraad_load_task_faction_progress(in_term_id) INTO term_faction_progress;
SELECT ARRAY_AGG((task_board_index, faction_name, reveal_state, time_stamp)::LandsraadTaskFactionRevealState) FROM landsraad_load_task_faction_reveal_state(in_term_id) INTO term_faction_reveal_state;
SELECT ARRAY_AGG((faction_name, guild_name, voting_influence)::LandsraadGuildContribution) FROM landsraad_load_guild_contributions(in_term_id, in_num_guilds, in_faction_names) INTO term_guild_contributions;
SELECT ARRAY_AGG((player_id, board_index, amount)::LandsraadPlayerContribution) FROM landsraad_load_player_contributions(in_term_id, in_player_ids) INTO term_player_contributions;
RETURN query SELECT term_faction_progress, term_faction_reveal_state, term_guild_contributions, term_player_contributions;
END $function$

View File

@@ -0,0 +1,11 @@
-- landsraad_notify_house_rewards_changed() -> trigger
-- oid: 58429 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_notify_house_rewards_changed()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
PERFORM pg_notify('landsraad_notify_channel', format('house_rewards_changed#{"PlayerId" : %s}', NEW.player_id));
RETURN NULL;
END $function$

View File

@@ -0,0 +1,48 @@
-- landsraad_perform_daily_task_reveal(in_term_id bigint, in_faction_names text[], in_house_names_to_reveal text[], in_reveal_day integer) -> TABLE(faction_name text, house_name text, board_index integer)
-- oid: 58430 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_perform_daily_task_reveal(in_term_id bigint, in_faction_names text[], in_house_names_to_reveal text[], in_reveal_day integer)
RETURNS TABLE(faction_name text, house_name text, board_index integer)
LANGUAGE plpgsql
AS $function$
DECLARE
last_processed_reveal_day INTEGER = NULL;
faction_ids BIGINT[];
newly_revealed_task_ids BIGINT[];
newly_revealed_house_names TEXT[];
newly_revealed_task_board_indices INTEGER[];
faction_of_newly_revealed_task BIGINT[];
BEGIN
LOCK TABLE landsraad_decree_term IN EXCLUSIVE MODE;
SELECT landsraad_decree_term.last_processed_reveal_day FROM landsraad_decree_term WHERE term_id = in_term_id INTO last_processed_reveal_day;
IF last_processed_reveal_day < in_reveal_day THEN
SELECT ARRAY_AGG(factions.id) FROM factions WHERE factions.name = ANY(in_faction_names) INTO faction_ids;
WITH revealed_task(id, faction_id) AS (
SELECT task.id, faction.id FROM landsraad_tasks AS task
CROSS JOIN UNNEST(faction_ids) AS faction(id)
WHERE task.house_name = ANY (in_house_names_to_reveal) AND task.term_id = in_term_id)
--filter out tasks already revealed from data to not stomp reveal date or send duplicate reveal event in telemetry
SELECT ARRAY_AGG(task.id), ARRAY_AGG(task.house_name), ARRAY_AGG(task.board_index), ARRAY_AGG(revealed_task.faction_id) FROM revealed_task
INNER JOIN landsraad_tasks AS task ON task.id = revealed_task.id
LEFT JOIN landsraad_task_reveal_state AS reveal_state ON task.id = reveal_state.task_id AND revealed_task.faction_id = reveal_state.faction_id
WHERE reveal_state.revealed IS NULL OR reveal_state.revealed IS FALSE
INTO newly_revealed_task_ids, newly_revealed_house_names, newly_revealed_task_board_indices, faction_of_newly_revealed_task;
INSERT INTO landsraad_task_reveal_state (task_id, faction_id, revealed, timestamp) SELECT UNNEST(newly_revealed_task_ids), UNNEST(faction_of_newly_revealed_task), TRUE, now()
ON CONFLICT(task_id, faction_id) DO UPDATE SET revealed = TRUE, timestamp = now();
UPDATE landsraad_decree_term SET last_processed_reveal_day = in_reveal_day WHERE term_id = in_term_id;
IF cardinality(newly_revealed_task_ids) > 0 THEN
PERFORM pg_notify('landsraad_notify_channel', 'progress_updated#{"changed": true}');
END IF;
END IF;
RETURN query
WITH newly_revealed_tasks (house_name, board_index, faction_id) AS (
SELECT UNNEST(newly_revealed_house_names), UNNEST(newly_revealed_task_board_indices), UNNEST(faction_of_newly_revealed_task))
SELECT factions.name, newly_revealed_tasks.house_name, newly_revealed_tasks.board_index FROM newly_revealed_tasks JOIN factions ON newly_revealed_tasks.faction_id = factions.id;
END $function$

View File

@@ -0,0 +1,27 @@
-- landsraad_process_house_rewards() -> trigger
-- oid: 58431 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_process_house_rewards()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
WITH
task_player_contribution_threshold_passed (player_id, house_name, template_id, amount) AS (
SELECT NEW.player_id, tasks.house_name, task_rewards.template_id, task_rewards.amount
FROM landsraad_task_rewards as task_rewards
INNER JOIN landsraad_tasks AS tasks
ON task_rewards.task_id = tasks.id
LEFT JOIN landsraad_task_player_contributions AS player_contributions
ON player_contributions.task_id = tasks.id
WHERE task_rewards.task_id = NEW.task_id
AND tasks.id = NEW.task_id
AND player_contributions.player_id = NEW.player_id
AND COALESCE(OLD.amount, 0) < task_rewards.threshold
AND NEW.amount >= task_rewards.threshold)
INSERT INTO landsraad_house_rewards (player_id, house_name, template_id, amount, last_updated)
SELECT player_id, house_name, template_id, SUM(amount), CURRENT_TIMESTAMP FROM task_player_contribution_threshold_passed GROUP BY player_id, house_name, template_id
ON CONFLICT (player_id, house_name, template_id) DO UPDATE SET amount = landsraad_house_rewards.amount + excluded.amount, last_updated = CURRENT_TIMESTAMP;
RETURN NULL;
END $function$

View File

@@ -0,0 +1,103 @@
-- landsraad_process_task_progress(max_rows integer) -> void
-- oid: 58432 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_process_task_progress(max_rows integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
task_progress RECORD = NULL;
current_term_id BIGINT = NULL;
last_progress_id BIGINT = NULL;
old_processed_id BIGINT = NULL;
new_processed_id BIGINT = NULL;
new_amount INTEGER = 0;
player BIGINT = NULL;
guild BIGINT = NULL;
notify_guild_ids BIGINT[];
guild_ids_json JSON = NULL;
BEGIN
LOCK TABLE landsraad_task_progress_processed IN EXCLUSIVE MODE;
SELECT term_id FROM landsraad_decree_term ORDER BY start_time DESC LIMIT 1 INTO current_term_id;
SELECT id FROM landsraad_task_progress ORDER BY id DESC LIMIT 1 INTO last_progress_id;
SELECT last_processed_id FROM landsraad_task_progress_processed INTO old_processed_id;
-- read batch of rows sorted by id, process ordered by timestamp
FOR task_progress IN
WITH progress_batch AS (
SELECT landsraad_task_progress.id, landsraad_task_progress.faction_id, landsraad_task_progress.task_id,
landsraad_task_progress.faction_progress, landsraad_task_progress.guild_progress, landsraad_task_progress.player_progress, landsraad_task_progress.timestamp,
task_progress_players.players, task_progress_guilds.guilds
FROM landsraad_task_progress,
LATERAL (SELECT ARRAY_AGG(player_id) AS players FROM landsraad_task_progress_player WHERE landsraad_task_progress_player.progress_id = landsraad_task_progress.id) AS task_progress_players,
LATERAL (SELECT ARRAY_AGG(guild_id) AS guilds FROM landsraad_task_progress_guild WHERE landsraad_task_progress_guild.progress_id = landsraad_task_progress.id) AS task_progress_guilds
WHERE CASE WHEN old_processed_id IS NOT NULL THEN id > old_processed_id ELSE TRUE END
ORDER BY id LIMIT MAX_ROWS
)
SELECT id, faction_id, task_id, players, guilds, faction_progress, guild_progress, player_progress FROM progress_batch ORDER BY timestamp
LOOP
IF NOT (SELECT landsraad_has_term_of_task_ended(task_progress.task_id)) THEN
-- player progress is allowed to happen even if the task was already completed
IF task_progress.players IS NOT NULL THEN
FOREACH player IN ARRAY task_progress.players
LOOP
INSERT INTO landsraad_task_player_contributions AS player_contribution (player_id, faction_id, task_id, amount)
VALUES (player, task_progress.faction_id, task_progress.task_id, task_progress.player_progress)
ON CONFLICT (player_id, faction_id, task_id)
DO UPDATE SET amount = player_contribution.amount + task_progress.player_progress;
END LOOP;
END IF;
IF NOT (SELECT landsraad_task_has_been_completed(task_progress.task_id)) THEN
IF task_progress.guilds IS NOT NULL THEN
FOREACH guild IN ARRAY task_progress.guilds
LOOP
-- only insert to guild contribution if no vote has been placed
IF (SELECT NOT EXISTS (SELECT 1 FROM landsraad_decree_votes WHERE landsraad_decree_votes.guild_id = guild)) THEN
INSERT INTO landsraad_task_guild_contributions AS guild_contribution (guild_id, faction_id, task_id, amount)
VALUES (guild, task_progress.faction_id, task_progress.task_id, task_progress.guild_progress)
ON CONFLICT (guild_id, faction_id, task_id)
DO UPDATE SET amount = guild_contribution.amount + task_progress.guild_progress;
notify_guild_ids = notify_guild_ids || guild;
END IF;
END LOOP;
END IF;
INSERT INTO landsraad_task_faction_contributions AS faction_contribution (faction_id, task_id, amount)
VALUES (task_progress.faction_id, task_progress.task_id, task_progress.faction_progress)
ON CONFLICT (faction_id, task_id)
DO UPDATE SET amount = faction_contribution.amount + task_progress.faction_progress;
END IF;
END IF;
new_processed_id = task_progress.id;
END LOOP;
IF new_processed_id IS NOT NULL THEN
IF old_processed_id IS NULL THEN
INSERT INTO landsraad_task_progress_processed (last_processed_id) VALUES (new_processed_id);
ELSE
UPDATE landsraad_task_progress_processed SET last_processed_id = new_processed_id;
END IF;
END IF;
IF last_progress_id > new_processed_id THEN
PERFORM pg_notify('landsraad_notify_channel', format('progress_pressure#{"UnprocessedCount": %s}', last_progress_id - new_processed_id));
END IF;
IF new_processed_id > old_processed_id THEN
PERFORM pg_notify('landsraad_notify_channel', 'progress_updated#{"changed": true}');
ELSE
PERFORM pg_notify('landsraad_notify_channel', 'progress_updated#{"changed": false}');
END IF;
IF cardinality(notify_guild_ids) > 0 THEN
SELECT json_agg(DISTINCT guild_id) FROM (SELECT unnest(notify_guild_ids) guild_id) guilds INTO guild_ids_json;
PERFORM pg_notify('landsraad_notify_channel', format('guild_vote_changed#{"GuildIds": %s}', guild_ids_json));
END IF;
END $function$

View File

@@ -0,0 +1,13 @@
-- landsraad_task_has_been_completed(in_task_id bigint) -> boolean
-- oid: 58433 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_task_has_been_completed(in_task_id bigint)
RETURNS boolean
LANGUAGE plpgsql
AS $function$
DECLARE
task_completed BOOLEAN = FALSE;
BEGIN
SELECT task.completed FROM landsraad_tasks AS task WHERE task.id = in_task_id INTO task_completed;
RETURN task_completed;
END $function$

View File

@@ -0,0 +1,28 @@
-- landsraad_update_task_faction_reveal_state(in_term_id bigint, in_task_board_index integer, faction_name text, reveal_state boolean) -> void
-- oid: 58436 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_update_task_faction_reveal_state(in_term_id bigint, in_task_board_index integer, faction_name text, reveal_state boolean)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
taskid BIGINT = NULL;
factionid BIGINT = NULL;
BEGIN
SELECT id FROM landsraad_tasks tasks WHERE tasks.board_index = in_task_board_index AND tasks.term_id = in_term_id INTO taskid;
IF taskid IS NULL THEN
RAISE EXCEPTION 'Cannot update landsraad task reveal state, no task id for index % term %', in_task_board_index, in_term_id;
END IF;
SELECT id FROM factions WHERE factions.name = faction_name INTO factionid;
IF factionid IS NULL OR faction_name = 'None' THEN
RAISE EXCEPTION 'Cannot update landsraad task reveal state, invalid faction (%)', faction_name;
END IF;
INSERT INTO landsraad_task_reveal_state (task_id, faction_id, revealed, timestamp) VALUES (taskid, factionid, reveal_state, now()) ON CONFLICT(task_id, faction_id) DO UPDATE
SET revealed = reveal_state, timestamp = now();
PERFORM pg_notify('landsraad_notify_channel', 'progress_updated#{"changed": true}');
END $function$

View File

@@ -0,0 +1,32 @@
-- landsraad_withdraw_house_reward(in_player_id bigint, in_house_rewards dune.landsraadplayerhousereward[]) -> void
-- oid: 58437 kind: FUNCTION category: landsraad
CREATE OR REPLACE FUNCTION dune.landsraad_withdraw_house_reward(in_player_id bigint, in_house_rewards dune.landsraadplayerhousereward[])
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
current_amount INTEGER = NULL;
house_reward record = NULL;
grouped_house_rewards LandsraadPlayerHouseReward[];
BEGIN
LOCK TABLE landsraad_house_rewards IN EXCLUSIVE MODE;
--group rewards to make sure multiple entries of the same item do not slip by amount verfication below
WITH grouped_rewards AS (SELECT house_name, template_id, SUM(amount) as amount FROM UNNEST(in_house_rewards) GROUP BY house_name, template_id)
SELECT ARRAY_AGG((grouped_rewards.house_name, grouped_rewards.template_id, grouped_rewards.amount)::LandsraadPlayerHouseReward) INTO grouped_house_rewards FROM grouped_rewards;
FOREACH house_reward in ARRAY grouped_house_rewards
LOOP
SELECT lhr.amount INTO current_amount FROM landsraad_house_rewards AS lhr WHERE lhr.player_id = in_player_id AND lhr.house_name = house_reward.house_name AND lhr.template_id = house_reward.template_id;
IF current_amount IS NULL OR current_amount < house_reward.amount THEN
RAISE EXCEPTION 'Cannot withdraw house reward %s for player % and house %s', house_reward.template_id, in_player_id, house_reward.house_name;
RETURN;
END IF;
END LOOP;
-- finish full loop of checks first, all rewards need to be withdrawable before updating
FOREACH house_reward in ARRAY grouped_house_rewards
LOOP
UPDATE landsraad_house_rewards SET amount = amount - house_reward.amount, last_updated = CURRENT_TIMESTAMP WHERE player_id = in_player_id AND house_name = house_reward.house_name AND template_id = house_reward.template_id;
END LOOP;
END $function$