Füge Logik zur Durchsetzung der Wahlvorlaufzeit hinzu: Implementiere die Funktion enforce_election_lead_time, um sicherzustellen, dass Wahlen erst nach Ablauf von 2 Tagen seit ihrer Erstellung ausgewertet werden. Aktualisiere SQL-Abfragen zur Berücksichtigung des Vorlaufs bei der Planung neuer Wahlen.
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m41s
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m41s
This commit is contained in:
@@ -10,6 +10,7 @@ use crate::worker::sql::{
|
||||
QUERY_COUNT_OFFICES_PER_REGION,
|
||||
QUERY_FIND_OFFICE_GAPS,
|
||||
QUERY_SELECT_NEEDED_ELECTIONS,
|
||||
QUERY_ENFORCE_ELECTION_LEAD_TIME,
|
||||
QUERY_INSERT_CANDIDATES,
|
||||
QUERY_SELECT_ELECTIONS_NEEDING_CANDIDATES,
|
||||
QUERY_PROCESS_EXPIRED_AND_FILL,
|
||||
@@ -181,10 +182,31 @@ impl PoliticsWorker {
|
||||
Self::notify_office_filled(pool, broker, &new_offices_direct)?;
|
||||
}
|
||||
|
||||
// 5) Neue Wahlen planen
|
||||
// 4b) Nach dem Entfernen abgelaufener Aemter erneut Luecken
|
||||
// synchronisieren. Das behebt Rueckstaende, wenn Aemter schon vor
|
||||
// Tagen/Wochen abgelaufen sind und dadurch erst jetzt echte Gaps
|
||||
// entstehen.
|
||||
Self::sync_offices_with_types(pool)?;
|
||||
|
||||
// 5) Sicherstellen, dass Wahlen niemals vor Ablauf von 2 Tagen seit
|
||||
// Anlegen ausgewertet werden.
|
||||
Self::enforce_election_lead_time(pool)?;
|
||||
|
||||
// 6) Bereits faellige Wahlen auswerten und neu besetzte Aemter melden.
|
||||
// Wichtig: Vor dem Anlegen neuer Wahlen ausfuehren, damit frisch
|
||||
// angelegte Wahlen nicht im selben Tageslauf wieder verarbeitet werden.
|
||||
let new_offices_from_elections = Self::process_elections(pool)?;
|
||||
if let Err(e) = Self::notify_player_election_results(pool, broker) {
|
||||
eprintln!("[PoliticsWorker] notify_player_election_results: {e}");
|
||||
}
|
||||
if !new_offices_from_elections.is_empty() {
|
||||
Self::notify_office_filled(pool, broker, &new_offices_from_elections)?;
|
||||
}
|
||||
|
||||
// 7) Neue Wahlen planen
|
||||
let new_elections = Self::schedule_elections(pool)?;
|
||||
|
||||
// 6) Für alle Wahlen ohne Kandidaten (inkl. manuell
|
||||
// 8) Fuer alle Wahlen ohne Kandidaten (inkl. manuell
|
||||
// angelegter) Kandidaten eintragen.
|
||||
let mut elections_to_fill = Self::find_elections_needing_candidates(pool)?;
|
||||
// Die gerade neu angelegten Wahlen sind typischerweise auch
|
||||
@@ -207,16 +229,7 @@ impl PoliticsWorker {
|
||||
Self::notify_election_created(pool, broker, &user_ids)?;
|
||||
}
|
||||
|
||||
// 7) Wahlen auswerten und neu besetzte Ämter melden
|
||||
let new_offices_from_elections = Self::process_elections(pool)?;
|
||||
if let Err(e) = Self::notify_player_election_results(pool, broker) {
|
||||
eprintln!("[PoliticsWorker] notify_player_election_results: {e}");
|
||||
}
|
||||
if !new_offices_from_elections.is_empty() {
|
||||
Self::notify_office_filled(pool, broker, &new_offices_from_elections)?;
|
||||
}
|
||||
|
||||
// 8) Als letzter Schritt sicherstellen, dass es für keinen
|
||||
// 9) Als letzter Schritt sicherstellen, dass es fuer keinen
|
||||
// Amtstyp/Region-Kombi mehr besetzte Ämter gibt als laut
|
||||
// `seats_per_region` erlaubt. Dieser Abgleich wird nach allen
|
||||
// Lösch- und Besetzungsvorgängen ausgeführt.
|
||||
@@ -337,8 +350,8 @@ impl PoliticsWorker {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Für jede Lücke eine Wahl am aktuellen Tag anlegen, sofern es nicht
|
||||
// bereits eine Wahl für diesen Amtstyp/Region an einem heutigen oder
|
||||
// Für jede Lücke eine Wahl mit 2 Tagen Vorlauf anlegen, sofern es nicht
|
||||
// bereits eine Wahl für diesen Amtstyp/Region an einem gleich späten oder
|
||||
// zukünftigen Datum gibt. Das eigentliche Anlegen der Wahl und das
|
||||
// Eintragen von Kandidaten läuft weiterhin über die bestehende
|
||||
// Logik in der Datenbank (process_elections / schedule_elections).
|
||||
@@ -353,7 +366,7 @@ impl PoliticsWorker {
|
||||
(office_type_id, date, posts_to_fill, created_at, updated_at, region_id)
|
||||
SELECT
|
||||
$1::int AS office_type_id,
|
||||
CURRENT_DATE AS date,
|
||||
(CURRENT_DATE + INTERVAL '2 days')::date AS date,
|
||||
$2::int AS posts_to_fill,
|
||||
NOW() AS created_at,
|
||||
NOW() AS updated_at,
|
||||
@@ -363,7 +376,7 @@ impl PoliticsWorker {
|
||||
FROM falukant_data.election e
|
||||
WHERE e.office_type_id = $1::int
|
||||
AND e.region_id = $3::int
|
||||
AND e.date::date >= CURRENT_DATE
|
||||
AND e.date::date >= (CURRENT_DATE + INTERVAL '2 days')::date
|
||||
);
|
||||
"#;
|
||||
|
||||
@@ -634,6 +647,19 @@ impl PoliticsWorker {
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn enforce_election_lead_time(pool: &ConnectionPool) -> Result<(), DbError> {
|
||||
let mut conn = pool
|
||||
.get()
|
||||
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
||||
|
||||
conn.prepare("enforce_election_lead_time", QUERY_ENFORCE_ELECTION_LEAD_TIME)
|
||||
.map_err(|e| DbError::new(format!("[PoliticsWorker] prepare enforce_election_lead_time: {e}")))?;
|
||||
conn.execute("enforce_election_lead_time", &[])
|
||||
.map_err(|e| DbError::new(format!("[PoliticsWorker] exec enforce_election_lead_time: {e}")))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Benachrichtigt Spieler-Kandidaten mit Wahlergebnis (Stimmen, Rang, Gewinner, gewonnen?).
|
||||
/// `tr` = JSON mit `event: "election_result"` (siehe `QUERY_PLAYER_ELECTION_RESULT_ROWS`).
|
||||
fn notify_player_election_results(
|
||||
|
||||
@@ -1113,7 +1113,7 @@ pub const QUERY_FIND_OFFICE_GAPS: &str = r#"
|
||||
pub const QUERY_SELECT_NEEDED_ELECTIONS: &str = r#"
|
||||
WITH
|
||||
target_date AS (
|
||||
SELECT NOW()::date AS election_date
|
||||
SELECT (NOW()::date + INTERVAL '2 days')::date AS election_date
|
||||
),
|
||||
offices_ending_today AS (
|
||||
SELECT po.id,
|
||||
@@ -1186,6 +1186,14 @@ pub const QUERY_SELECT_NEEDED_ELECTIONS: &str = r#"
|
||||
ORDER BY ne.region_id, ne.election_id;
|
||||
"#;
|
||||
|
||||
pub const QUERY_ENFORCE_ELECTION_LEAD_TIME: &str = r#"
|
||||
UPDATE falukant_data.election AS e
|
||||
SET date = (e.created_at::date + INTERVAL '2 days')::date,
|
||||
updated_at = NOW()
|
||||
WHERE e.created_at IS NOT NULL
|
||||
AND e.date::date < (e.created_at::date + INTERVAL '2 days')::date;
|
||||
"#;
|
||||
|
||||
pub const QUERY_INSERT_CANDIDATES: &str = r#"
|
||||
INSERT INTO falukant_data.candidate
|
||||
(election_id, character_id, created_at, updated_at)
|
||||
|
||||
Reference in New Issue
Block a user