Add sleep management for productions in ProduceWorker: Implement logic to set productions to sleep when storage capacity is insufficient. Introduce methods for processing and retrieving sleep productions, enhancing inventory management and production flow control.
This commit is contained in:
@@ -14,6 +14,8 @@ use crate::worker::sql::{
|
||||
QUERY_DELETE_PRODUCTION,
|
||||
QUERY_INSERT_INVENTORY,
|
||||
QUERY_INSERT_UPDATE_PRODUCTION_LOG,
|
||||
QUERY_SET_PRODUCTION_SLEEP,
|
||||
QUERY_GET_SLEEP_PRODUCTIONS,
|
||||
};
|
||||
use crate::worker::insert_notification_conn;
|
||||
|
||||
@@ -44,6 +46,7 @@ pub struct ProduceWorker {
|
||||
base: BaseWorker,
|
||||
last_iteration: Option<Instant>,
|
||||
last_start_fix: Option<Instant>,
|
||||
last_sleep_check: Option<Instant>,
|
||||
}
|
||||
|
||||
impl ProduceWorker {
|
||||
@@ -52,6 +55,7 @@ impl ProduceWorker {
|
||||
base: BaseWorker::new("ProduceWorker", pool, broker),
|
||||
last_iteration: None,
|
||||
last_start_fix: None,
|
||||
last_sleep_check: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +76,8 @@ impl ProduceWorker {
|
||||
|
||||
self.base.set_current_step("Process Productions");
|
||||
self.process_productions();
|
||||
self.base.set_current_step("Process Sleep Productions");
|
||||
self.process_sleep_productions();
|
||||
self.base.set_current_step("Signal Activity");
|
||||
// TODO: Später Analogie zu signalActivity() aus der C++-Basisklasse herstellen.
|
||||
self.base.set_current_step("Loop Done");
|
||||
@@ -215,12 +221,37 @@ impl ProduceWorker {
|
||||
production_id,
|
||||
} = *production;
|
||||
|
||||
if self.add_to_inventory(branch_id, product_id, quantity, quality, user_id) {
|
||||
self.delete_production(production_id);
|
||||
self.add_production_to_log(region_id, user_id, product_id, quantity);
|
||||
// Prüfe VOR dem Abschluss, ob genug Lagerplatz vorhanden ist
|
||||
if self.has_enough_storage_capacity(branch_id, quantity) {
|
||||
// Genug Platz: Produktion abschließen
|
||||
if self.add_to_inventory(branch_id, product_id, quantity, quality, user_id) {
|
||||
self.delete_production(production_id);
|
||||
self.add_production_to_log(region_id, user_id, product_id, quantity);
|
||||
}
|
||||
} else {
|
||||
// Nicht genug Platz: Produktion auf sleep setzen
|
||||
if let Err(err) = self.set_production_sleep(production_id) {
|
||||
eprintln!("[ProduceWorker] Fehler beim Setzen von sleep für Produktion {}: {}", production_id, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn has_enough_storage_capacity(&self, branch_id: i32, required_quantity: i32) -> bool {
|
||||
let stocks = match self.get_available_stocks(branch_id) {
|
||||
Ok(rows) => rows,
|
||||
Err(err) => {
|
||||
eprintln!("[ProduceWorker] Fehler in getAvailableStocks: {err}");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let total_free_capacity: i32 = stocks.iter()
|
||||
.map(|stock| (stock.total_capacity - stock.filled).max(0))
|
||||
.sum();
|
||||
|
||||
total_free_capacity >= required_quantity
|
||||
}
|
||||
|
||||
fn add_to_inventory(
|
||||
&mut self,
|
||||
branch_id: i32,
|
||||
@@ -458,6 +489,95 @@ impl ProduceWorker {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_production_sleep(&self, production_id: i32) -> Result<(), crate::db::DbError> {
|
||||
let mut conn = self
|
||||
.base
|
||||
.pool
|
||||
.get()
|
||||
.map_err(|e| crate::db::DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
||||
|
||||
conn.prepare("set_production_sleep", QUERY_SET_PRODUCTION_SLEEP)?;
|
||||
conn.execute("set_production_sleep", &[&production_id])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_sleep_productions(&mut self) {
|
||||
const SLEEP_CHECK_INTERVAL_SECS: u64 = 300; // 5 Minuten
|
||||
|
||||
let now = Instant::now();
|
||||
let should_check = match self.last_sleep_check {
|
||||
None => {
|
||||
self.last_sleep_check = Some(now);
|
||||
true
|
||||
}
|
||||
Some(last) => {
|
||||
if now.saturating_duration_since(last).as_secs() >= SLEEP_CHECK_INTERVAL_SECS {
|
||||
self.last_sleep_check = Some(now);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if !should_check {
|
||||
return;
|
||||
}
|
||||
|
||||
let sleep_productions = match self.get_sleep_productions() {
|
||||
Ok(rows) => rows,
|
||||
Err(err) => {
|
||||
eprintln!("[ProduceWorker] Fehler beim Laden von sleep-Produktionen: {err}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
for production in sleep_productions {
|
||||
self.handle_sleep_production(&production);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_sleep_productions(&self) -> Result<Vec<FinishedProduction>, crate::db::DbError> {
|
||||
let rows = self.load_sleep_productions()?;
|
||||
Ok(rows
|
||||
.into_iter()
|
||||
.filter_map(Self::map_row_to_finished_production)
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn load_sleep_productions(&self) -> Result<Rows, crate::db::DbError> {
|
||||
let mut conn = self
|
||||
.base
|
||||
.pool
|
||||
.get()
|
||||
.map_err(|e| crate::db::DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
||||
|
||||
conn.prepare("get_sleep_productions", QUERY_GET_SLEEP_PRODUCTIONS)?;
|
||||
conn.execute("get_sleep_productions", &[])
|
||||
}
|
||||
|
||||
fn handle_sleep_production(&mut self, production: &FinishedProduction) {
|
||||
let FinishedProduction {
|
||||
branch_id,
|
||||
product_id,
|
||||
quantity,
|
||||
quality,
|
||||
user_id,
|
||||
region_id,
|
||||
production_id,
|
||||
} = *production;
|
||||
|
||||
// Prüfe erneut, ob jetzt genug Lagerplatz vorhanden ist
|
||||
if self.has_enough_storage_capacity(branch_id, quantity) {
|
||||
// Jetzt genug Platz: Produktion abschließen
|
||||
if self.add_to_inventory(branch_id, product_id, quantity, quality, user_id) {
|
||||
self.delete_production(production_id);
|
||||
self.add_production_to_log(region_id, user_id, product_id, quantity);
|
||||
}
|
||||
}
|
||||
// Wenn immer noch nicht genug Platz: Produktion bleibt auf sleep
|
||||
}
|
||||
|
||||
fn insert_or_update_production_log(
|
||||
&self,
|
||||
region_id: i32,
|
||||
|
||||
@@ -1655,6 +1655,7 @@ pub const QUERY_GET_FINISHED_PRODUCTIONS: &str = r#"
|
||||
AND pwe.weather_type_id = w.weather_type_id
|
||||
-- Wetter-Effekte derzeit aus der Qualitätsberechnung entfernt
|
||||
WHERE p.start_timestamp + INTERVAL '1 minute' * pr.production_time <= NOW()
|
||||
AND COALESCE(p.sleep, FALSE) = FALSE
|
||||
ORDER BY p.start_timestamp;
|
||||
"#;
|
||||
|
||||
@@ -1663,6 +1664,64 @@ pub const QUERY_DELETE_PRODUCTION: &str = r#"
|
||||
WHERE id = $1;
|
||||
"#;
|
||||
|
||||
pub const QUERY_SET_PRODUCTION_SLEEP: &str = r#"
|
||||
UPDATE falukant_data.production
|
||||
SET sleep = TRUE
|
||||
WHERE id = $1;
|
||||
"#;
|
||||
|
||||
pub const QUERY_GET_SLEEP_PRODUCTIONS: &str = r#"
|
||||
SELECT
|
||||
p.id AS production_id,
|
||||
p.branch_id,
|
||||
p.product_id,
|
||||
p.quantity,
|
||||
p.start_timestamp,
|
||||
pr.production_time,
|
||||
br.region_id,
|
||||
br.falukant_user_id AS user_id,
|
||||
ROUND(
|
||||
GREATEST(
|
||||
0,
|
||||
LEAST(
|
||||
100,
|
||||
(
|
||||
(COALESCE(k.knowledge, 0) * 0.75
|
||||
+ COALESCE(k2.knowledge, 0) * 0.25)
|
||||
* COALESCE(pwe.quality_effect, 100) / 100.0
|
||||
)
|
||||
)
|
||||
)
|
||||
)::int AS quality
|
||||
FROM falukant_data.production p
|
||||
JOIN falukant_type.product pr
|
||||
ON p.product_id = pr.id
|
||||
JOIN falukant_data.branch br
|
||||
ON p.branch_id = br.id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT c.id, c.user_id
|
||||
FROM falukant_data.character c
|
||||
WHERE c.user_id = br.falukant_user_id
|
||||
ORDER BY c.updated_at DESC NULLS LAST, c.id DESC
|
||||
LIMIT 1
|
||||
) c ON TRUE
|
||||
LEFT JOIN falukant_data.knowledge k
|
||||
ON p.product_id = k.product_id
|
||||
AND k.character_id = c.id
|
||||
LEFT JOIN falukant_data.director d
|
||||
ON d.employer_user_id = c.user_id
|
||||
LEFT JOIN falukant_data.knowledge k2
|
||||
ON k2.character_id = d.director_character_id
|
||||
AND k2.product_id = p.product_id
|
||||
LEFT JOIN falukant_data.weather w
|
||||
ON w.region_id = br.region_id
|
||||
LEFT JOIN falukant_type.product_weather_effect pwe
|
||||
ON pwe.product_id = p.product_id
|
||||
AND pwe.weather_type_id = w.weather_type_id
|
||||
WHERE p.sleep = TRUE
|
||||
ORDER BY p.start_timestamp;
|
||||
"#;
|
||||
|
||||
pub const QUERY_INSERT_UPDATE_PRODUCTION_LOG: &str = r#"
|
||||
INSERT INTO falukant_log.production (
|
||||
region_id,
|
||||
|
||||
Reference in New Issue
Block a user