code fixes
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m52s
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m52s
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -11,7 +11,7 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"libsystemd",
|
"libsystemd",
|
||||||
"postgres",
|
"postgres",
|
||||||
"rand 0.8.5",
|
"rand 0.9.2",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use crate::db::{ConnectionPool, DbError, Rows};
|
use crate::db::{ConnectionPool, DbError, Rows};
|
||||||
use crate::message_broker::MessageBroker;
|
use crate::message_broker::MessageBroker;
|
||||||
use rand::distributions::{Distribution, Uniform};
|
|
||||||
use rand::rngs::StdRng;
|
use rand::rngs::StdRng;
|
||||||
use rand::{thread_rng, Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -29,7 +28,6 @@ use crate::worker::sql::{
|
|||||||
pub struct CharacterCreationWorker {
|
pub struct CharacterCreationWorker {
|
||||||
pub(crate) base: BaseWorker,
|
pub(crate) base: BaseWorker,
|
||||||
rng: StdRng,
|
rng: StdRng,
|
||||||
dist: Uniform<i32>,
|
|
||||||
first_name_cache: HashMap<String, HashSet<i32>>,
|
first_name_cache: HashMap<String, HashSet<i32>>,
|
||||||
last_name_cache: HashSet<i32>,
|
last_name_cache: HashSet<i32>,
|
||||||
death_check_running: Arc<AtomicBool>,
|
death_check_running: Arc<AtomicBool>,
|
||||||
@@ -46,8 +44,8 @@ impl CharacterCreationWorker {
|
|||||||
/// Interner Konstruktor, der optional den NPC-Todes-Monitor startet.
|
/// Interner Konstruktor, der optional den NPC-Todes-Monitor startet.
|
||||||
fn new_internal(pool: ConnectionPool, broker: MessageBroker, start_death_thread: bool) -> Self {
|
fn new_internal(pool: ConnectionPool, broker: MessageBroker, start_death_thread: bool) -> Self {
|
||||||
let base = BaseWorker::new("CharacterCreationWorker", pool.clone(), broker.clone());
|
let base = BaseWorker::new("CharacterCreationWorker", pool.clone(), broker.clone());
|
||||||
let rng = StdRng::from_entropy();
|
let mut base_rng = rand::rng();
|
||||||
let dist = Uniform::from(2..=3);
|
let rng = StdRng::from_rng(&mut base_rng);
|
||||||
let death_check_running = Arc::new(AtomicBool::new(start_death_thread));
|
let death_check_running = Arc::new(AtomicBool::new(start_death_thread));
|
||||||
|
|
||||||
let death_thread = if start_death_thread {
|
let death_thread = if start_death_thread {
|
||||||
@@ -80,7 +78,6 @@ impl CharacterCreationWorker {
|
|||||||
Self {
|
Self {
|
||||||
base,
|
base,
|
||||||
rng,
|
rng,
|
||||||
dist,
|
|
||||||
first_name_cache: HashMap::new(),
|
first_name_cache: HashMap::new(),
|
||||||
last_name_cache: HashSet::new(),
|
last_name_cache: HashSet::new(),
|
||||||
death_check_running,
|
death_check_running,
|
||||||
@@ -139,7 +136,7 @@ impl CharacterCreationWorker {
|
|||||||
|
|
||||||
for &nobility in &nobility_stands {
|
for &nobility in &nobility_stands {
|
||||||
for &gender in &genders {
|
for &gender in &genders {
|
||||||
let num_chars = self.rng.sample(self.dist);
|
let num_chars = self.rng.random_range(2..=3);
|
||||||
for _ in 0..num_chars {
|
for _ in 0..num_chars {
|
||||||
self.create_character(region_id, gender, nobility);
|
self.create_character(region_id, gender, nobility);
|
||||||
}
|
}
|
||||||
@@ -248,8 +245,8 @@ impl CharacterCreationWorker {
|
|||||||
if set.is_empty() {
|
if set.is_empty() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
let mut rng = thread_rng();
|
let mut rng = rand::rng();
|
||||||
let idx = rng.gen_range(0..set.len());
|
let idx = rng.random_range(0..set.len());
|
||||||
*set.iter().nth(idx).unwrap_or(&-1)
|
*set.iter().nth(idx).unwrap_or(&-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,9 +387,8 @@ impl CharacterCreationWorker {
|
|||||||
let death_probability =
|
let death_probability =
|
||||||
base_probability + increase_per_year * (age.saturating_sub(60) as f64);
|
base_probability + increase_per_year * (age.saturating_sub(60) as f64);
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = rand::rng();
|
||||||
let dist = Uniform::from(0.0..1.0);
|
let roll: f64 = rng.random_range(0.0..1.0);
|
||||||
let roll: f64 = dist.sample(&mut rng);
|
|
||||||
roll < death_probability
|
roll < death_probability
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,4 +533,3 @@ impl CharacterCreationWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ impl DirectorWorker {
|
|||||||
.filter_map(Self::map_row_to_resignation_candidate)
|
.filter_map(Self::map_row_to_resignation_candidate)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
for candidate in candidates {
|
for candidate in candidates {
|
||||||
let sat = candidate.satisfaction.clamp(0, 100) as f64;
|
let sat = candidate.satisfaction.clamp(0, 100) as f64;
|
||||||
let resignation_probability = 1.0 - (sat / 100.0);
|
let resignation_probability = 1.0 - (sat / 100.0);
|
||||||
@@ -214,7 +214,7 @@ impl DirectorWorker {
|
|||||||
);
|
);
|
||||||
let _ = conn.execute("insert_notification", &[&candidate.employer_user_id, &payload]);
|
let _ = conn.execute("insert_notification", &[&candidate.employer_user_id, &payload]);
|
||||||
}
|
}
|
||||||
let roll: f64 = rng.gen_range(0.0..1.0);
|
let roll: f64 = rng.random_range(0.0..1.0);
|
||||||
if roll >= resignation_probability {
|
if roll >= resignation_probability {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::db::{ConnectionPool, DbConnection, DbError};
|
use crate::db::{ConnectionPool, DbConnection, DbError};
|
||||||
use crate::message_broker::MessageBroker;
|
use crate::message_broker::MessageBroker;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use rand::seq::SliceRandom;
|
use rand::prelude::SliceRandom;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -447,7 +447,7 @@ impl EventsWorker {
|
|||||||
|
|
||||||
fn run_loop(pool: ConnectionPool, broker: MessageBroker, state: Arc<WorkerState>) {
|
fn run_loop(pool: ConnectionPool, broker: MessageBroker, state: Arc<WorkerState>) {
|
||||||
let mut last_event_check = None;
|
let mut last_event_check = None;
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let events = Self::initialize_events();
|
let events = Self::initialize_events();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -502,7 +502,7 @@ impl EventsWorker {
|
|||||||
// Prüfe jedes mögliche Ereignis
|
// Prüfe jedes mögliche Ereignis
|
||||||
for event in events {
|
for event in events {
|
||||||
// Zufällige Prüfung basierend auf Wahrscheinlichkeit
|
// Zufällige Prüfung basierend auf Wahrscheinlichkeit
|
||||||
let roll = rng.gen_range(0.0..=1.0);
|
let roll = rng.random_range(0.0..=1.0);
|
||||||
let effective_prob = event.probability_per_minute * Self::EVENT_RATE_SCALE;
|
let effective_prob = event.probability_per_minute * Self::EVENT_RATE_SCALE;
|
||||||
if roll < effective_prob {
|
if roll < effective_prob {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@@ -560,7 +560,7 @@ impl EventsWorker {
|
|||||||
// Wende Effekte an
|
// Wende Effekte an
|
||||||
let mut effect_results = Vec::new();
|
let mut effect_results = Vec::new();
|
||||||
for effect in &event.effects {
|
for effect in &event.effects {
|
||||||
let effect_roll = rng.gen_range(0.0..=1.0);
|
let effect_roll = rng.random_range(0.0..=1.0);
|
||||||
match effect {
|
match effect {
|
||||||
EventEffect::MoneyChange {
|
EventEffect::MoneyChange {
|
||||||
probability,
|
probability,
|
||||||
@@ -750,7 +750,7 @@ impl EventsWorker {
|
|||||||
// Wende Effekte an (in diesem Fall nur CharacterDeath)
|
// Wende Effekte an (in diesem Fall nur CharacterDeath)
|
||||||
let mut effect_results = Vec::new();
|
let mut effect_results = Vec::new();
|
||||||
for effect in &event.effects {
|
for effect in &event.effects {
|
||||||
let effect_roll = rng.gen_range(0.0..=1.0);
|
let effect_roll = rng.random_range(0.0..=1.0);
|
||||||
match effect {
|
match effect {
|
||||||
EventEffect::CharacterDeath { probability } => {
|
EventEffect::CharacterDeath { probability } => {
|
||||||
if effect_roll < *probability
|
if effect_roll < *probability
|
||||||
@@ -835,7 +835,7 @@ impl EventsWorker {
|
|||||||
let mut price_change_note: Option<serde_json::Value> = None;
|
let mut price_change_note: Option<serde_json::Value> = None;
|
||||||
let mut production_quality_note: Option<serde_json::Value> = None;
|
let mut production_quality_note: Option<serde_json::Value> = None;
|
||||||
for effect in &event.effects {
|
for effect in &event.effects {
|
||||||
let effect_roll = rng.gen_range(0.0..=1.0);
|
let effect_roll = rng.random_range(0.0..=1.0);
|
||||||
match effect {
|
match effect {
|
||||||
EventEffect::WeatherChange { probability } => {
|
EventEffect::WeatherChange { probability } => {
|
||||||
if effect_roll < *probability {
|
if effect_roll < *probability {
|
||||||
@@ -851,7 +851,7 @@ impl EventsWorker {
|
|||||||
max_change,
|
max_change,
|
||||||
} => {
|
} => {
|
||||||
if effect_roll < *probability {
|
if effect_roll < *probability {
|
||||||
let change = rng.gen_range(*min_change..=*max_change);
|
let change = rng.random_range(*min_change..=*max_change);
|
||||||
Self::apply_production_quality_change(&mut conn, region_id, change)?;
|
Self::apply_production_quality_change(&mut conn, region_id, change)?;
|
||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "production_quality_change",
|
"type": "production_quality_change",
|
||||||
@@ -879,7 +879,7 @@ impl EventsWorker {
|
|||||||
max_percent,
|
max_percent,
|
||||||
} => {
|
} => {
|
||||||
if effect_roll < *probability {
|
if effect_roll < *probability {
|
||||||
let percent_change = rng.gen_range(*min_percent..=*max_percent);
|
let percent_change = rng.random_range(*min_percent..=*max_percent);
|
||||||
Self::apply_price_change(&mut conn, region_id, percent_change)?;
|
Self::apply_price_change(&mut conn, region_id, percent_change)?;
|
||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "price_change",
|
"type": "price_change",
|
||||||
@@ -907,7 +907,7 @@ impl EventsWorker {
|
|||||||
max_percent,
|
max_percent,
|
||||||
} => {
|
} => {
|
||||||
if effect_roll < *probability {
|
if effect_roll < *probability {
|
||||||
let percent_change = rng.gen_range(*min_percent..=*max_percent);
|
let percent_change = rng.random_range(*min_percent..=*max_percent);
|
||||||
Self::apply_transport_speed_change(&mut conn, region_id, percent_change)?;
|
Self::apply_transport_speed_change(&mut conn, region_id, percent_change)?;
|
||||||
effect_results.push(json!({
|
effect_results.push(json!({
|
||||||
"type": "transport_speed_change",
|
"type": "transport_speed_change",
|
||||||
@@ -1218,7 +1218,7 @@ impl EventsWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Berechne die prozentuale Änderung
|
// Berechne die prozentuale Änderung
|
||||||
let percent_change = rng.gen_range(min_percent..=max_percent);
|
let percent_change = rng.random_range(min_percent..=max_percent);
|
||||||
|
|
||||||
// Reduziere die Kapazität aller Stocks
|
// Reduziere die Kapazität aller Stocks
|
||||||
conn.prepare("update_stock_capacity_regional", QUERY_UPDATE_STOCK_CAPACITY_REGIONAL)?;
|
conn.prepare("update_stock_capacity_regional", QUERY_UPDATE_STOCK_CAPACITY_REGIONAL)?;
|
||||||
@@ -1283,7 +1283,7 @@ impl EventsWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Berechne die Änderung
|
// Berechne die Änderung
|
||||||
let quality_change = rng.gen_range(min_change..=max_change);
|
let quality_change = rng.random_range(min_change..=max_change);
|
||||||
|
|
||||||
// Reduziere die Qualität aller Häuser
|
// Reduziere die Qualität aller Häuser
|
||||||
conn.prepare("update_house_quality", QUERY_UPDATE_HOUSE_QUALITY)?;
|
conn.prepare("update_house_quality", QUERY_UPDATE_HOUSE_QUALITY)?;
|
||||||
@@ -1393,7 +1393,7 @@ impl EventsWorker {
|
|||||||
|
|
||||||
// Spezialfall: Unerwarteter Geldsegen -> absoluter Zufallsbetrag 1..500
|
// Spezialfall: Unerwarteter Geldsegen -> absoluter Zufallsbetrag 1..500
|
||||||
if event.id == "windfall" {
|
if event.id == "windfall" {
|
||||||
let absolute_change: f64 = rng.gen_range(1.0..=500.0);
|
let absolute_change: f64 = rng.random_range(1.0..=500.0);
|
||||||
let percent_change = if current_money > 0.0 {
|
let percent_change = if current_money > 0.0 {
|
||||||
(absolute_change / current_money) * 100.0
|
(absolute_change / current_money) * 100.0
|
||||||
} else {
|
} else {
|
||||||
@@ -1430,7 +1430,7 @@ impl EventsWorker {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let loss: f64 = rng.gen_range(1.0..=max_loss);
|
let loss: f64 = rng.random_range(1.0..=max_loss);
|
||||||
let percent_change = -(loss / current_money) * 100.0;
|
let percent_change = -(loss / current_money) * 100.0;
|
||||||
let absolute_change = -loss;
|
let absolute_change = -loss;
|
||||||
|
|
||||||
@@ -1456,7 +1456,7 @@ impl EventsWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Standardfall: prozentuale Änderung, optional mit Mindestbetrag für positive Änderungen
|
// Standardfall: prozentuale Änderung, optional mit Mindestbetrag für positive Änderungen
|
||||||
let percent_change = rng.gen_range(min_percent..=max_percent);
|
let percent_change = rng.random_range(min_percent..=max_percent);
|
||||||
let computed_change = current_money * (percent_change / 100.0);
|
let computed_change = current_money * (percent_change / 100.0);
|
||||||
let effective_change = match min_absolute_positive {
|
let effective_change = match min_absolute_positive {
|
||||||
Some(min_abs) if percent_change > 0.0 && computed_change < *min_abs => *min_abs,
|
Some(min_abs) if percent_change > 0.0 && computed_change < *min_abs => *min_abs,
|
||||||
@@ -1491,7 +1491,7 @@ impl EventsWorker {
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let percent_change = rng.gen_range(min_percent..=max_percent);
|
let percent_change = rng.random_range(min_percent..=max_percent);
|
||||||
Self::apply_storage_capacity_change(conn, user_id, percent_change)?;
|
Self::apply_storage_capacity_change(conn, user_id, percent_change)?;
|
||||||
|
|
||||||
Ok(Some(json!({
|
Ok(Some(json!({
|
||||||
@@ -1744,7 +1744,7 @@ impl EventsWorker {
|
|||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
.unwrap_or(100);
|
.unwrap_or(100);
|
||||||
|
|
||||||
let health_change = rng.gen_range(min_change..=max_change);
|
let health_change = rng.random_range(min_change..=max_change);
|
||||||
// Durch Unfälle/Krankheiten soll Gesundheit von Spieler-Charakteren nicht auf 0 fallen
|
// Durch Unfälle/Krankheiten soll Gesundheit von Spieler-Charakteren nicht auf 0 fallen
|
||||||
let new_health = (current_health + health_change).clamp(1, 100);
|
let new_health = (current_health + health_change).clamp(1, 100);
|
||||||
|
|
||||||
@@ -1816,7 +1816,7 @@ impl EventsWorker {
|
|||||||
.and_then(|v| v.parse::<i32>().ok())
|
.and_then(|v| v.parse::<i32>().ok())
|
||||||
.unwrap_or(100);
|
.unwrap_or(100);
|
||||||
|
|
||||||
let health_change = rng.gen_range(min_change..=max_change);
|
let health_change = rng.random_range(min_change..=max_change);
|
||||||
let user_id: Option<i32> = row
|
let user_id: Option<i32> = row
|
||||||
.get("user_id")
|
.get("user_id")
|
||||||
.and_then(|v| v.parse::<i32>().ok());
|
.and_then(|v| v.parse::<i32>().ok());
|
||||||
@@ -2235,9 +2235,9 @@ impl EventsWorker {
|
|||||||
|
|
||||||
// 3. Berechne Schäden
|
// 3. Berechne Schäden
|
||||||
let inventory_damage_percent =
|
let inventory_damage_percent =
|
||||||
rng.gen_range(params.inventory_damage_min_percent..=params.inventory_damage_max_percent);
|
rng.random_range(params.inventory_damage_min_percent..=params.inventory_damage_max_percent);
|
||||||
let storage_destruction_percent =
|
let storage_destruction_percent =
|
||||||
rng.gen_range(params.storage_destruction_min_percent..=params.storage_destruction_max_percent);
|
rng.random_range(params.storage_destruction_min_percent..=params.storage_destruction_max_percent);
|
||||||
|
|
||||||
let total_stocks = stock_rows.len();
|
let total_stocks = stock_rows.len();
|
||||||
let stocks_to_destroy_requested = ((total_stocks as f64 * storage_destruction_percent / 100.0)
|
let stocks_to_destroy_requested = ((total_stocks as f64 * storage_destruction_percent / 100.0)
|
||||||
@@ -2455,9 +2455,9 @@ impl EventsWorker {
|
|||||||
|
|
||||||
// 3. Berechne Schäden
|
// 3. Berechne Schäden
|
||||||
let inventory_damage_percent =
|
let inventory_damage_percent =
|
||||||
rng.gen_range(params.inventory_damage_min_percent..=params.inventory_damage_max_percent);
|
rng.random_range(params.inventory_damage_min_percent..=params.inventory_damage_max_percent);
|
||||||
let storage_destruction_percent =
|
let storage_destruction_percent =
|
||||||
rng.gen_range(params.storage_destruction_min_percent..=params.storage_destruction_max_percent);
|
rng.random_range(params.storage_destruction_min_percent..=params.storage_destruction_max_percent);
|
||||||
|
|
||||||
let total_stocks = stock_rows.len();
|
let total_stocks = stock_rows.len();
|
||||||
let stocks_to_destroy_requested = ((total_stocks as f64 * storage_destruction_percent / 100.0)
|
let stocks_to_destroy_requested = ((total_stocks as f64 * storage_destruction_percent / 100.0)
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ use std::sync::atomic::Ordering;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use rand::distributions::{Distribution, Uniform};
|
|
||||||
use rand::rngs::StdRng;
|
use rand::rngs::StdRng;
|
||||||
use rand::SeedableRng;
|
use rand::{Rng, SeedableRng};
|
||||||
|
|
||||||
use super::base::{BaseWorker, Worker, WorkerState};
|
use super::base::{BaseWorker, Worker, WorkerState};
|
||||||
use super::sql::{
|
use super::sql::{
|
||||||
@@ -46,7 +45,6 @@ const GAME_MONTH_SLICE_INTERVAL: Duration = Duration::from_secs(2 * 3600);
|
|||||||
pub struct FalukantFamilyWorker {
|
pub struct FalukantFamilyWorker {
|
||||||
base: BaseWorker,
|
base: BaseWorker,
|
||||||
rng: StdRng,
|
rng: StdRng,
|
||||||
dist: Uniform<f64>,
|
|
||||||
last_daily: Option<Instant>,
|
last_daily: Option<Instant>,
|
||||||
last_monthly: Option<Instant>,
|
last_monthly: Option<Instant>,
|
||||||
/// Gemeinsamer Tick für Liebschafts-Raten + Dienerschaft (Monatstick ≈ 2 h).
|
/// Gemeinsamer Tick für Liebschafts-Raten + Dienerschaft (Monatstick ≈ 2 h).
|
||||||
@@ -63,8 +61,10 @@ impl FalukantFamilyWorker {
|
|||||||
pub fn new(pool: ConnectionPool, broker: MessageBroker) -> Self {
|
pub fn new(pool: ConnectionPool, broker: MessageBroker) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base: BaseWorker::new("FalukantFamilyWorker", pool, broker),
|
base: BaseWorker::new("FalukantFamilyWorker", pool, broker),
|
||||||
rng: StdRng::from_entropy(),
|
rng: {
|
||||||
dist: Uniform::from(0.0..1.0),
|
let mut base_rng = rand::rng();
|
||||||
|
StdRng::from_rng(&mut base_rng)
|
||||||
|
},
|
||||||
last_daily: None,
|
last_daily: None,
|
||||||
last_monthly: None,
|
last_monthly: None,
|
||||||
last_game_month_slice: None,
|
last_game_month_slice: None,
|
||||||
@@ -361,7 +361,7 @@ impl FalukantFamilyWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if breakup_risk_pct > 0.0 && self.dist.sample(&mut self.rng) * 100.0 < breakup_risk_pct {
|
if breakup_risk_pct > 0.0 && self.rng.random_range(0.0..1.0) * 100.0 < breakup_risk_pct {
|
||||||
conn.execute("deactivate_lover", &[&l.rel_id])?;
|
conn.execute("deactivate_lover", &[&l.rel_id])?;
|
||||||
ended_rel_ids.insert(l.rel_id);
|
ended_rel_ids.insert(l.rel_id);
|
||||||
push_user_id(&mut breakup_socket_users, l.user1_id);
|
push_user_id(&mut breakup_socket_users, l.user1_id);
|
||||||
@@ -676,7 +676,7 @@ impl FalukantFamilyWorker {
|
|||||||
p -= 2.0;
|
p -= 2.0;
|
||||||
}
|
}
|
||||||
p = p.clamp(0.0, 25.0);
|
p = p.clamp(0.0, 25.0);
|
||||||
if self.dist.sample(&mut self.rng) * 100.0 < p {
|
if self.rng.random_range(0.0..1.0) * 100.0 < p {
|
||||||
self.base.broker.publish(format!(
|
self.base.broker.publish(format!(
|
||||||
r#"{{"event":"falukant_family_scandal_hint","relationship_id":{}}}"#,
|
r#"{{"event":"falukant_family_scandal_hint","relationship_id":{}}}"#,
|
||||||
l.rel_id
|
l.rel_id
|
||||||
@@ -709,7 +709,7 @@ impl FalukantFamilyWorker {
|
|||||||
}
|
}
|
||||||
let mut rng_malus_cids: Vec<i32> = Vec::new();
|
let mut rng_malus_cids: Vec<i32> = Vec::new();
|
||||||
for cid in unique_cids.iter().copied() {
|
for cid in unique_cids.iter().copied() {
|
||||||
let r = self.dist.sample(&mut self.rng) * 100.0;
|
let r = self.rng.random_range(0.0..1.0) * 100.0;
|
||||||
let malus = if r < 1.0 {
|
let malus = if r < 1.0 {
|
||||||
-5.0
|
-5.0
|
||||||
} else if r < 3.0 {
|
} else if r < 3.0 {
|
||||||
|
|||||||
@@ -177,19 +177,19 @@ fn try_resolve_one_raid(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
|
|
||||||
// Begegnung (Bande + Sichtbarkeit großer Ladung)
|
// Begegnung (Bande + Sichtbarkeit großer Ladung)
|
||||||
let visibility_penalty = ((transport_size as f64 / vehicle_cap as f64).min(2.0) - 1.0) * 0.04;
|
let visibility_penalty = ((transport_size as f64 / vehicle_cap as f64).min(2.0) - 1.0) * 0.04;
|
||||||
let encounter_p = (0.08_f64 + band_size as f64 * 0.012 + visibility_penalty).clamp(0.05, 0.45);
|
let encounter_p = (0.08_f64 + band_size as f64 * 0.012 + visibility_penalty).clamp(0.05, 0.45);
|
||||||
if !rng.gen_bool(encounter_p) {
|
if !rng.random_bool(encounter_p) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kampf
|
// Kampf
|
||||||
let raid_power = band_size + rng.gen_range(0..=band_size);
|
let raid_power = band_size + rng.random_range(0..=band_size);
|
||||||
let gmax = guard_count.max(1);
|
let gmax = guard_count.max(1);
|
||||||
let guard_power = guard_count + rng.gen_range(0..=gmax);
|
let guard_power = guard_count + rng.random_range(0..=gmax);
|
||||||
|
|
||||||
let outcome = if raid_power > (guard_power as f64 * 1.25) as i32 {
|
let outcome = if raid_power > (guard_power as f64 * 1.25) as i32 {
|
||||||
"major_success"
|
"major_success"
|
||||||
@@ -218,15 +218,15 @@ fn try_resolve_one_raid(
|
|||||||
|
|
||||||
// Beuteanteil (nie Totalverlust)
|
// Beuteanteil (nie Totalverlust)
|
||||||
let base_loot = match outcome {
|
let base_loot = match outcome {
|
||||||
"major_success" => rng.gen_range(0.35..0.60),
|
"major_success" => rng.random_range(0.35..0.60),
|
||||||
_ => rng.gen_range(0.15..0.45),
|
_ => rng.random_range(0.15..0.45),
|
||||||
};
|
};
|
||||||
let guard_mul = (1.0_f64 - 0.05_f64 * (guard_count.min(12) as f64)).max(0.35);
|
let guard_mul = (1.0_f64 - 0.05_f64 * (guard_count.min(12) as f64)).max(0.35);
|
||||||
let loot_share = (base_loot * guard_mul).clamp(0.05, 0.55);
|
let loot_share = (base_loot * guard_mul).clamp(0.05, 0.55);
|
||||||
let mut stolen = ((transport_size as f64) * loot_share).floor() as i32;
|
let mut stolen = ((transport_size as f64) * loot_share).floor() as i32;
|
||||||
stolen = stolen.clamp(1, transport_size - 1);
|
stolen = stolen.clamp(1, transport_size - 1);
|
||||||
|
|
||||||
let carry_loss = rng.gen_range(0.65..0.90);
|
let carry_loss = rng.random_range(0.65..0.90);
|
||||||
let mut to_store = (stolen as f64 * carry_loss).floor() as i32;
|
let mut to_store = (stolen as f64 * carry_loss).floor() as i32;
|
||||||
to_store = to_store.max(0).min(stolen);
|
to_store = to_store.max(0).min(stolen);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use crate::db::{ConnectionPool, DbError};
|
use crate::db::{ConnectionPool, DbError};
|
||||||
use crate::message_broker::MessageBroker;
|
use crate::message_broker::MessageBroker;
|
||||||
use rand::distributions::{Distribution, Uniform};
|
use rand::Rng;
|
||||||
use rand::rngs::StdRng;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@@ -64,8 +62,7 @@ impl StockageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_local_stocks(pool: &ConnectionPool, broker: &MessageBroker) -> Result<(), DbError> {
|
fn add_local_stocks(pool: &ConnectionPool, broker: &MessageBroker) -> Result<(), DbError> {
|
||||||
let mut rng = StdRng::from_entropy();
|
let mut rng = rand::rng();
|
||||||
let dist = Uniform::from(0.0..1.0);
|
|
||||||
|
|
||||||
let town_ids = Self::get_town_ids(pool)?;
|
let town_ids = Self::get_town_ids(pool)?;
|
||||||
eprintln!("[StockageManager] Prüfe {} Städte auf neue Lager", town_ids.len());
|
eprintln!("[StockageManager] Prüfe {} Städte auf neue Lager", town_ids.len());
|
||||||
@@ -76,7 +73,7 @@ impl StockageManager {
|
|||||||
// Das bedeutet: 2/217 ≈ 0.92% pro Stadt pro Durchlauf
|
// Das bedeutet: 2/217 ≈ 0.92% pro Stadt pro Durchlauf
|
||||||
// Pro Tag (1440 Durchläufe): ~73% Chance pro Stadt
|
// Pro Tag (1440 Durchläufe): ~73% Chance pro Stadt
|
||||||
// Erhöht von 2/2161 (0.0926%) auf 2/217 (0.92%) = 10x höher
|
// Erhöht von 2/2161 (0.0926%) auf 2/217 (0.92%) = 10x höher
|
||||||
let roll: f64 = dist.sample(&mut rng) * 216.0_f64;
|
let roll: f64 = rng.random_range(0.0..1.0) * 216.0_f64;
|
||||||
let chance = roll.round();
|
let chance = roll.round();
|
||||||
if chance <= 1.0 {
|
if chance <= 1.0 {
|
||||||
eprintln!("[StockageManager] Erstelle Lager für Stadt {}", town_id);
|
eprintln!("[StockageManager] Erstelle Lager für Stadt {}", town_id);
|
||||||
@@ -185,4 +182,3 @@ impl Worker for StockageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::db::{ConnectionPool, DbError, Row, Rows};
|
use crate::db::{ConnectionPool, DbError, Row, Rows};
|
||||||
use crate::message_broker::MessageBroker;
|
use crate::message_broker::MessageBroker;
|
||||||
use rand::distributions::{Distribution, Uniform};
|
use rand::prelude::{IndexedRandom, SliceRandom};
|
||||||
use rand::seq::SliceRandom;
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::Value as Json;
|
use serde_json::Value as Json;
|
||||||
@@ -388,9 +387,8 @@ impl UndergroundWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let current = parse_i32(&rows[0], "health", 0);
|
let current = parse_i32(&rows[0], "health", 0);
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let dist = Uniform::from(0..=current.max(0));
|
let new_health = rng.random_range(0..=current.max(0));
|
||||||
let new_health = dist.sample(&mut rng);
|
|
||||||
|
|
||||||
conn.execute("ug_update_char_health", &[&victim_id, &new_health])?;
|
conn.execute("ug_update_char_health", &[&victim_id, &new_health])?;
|
||||||
|
|
||||||
@@ -705,7 +703,7 @@ impl UndergroundWorker {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
let mut to_remove = random_ll(1, cap);
|
let mut to_remove = random_ll(1, cap);
|
||||||
rows.shuffle(&mut rng);
|
rows.shuffle(&mut rng);
|
||||||
|
|
||||||
@@ -867,7 +865,7 @@ impl UndergroundWorker {
|
|||||||
let cap = max(1_i64, total / 2);
|
let cap = max(1_i64, total / 2);
|
||||||
let mut to_remove = random_ll(1, cap);
|
let mut to_remove = random_ll(1, cap);
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
rows.shuffle(&mut rng);
|
rows.shuffle(&mut rng);
|
||||||
|
|
||||||
let mut affected = Vec::new();
|
let mut affected = Vec::new();
|
||||||
@@ -1107,7 +1105,7 @@ impl UndergroundWorker {
|
|||||||
}
|
}
|
||||||
let pick = *best_indices
|
let pick = *best_indices
|
||||||
.as_slice()
|
.as_slice()
|
||||||
.choose(&mut rand::thread_rng())
|
.choose(&mut rand::rng())
|
||||||
.unwrap_or(&scored[0].1);
|
.unwrap_or(&scored[0].1);
|
||||||
let target = &lover_rows[pick];
|
let target = &lover_rows[pick];
|
||||||
|
|
||||||
@@ -1542,18 +1540,18 @@ fn parse_opt_i32(row: &Row, key: &str) -> Option<i32> {
|
|||||||
// Hilfsfunktionen für Zufall und Parsing
|
// Hilfsfunktionen für Zufall und Parsing
|
||||||
|
|
||||||
fn random_int(lo: i32, hi: i32) -> i32 {
|
fn random_int(lo: i32, hi: i32) -> i32 {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
rng.gen_range(lo..=hi)
|
rng.random_range(lo..=hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_ll(lo: i64, hi: i64) -> i64 {
|
fn random_ll(lo: i64, hi: i64) -> i64 {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
rng.gen_range(lo..=hi)
|
rng.random_range(lo..=hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_indices(n: usize, k: usize) -> Vec<usize> {
|
fn random_indices(n: usize, k: usize) -> Vec<usize> {
|
||||||
let mut idx: Vec<usize> = (0..n).collect();
|
let mut idx: Vec<usize> = (0..n).collect();
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
idx.shuffle(&mut rng);
|
idx.shuffle(&mut rng);
|
||||||
if k < idx.len() {
|
if k < idx.len() {
|
||||||
idx.truncate(k);
|
idx.truncate(k);
|
||||||
@@ -1562,8 +1560,8 @@ fn random_indices(n: usize, k: usize) -> Vec<usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn random_double(lo: f64, hi: f64) -> f64 {
|
fn random_double(lo: f64, hi: f64) -> f64 {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::rng();
|
||||||
rng.gen_range(lo..hi)
|
rng.random_range(lo..hi)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_i32(row: &Row, key: &str, default: i32) -> i32 {
|
fn parse_i32(row: &Row, key: &str, default: i32) -> i32 {
|
||||||
@@ -1620,4 +1618,3 @@ fn change_falukant_user_money(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
use crate::db::{ConnectionPool, DbError, Rows};
|
use crate::db::{ConnectionPool, DbError, Rows};
|
||||||
use crate::message_broker::MessageBroker;
|
use crate::message_broker::MessageBroker;
|
||||||
use chrono::{Local, NaiveDate};
|
use chrono::{Local, NaiveDate};
|
||||||
use rand::distributions::{Distribution, Uniform};
|
|
||||||
use rand::rngs::StdRng;
|
use rand::rngs::StdRng;
|
||||||
use rand::SeedableRng;
|
use rand::{Rng, SeedableRng};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
@@ -68,7 +67,6 @@ struct Character {
|
|||||||
pub struct UserCharacterWorker {
|
pub struct UserCharacterWorker {
|
||||||
base: BaseWorker,
|
base: BaseWorker,
|
||||||
rng: StdRng,
|
rng: StdRng,
|
||||||
dist: Uniform<f64>,
|
|
||||||
last_hourly_run: Option<Instant>,
|
last_hourly_run: Option<Instant>,
|
||||||
last_pregnancy_run: Option<Instant>,
|
last_pregnancy_run: Option<Instant>,
|
||||||
/// Letzter Kalendertag, an dem Ehe-Konzeption (oder Legacy-Instant) gelaufen ist — höchstens 1×/Tag.
|
/// Letzter Kalendertag, an dem Ehe-Konzeption (oder Legacy-Instant) gelaufen ist — höchstens 1×/Tag.
|
||||||
@@ -86,13 +84,12 @@ pub struct UserCharacterWorker {
|
|||||||
impl UserCharacterWorker {
|
impl UserCharacterWorker {
|
||||||
pub fn new(pool: ConnectionPool, broker: MessageBroker) -> Self {
|
pub fn new(pool: ConnectionPool, broker: MessageBroker) -> Self {
|
||||||
let base = BaseWorker::new("UserCharacterWorker", pool, broker);
|
let base = BaseWorker::new("UserCharacterWorker", pool, broker);
|
||||||
let rng = StdRng::from_entropy();
|
let mut base_rng = rand::rng();
|
||||||
let dist = Uniform::from(0.0..1.0);
|
let rng = StdRng::from_rng(&mut base_rng);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
base,
|
base,
|
||||||
rng,
|
rng,
|
||||||
dist,
|
|
||||||
last_hourly_run: None,
|
last_hourly_run: None,
|
||||||
last_pregnancy_run: None,
|
last_pregnancy_run: None,
|
||||||
last_marriage_fertility_date: None,
|
last_marriage_fertility_date: None,
|
||||||
@@ -301,15 +298,14 @@ impl UserCharacterWorker {
|
|||||||
|
|
||||||
if age >= 45 {
|
if age >= 45 {
|
||||||
let probability = (0.1 + (age - 45) as f64 * 0.02).min(1.0);
|
let probability = (0.1 + (age - 45) as f64 * 0.02).min(1.0);
|
||||||
if self.dist.sample(&mut self.rng) < probability {
|
if self.rng.random_range(0.0..1.0) < probability {
|
||||||
let damage_dist = Uniform::from(1..=10);
|
return -self.rng.random_range(1..=10);
|
||||||
return -damage_dist.sample(&mut self.rng);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let probability = (age - 30) as f64 / 30.0;
|
let probability = (age - 30) as f64 / 30.0;
|
||||||
if self.dist.sample(&mut self.rng) < probability {
|
if self.rng.random_range(0.0..1.0) < probability {
|
||||||
-1
|
-1
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
@@ -686,7 +682,7 @@ impl UserCharacterWorker {
|
|||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
.unwrap_or("marriage");
|
.unwrap_or("marriage");
|
||||||
|
|
||||||
let gender = if self.dist.sample(&mut self.rng) < 0.5 {
|
let gender = if self.rng.random_range(0.0..1.0) < 0.5 {
|
||||||
"male"
|
"male"
|
||||||
} else {
|
} else {
|
||||||
"female"
|
"female"
|
||||||
@@ -741,7 +737,7 @@ impl UserCharacterWorker {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let gender = if self.dist.sample(&mut self.rng) < 0.5 {
|
let gender = if self.rng.random_range(0.0..1.0) < 0.5 {
|
||||||
"male"
|
"male"
|
||||||
} else {
|
} else {
|
||||||
"female"
|
"female"
|
||||||
@@ -1263,4 +1259,3 @@ impl Worker for UserCharacterWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user