diff --git a/YpDaemon/src/worker/sql.rs b/YpDaemon/src/worker/sql.rs index 4334760..923ba49 100644 --- a/YpDaemon/src/worker/sql.rs +++ b/YpDaemon/src/worker/sql.rs @@ -580,6 +580,13 @@ pub const QUERY_COUNT_CHILDREN: &str = r#" SELECT COUNT(*) AS cnt FROM falukant_data.child_relation WHERE (father_character_id = $1 OR mother_character_id = $1) AND child_character_id != $2; "#; +pub const QUERY_COUNT_CHILDREN_BY_USER: &str = r#" +SELECT COUNT(DISTINCT cr.child_character_id) AS cnt +FROM falukant_data.child_relation cr +JOIN falukant_data.character parent ON (parent.id = cr.father_character_id OR parent.id = cr.mother_character_id) +WHERE parent.user_id = $1; +"#; + // user_character worker queries pub const QUERY_GET_USERS_TO_UPDATE: &str = r#" SELECT id, CURRENT_DATE - birthdate::date AS age, health diff --git a/YpDaemon/src/worker/user_character.rs b/YpDaemon/src/worker/user_character.rs index cf423f4..a4c7d0d 100644 --- a/YpDaemon/src/worker/user_character.rs +++ b/YpDaemon/src/worker/user_character.rs @@ -25,7 +25,7 @@ use crate::worker::sql::{ QUERY_GET_SETTLEMENT_VALUE, QUERY_GET_INVENTORY_VALUE, QUERY_GET_CREDIT_DEBT, - QUERY_COUNT_CHILDREN, + QUERY_COUNT_CHILDREN_BY_USER, QUERY_GET_HEIR, QUERY_RANDOM_HEIR, QUERY_SET_CHARACTER_USER, @@ -795,8 +795,8 @@ impl UserCharacterWorker { .get() .map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?; - conn.prepare("count_children", QUERY_COUNT_CHILDREN)?; - let rows = conn.execute("count_children", &[&deceased_user_id])?; + conn.prepare("count_children_by_user", QUERY_COUNT_CHILDREN_BY_USER)?; + let rows = conn.execute("count_children_by_user", &[&deceased_user_id])?; Ok(rows .first() diff --git a/src/worker/director.rs b/src/worker/director.rs index 83afff0..a17d016 100644 --- a/src/worker/director.rs +++ b/src/worker/director.rs @@ -158,29 +158,12 @@ impl DirectorWorker { for director in directors { if director.may_produce { - eprintln!( - "[DirectorWorker] Starte Produktionsprüfung für Director {} (branch_id={})", - director.id, director.branch_id - ); self.start_productions(&director)?; } if director.may_start_transport { - eprintln!( - "[DirectorWorker] Starte Transportprüfung für Director {} (branch_id={})", - director.id, director.branch_id - ); - if let Err(err) = self.start_transports_stub(&director) { - eprintln!( - "[DirectorWorker] Fehler bei start_transports für Director {}: {err}", - director.id - ); - } + if let Err(_) = self.start_transports_stub(&director) {} } if director.may_sell { - eprintln!( - "[DirectorWorker] Starte Verkaufsprüfung für Director {} (branch_id={})", - director.id, director.branch_id - ); self.start_sellings(&director)?; } } @@ -215,33 +198,14 @@ impl DirectorWorker { conn.prepare("get_to_produce", QUERY_GET_BEST_PRODUCTION)?; let rows = conn.execute("get_to_produce", &[&director.id, &director.branch_id])?; if rows.is_empty() { - eprintln!( - "[DirectorWorker] Keine Produktionskandidaten für Director {} gefunden.", - director.id - ); return Ok(()); } let mut base_plan = match rows.first().and_then(Self::map_row_to_production_plan) { Some(p) => p, - None => { - eprintln!( - "[DirectorWorker] Produktionsplan für Director {} konnte nicht gemappt werden.", - director.id - ); - return Ok(()); - } + None => return Ok(()), }; - eprintln!( - "[DirectorWorker] Produktionsplan: director_user_id={}, branch_id={}, product_id={}, money={}, certificate={}", - base_plan.falukant_user_id, - base_plan.branch_id, - base_plan.product_id, - base_plan.money, - base_plan.certificate - ); - // Query zum Abfragen der aktuellen Kapazitätswerte vorbereiten conn.prepare("get_branch_capacity", QUERY_GET_BRANCH_CAPACITY)?; @@ -274,24 +238,12 @@ impl DirectorWorker { // Prüfen, ob noch Produktionen gestartet werden können if running_productions >= MAX_PARALLEL_PRODUCTIONS { - eprintln!( - "[DirectorWorker] Maximale Anzahl an Produktionen ({}) erreicht für Branch {}.", - MAX_PARALLEL_PRODUCTIONS, - director.branch_id - ); break; } // Freie Kapazität berechnen let free_capacity = stock_size - used_in_stock - running_productions_quantity; if free_capacity <= 0 { - eprintln!( - "[DirectorWorker] Kein freier Lagerplatz mehr für Branch {} (stock_size={}, used={}, running_qty={}).", - director.branch_id, - stock_size, - used_in_stock, - running_productions_quantity - ); break; } @@ -302,10 +254,7 @@ impl DirectorWorker { base_plan.running_productions_quantity = running_productions_quantity; // Eine neue Produktion starten (max. 100 Stück) - if let Err(err) = self.create_single_production(&mut conn, &base_plan) { - eprintln!( - "[DirectorWorker] Fehler beim Starten einer Produktion: {err}" - ); + if self.create_single_production(&mut conn, &base_plan).is_err() { break; } } @@ -373,7 +322,6 @@ impl DirectorWorker { // Hole aktuelle Kapazitätswerte direkt aus der DB, um Race Conditions zu vermeiden let capacity_rows = conn.execute("get_branch_capacity", &[&plan.branch_id])?; if capacity_rows.is_empty() { - eprintln!("[DirectorWorker] Keine Kapazitätsdaten für Branch {} gefunden", plan.branch_id); return Ok(()); } @@ -395,10 +343,6 @@ impl DirectorWorker { let free_capacity = stock_size - used_in_stock - running_productions_quantity; if free_capacity <= 0 { - eprintln!( - "[DirectorWorker] Keine Produktion gestartet: Kein freier Lagerplatz (stock_size={}, used={}, running_qty={})", - stock_size, used_in_stock, running_productions_quantity - ); return Ok(()); } @@ -407,42 +351,16 @@ impl DirectorWorker { let to_produce = (free_capacity.min(max_money_production)).clamp(0, 100); - eprintln!( - "[DirectorWorker] Produktionsberechnung: free_capacity={}, one_piece_cost={}, max_money_production={}, to_produce={}, running_productions={}", - free_capacity, - one_piece_cost, - max_money_production, - to_produce, - plan.running_productions - ); - if to_produce < 1 { - eprintln!( - "[DirectorWorker] Keine Produktion gestartet: free_capacity={}, max_money_production={}, running_productions={}, running_qty={}", - free_capacity, - max_money_production, - plan.running_productions, - plan.running_productions_quantity - ); return Ok(()); } let production_cost = to_produce as f64 * one_piece_cost; - if let Err(err) = self.base.change_falukant_user_money( + let _ = self.base.change_falukant_user_money( plan.falukant_user_id, -production_cost, "director starts production", - ) { - eprintln!( - "[DirectorWorker] Fehler bei change_falukant_user_money: {err}" - ); - } - - // Debug: Log vor dem DB-Aufruf - eprintln!( - "[DirectorWorker] calling change_falukant_user_money for start production: user_id={}, money_change={}", - plan.falukant_user_id, -production_cost ); conn.prepare("insert_production", QUERY_INSERT_PRODUCTION)?; @@ -454,11 +372,6 @@ impl DirectorWorker { &[&plan.branch_id, &plan.product_id, &to_produce, &plan.region_id], )?; - eprintln!( - "[DirectorWorker] Produktion angelegt: branch_id={}, product_id={}, quantity={}", - plan.branch_id, plan.product_id, to_produce - ); - let message = format!( r#"{{"event":"production_started","branch_id":{}}}"#, plan.branch_id @@ -478,10 +391,6 @@ impl DirectorWorker { if plan.money > 0.0 { (plan.money / one_piece_cost).floor() as i32 } else { - eprintln!( - "[DirectorWorker] Warnung: money=0 für falukant_user_id={}, verwende nur Lagerkapazität als Limit.", - plan.falukant_user_id - ); i32::MAX } } else { @@ -505,11 +414,6 @@ impl DirectorWorker { let mut items: Vec = rows.into_iter().filter_map(Self::map_row_to_inventory_item).collect(); - eprintln!( - "[DirectorWorker] Transportprüfung für Director {} (branch_id={}): {} Inventar-Items gefunden", - director.id, director.branch_id, items.len() - ); - // Für alle Items dieses Directors sollten die user_id-Felder identisch // sein (Arbeitgeber des Directors). let falukant_user_id = if items.is_empty() { @@ -539,49 +443,23 @@ impl DirectorWorker { .and_then(|row| row.get("count").and_then(|v| v.parse::().ok())) .unwrap_or(0); - // Falls es nichts zu transportieren gibt, prüfe auf leere Transporte if items.is_empty() { - eprintln!( - "[DirectorWorker] Keine Inventar-Items für Transporte gefunden für Director {} (branch_id={})", - director.id, director.branch_id - ); - - // Wenn keine Transportmittel im Branch vorhanden sind, versuche leere Transporte zu planen if vehicles_in_branch == 0 { - eprintln!( - "[DirectorWorker] Keine Transportmittel im Branch {} vorhanden, prüfe auf leere Transporte zum Zurückholen", - director.branch_id - ); - if let Err(err) = self.plan_empty_transports_for_vehicle_retrieval( + let _ = self.plan_empty_transports_for_vehicle_retrieval( &mut conn, falukant_user_id, director.branch_id, - ) { - eprintln!( - "[DirectorWorker] Fehler beim Planen leerer Transporte: {err}" - ); - } + ); } return Ok(()); } - // Wenn keine Transportmittel im Branch vorhanden sind, aber Items vorhanden sind, - // versuche leere Transporte zu planen, um Fahrzeuge zurückzuholen if vehicles_in_branch == 0 && !items.is_empty() { - eprintln!( - "[DirectorWorker] Keine Transportmittel im Branch {} vorhanden, aber {} Items vorhanden. Prüfe auf leere Transporte zum Zurückholen", - director.branch_id, items.len() - ); - if let Err(err) = self.plan_empty_transports_for_vehicle_retrieval( + let _ = self.plan_empty_transports_for_vehicle_retrieval( &mut conn, falukant_user_id, director.branch_id, - ) { - eprintln!( - "[DirectorWorker] Fehler beim Planen leerer Transporte: {err}" - ); - } - // Nach dem Planen leerer Transporte erneut prüfen, ob jetzt Transportmittel vorhanden sind + ); let vehicle_count_rows_after = conn.execute( "count_vehicles_in_branch", &[&falukant_user_id, &director.branch_id], @@ -591,12 +469,7 @@ impl DirectorWorker { .next() .and_then(|row| row.get("count").and_then(|v| v.parse::().ok())) .unwrap_or(0); - if vehicles_in_branch_after == 0 { - eprintln!( - "[DirectorWorker] Nach Planen leerer Transporte immer noch keine Transportmittel im Branch {} vorhanden. Überspringe normale Transportplanung.", - director.branch_id - ); return Ok(()); } } @@ -605,29 +478,11 @@ impl DirectorWorker { // - ggf. Transport-Einträge erzeugt // - Inventar-Mengen reduziert for item in items.iter_mut() { - eprintln!( - "[DirectorWorker] Prüfe Transport für Item: product_id={}, quantity={}, quality={}, region_id={}, branch_id={}", - item.product_id, item.quantity, item.quality, item.region_id, item.branch_id - ); - - let shipped = self.plan_transports_for_item( + let _ = self.plan_transports_for_item( &mut conn, falukant_user_id, item, )?; - - // Inventar wird bereits in plan_transports_for_item reduziert - if shipped > 0 { - eprintln!( - "[DirectorWorker] Transport geplant: {} Einheiten von Produkt {} transportiert (Inventar bereits reduziert)", - shipped, item.product_id - ); - } else { - eprintln!( - "[DirectorWorker] Kein lohnender Transport gefunden für Produkt {} (region_id={})", - item.product_id, item.region_id - ); - } } // Nach normalen Transporten: Wenn keine Transportmittel mehr im Branch vorhanden sind, @@ -643,19 +498,11 @@ impl DirectorWorker { .unwrap_or(0); if vehicles_in_branch_final == 0 { - eprintln!( - "[DirectorWorker] Nach Transporten keine Transportmittel mehr im Branch {} vorhanden, prüfe auf leere Transporte zum Zurückholen", - director.branch_id - ); - if let Err(err) = self.plan_empty_transports_for_vehicle_retrieval( + let _ = self.plan_empty_transports_for_vehicle_retrieval( &mut conn, falukant_user_id, director.branch_id, - ) { - eprintln!( - "[DirectorWorker] Fehler beim Planen leerer Transporte: {err}" - ); - } + ); } Ok(()) @@ -841,30 +688,16 @@ impl DirectorWorker { let tax_cents = ((profit_cents as f64) * cumulative_tax_percent / 100.0).round() as i64; let payout_cents = revenue_cents - tax_cents; - eprintln!("[DirectorWorker] sell: revenue={:.2}, cost={:.2}, profit_cents={}, tax%={:.2}, tax_cents={}, payout_cents={}", sell_price, one_piece_cost * item.quantity as f64, profit_cents, cumulative_tax_percent, tax_cents, payout_cents); - if tax_cents > 0 { let tax_amount = (tax_cents as f64) / 100.0; - if let Err(err) = self.base.change_falukant_user_money(DEFAULT_TREASURY_USER_ID, tax_amount, &format!("tax from sale product {}", item.product_id)) { - eprintln!("[DirectorWorker] Fehler bei change_falukant_user_money (tax): {err}"); - } + let _ = self.base.change_falukant_user_money(DEFAULT_TREASURY_USER_ID, tax_amount, &format!("tax from sale product {}", item.product_id)); } let payout_amount = (payout_cents as f64) / 100.0; - if payout_cents != 0 && let Err(err) = self.base.change_falukant_user_money(item.user_id, payout_amount, "sell products") { - eprintln!("[DirectorWorker] Fehler bei change_falukant_user_money (sell products): {err}"); + if payout_cents != 0 { + let _ = self.base.change_falukant_user_money(item.user_id, payout_amount, "sell products"); } - // Debug: Log vor dem DB-Aufruf - eprintln!( - "[DirectorWorker] sell: user_id={}, revenue={:.2}, tax={:.2}, payout={:.2}, product_id={}", - item.user_id, - sell_price, - (tax_cents as f64) / 100.0, - payout_amount, - item.product_id - ); - conn.execute( "add_sell_log", &[ @@ -914,23 +747,11 @@ impl DirectorWorker { // Load worth_percent by region for this product let worth_by_region = Self::get_worth_by_region(conn, falukant_user_id, item.product_id)?; if worth_by_region.is_empty() { - eprintln!("[DirectorWorker] Keine worth_percent-Werte für Produkt {} gefunden", item.product_id); return Ok(0); } - eprintln!( - "[DirectorWorker] Gefundene Regionen für Produkt {}: {} Regionen", - item.product_id, - worth_by_region.len() - ); - - // Compute local piece price let local_percent = worth_by_region.get(&item.region_id).copied().unwrap_or(100.0); let local_piece_price = Self::compute_piece_price_for_percent(item, local_percent); - eprintln!( - "[DirectorWorker] Lokaler Preis für Produkt {}: {:.2} (worth_percent={:.2}, quality={})", - item.product_id, local_piece_price, local_percent, item.quality - ); let mut best_target_region: Option = None; let mut best_quantity: i32 = 0; @@ -945,16 +766,7 @@ impl DirectorWorker { let remote_piece_price = Self::compute_piece_price_for_percent(item, remote_percent); let delta_per_unit = remote_piece_price - local_piece_price; - eprintln!( - "[DirectorWorker] Region {}: Preis {:.2}, Delta {:.2}", - region_id, remote_piece_price, delta_per_unit - ); - if delta_per_unit <= 0.0 { - eprintln!( - "[DirectorWorker] Region {}: Kein Preisvorteil (Delta <= 0)", - region_id - ); continue; } @@ -966,16 +778,7 @@ impl DirectorWorker { region_id, )?; - eprintln!( - "[DirectorWorker] Region {}: {} verfügbare Transportmittel", - region_id, vehicles.len() - ); - if vehicles.is_empty() { - eprintln!( - "[DirectorWorker] Region {}: Keine verfügbaren Transportmittel", - region_id - ); continue; } @@ -994,24 +797,11 @@ impl DirectorWorker { let extra_revenue = delta_per_unit * qty as f64; let transport_cost = Self::calc_transport_cost(remote_piece_price, qty); let net_gain = extra_revenue - transport_cost; - eprintln!( - "[DirectorWorker] Region {}: extra_revenue={:.2}, transport_cost={:.2}, net_gain={:.2}, qty={}", - region_id, extra_revenue, transport_cost, net_gain, qty - ); - if net_gain <= 0.0 { - eprintln!( - "[DirectorWorker] Region {}: Netto-Gewinn <= 0, überspringe", - region_id - ); continue; } if net_gain > best_gain { - eprintln!( - "[DirectorWorker] Region {}: Neuer bester Transport (Gewinn {:.2})", - region_id, net_gain - ); best_gain = net_gain; best_target_region = Some(region_id); best_quantity = qty; @@ -1047,10 +837,6 @@ impl DirectorWorker { item.quantity = remaining_quantity; } - eprintln!( - "[DirectorWorker] Transport geplant: {} Einheiten von Produkt {} von Region {} nach Region {} (Stückpreis lokal {:.2}, remote {:.2}). Inventar reduziert.", - shipped, item.product_id, item.region_id, target_region, local_piece_price, best_remote_piece_price - ); } Ok(shipped) @@ -1075,10 +861,6 @@ impl DirectorWorker { .and_then(|row| row.get("count").and_then(|v| v.parse::().ok())) .unwrap_or(0); - eprintln!( - "[DirectorWorker] Fahrzeuge in Region {} für User {}: {}", - source_region, falukant_user_id, vehicle_count - ); // Debug: Prüfe, ob eine Route existiert conn.prepare("check_route", QUERY_CHECK_ROUTE)?; @@ -1093,10 +875,6 @@ impl DirectorWorker { .and_then(|row| row.get("count").and_then(|v| v.parse::().ok())) .unwrap_or(0) > 0; - eprintln!( - "[DirectorWorker] Route von Region {} nach Region {} existiert: {}", - source_region, target_region, route_exists - ); conn.prepare( "get_transport_vehicles_for_route", @@ -1123,10 +901,6 @@ impl DirectorWorker { } } - eprintln!( - "[DirectorWorker] Gefundene Transportmittel für Route {} -> {}: {}", - source_region, target_region, result.len() - ); Ok(result) } @@ -1210,10 +984,6 @@ impl DirectorWorker { )?; if branch_rows.is_empty() { - eprintln!( - "[DirectorWorker] Keine anderen Branches für User {} gefunden", - falukant_user_id - ); return Ok(()); } @@ -1292,9 +1062,6 @@ impl DirectorWorker { } if branches_with_vehicles.is_empty() { - eprintln!( - "[DirectorWorker] Keine Branches mit freien Transportmitteln gefunden" - ); return Ok(()); } @@ -1303,10 +1070,6 @@ impl DirectorWorker { let (target_branch_id, target_region_id, vehicle_count, price_delta) = branches_with_vehicles[0]; - eprintln!( - "[DirectorWorker] Bester Branch für Fahrzeug-Rückholung: Branch {} (Region {}), {} Fahrzeuge, Preisvorteil: {:.2}%", - target_branch_id, target_region_id, vehicle_count, price_delta - ); // Hole die Fahrzeuge nochmal für diesen Branch let vehicles = Self::get_transport_vehicles_for_route( @@ -1326,10 +1089,6 @@ impl DirectorWorker { transport_count += 1; } - eprintln!( - "[DirectorWorker] {} leere Transporte geplant: Region {} -> Region {}", - transport_count, target_region_id, current_region_id - ); Ok(()) } @@ -1368,9 +1127,6 @@ impl DirectorWorker { -(item.income as f64), "director payed out", ) { - eprintln!( - "[DirectorWorker] Fehler bei change_falukant_user_money (director payed out): {err}" - ); } conn.execute("set_salary_payed", &[&item.id])?; diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 20a4e81..348fcb8 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -580,6 +580,14 @@ pub const QUERY_COUNT_CHILDREN: &str = r#" SELECT COUNT(*) AS cnt FROM falukant_data.child_relation WHERE (father_character_id = $1 OR mother_character_id = $1) AND child_character_id != $2; "#; +/// Zählt Kinder eines Users (über alle Charaktere des Users als Elternteil). Ein Parameter: user_id. +pub const QUERY_COUNT_CHILDREN_BY_USER: &str = r#" +SELECT COUNT(DISTINCT cr.child_character_id) AS cnt +FROM falukant_data.child_relation cr +JOIN falukant_data.character parent ON (parent.id = cr.father_character_id OR parent.id = cr.mother_character_id) +WHERE parent.user_id = $1; +"#; + // user_character worker queries pub const QUERY_GET_USERS_TO_UPDATE: &str = r#" SELECT id, CURRENT_DATE - birthdate::date AS age, health diff --git a/src/worker/user_character.rs b/src/worker/user_character.rs index df9bf6b..7a0b4a0 100644 --- a/src/worker/user_character.rs +++ b/src/worker/user_character.rs @@ -26,7 +26,7 @@ use crate::worker::sql::{ QUERY_GET_SETTLEMENT_VALUE, QUERY_GET_INVENTORY_VALUE, QUERY_GET_CREDIT_DEBT, - QUERY_COUNT_CHILDREN, + QUERY_COUNT_CHILDREN_BY_USER, QUERY_GET_HEIR, QUERY_RANDOM_HEIR, QUERY_SET_CHARACTER_USER, @@ -844,8 +844,8 @@ impl UserCharacterWorker { .get() .map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?; - conn.prepare("count_children", QUERY_COUNT_CHILDREN)?; - let rows = conn.execute("count_children", &[&deceased_user_id])?; + conn.prepare("count_children_by_user", QUERY_COUNT_CHILDREN_BY_USER)?; + let rows = conn.execute("count_children_by_user", &[&deceased_user_id])?; Ok(rows .first()