From a1d1413d1d62059b1031402717c59ce088b312db Mon Sep 17 00:00:00 2001 From: Paris DOUADY Date: Tue, 9 Jan 2024 23:44:38 +0100 Subject: [PATCH] wip social network --- simulation/src/init.rs | 3 + simulation/src/souls/mod.rs | 1 + simulation/src/souls/social_network.rs | 91 ++++++++++++++++++++++++++ simulation/src/world.rs | 1 + 4 files changed, 96 insertions(+) create mode 100644 simulation/src/souls/social_network.rs diff --git a/simulation/src/init.rs b/simulation/src/init.rs index f0bb9c75..b1101c8e 100644 --- a/simulation/src/init.rs +++ b/simulation/src/init.rs @@ -9,6 +9,7 @@ use crate::physics::coworld_synchronize; use crate::souls::freight_station::freight_station_system; use crate::souls::goods_company::{company_system, GoodsCompanyRegistry}; use crate::souls::human::update_decision_system; +use crate::souls::social_network::{clean_kinships_system, SocialNetworkRes}; use crate::transportation::pedestrian_decision_system; use crate::transportation::road::{vehicle_decision_system, vehicle_state_update_system}; use crate::transportation::testing_vehicles::{random_vehicles_update, RandomVehicles}; @@ -45,6 +46,7 @@ pub fn init() { register_system("freight_station", freight_station_system); register_system("random_vehicles", random_vehicles_update); register_system("update_map", |_, res| res.write::().update()); + register_system("social_cleaner", clean_kinships_system); register_system_sim("add_souls_to_empty_buildings", add_souls_to_empty_buildings); @@ -62,6 +64,7 @@ pub fn init() { register_init(init_market); + register_resource_default::("social_network"); register_resource_default::("multiplayer_state"); register_resource_default::("random_vehicles"); register_resource_default::("tick"); diff --git a/simulation/src/souls/mod.rs b/simulation/src/souls/mod.rs index 499bdf13..b89a4b08 100644 --- a/simulation/src/souls/mod.rs +++ b/simulation/src/souls/mod.rs @@ -15,6 +15,7 @@ pub mod desire; pub mod freight_station; pub mod goods_company; pub mod human; +pub mod social_network; /// Adds souls to empty buildings pub(crate) fn add_souls_to_empty_buildings(sim: &mut Simulation) { diff --git a/simulation/src/souls/social_network.rs b/simulation/src/souls/social_network.rs new file mode 100644 index 00000000..acf0cbe4 --- /dev/null +++ b/simulation/src/souls/social_network.rs @@ -0,0 +1,91 @@ +use crate::utils::resources::Resources; +use crate::{HumanID, World}; +use common::scroll::BTreeMapScroller; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::ops::Bound; + +#[derive(Default, Serialize, Deserialize)] +pub struct SocialNetworkRes { + // Symmetric + kinship: BTreeMap<(HumanID, HumanID), f32>, + + social_maker_pivot: Option, + + cleaner: BTreeMapScroller<(HumanID, HumanID)>, +} + +impl SocialNetworkRes { + pub fn new() -> Self { + Self::default() + } + + pub fn set_kinship(&mut self, a: HumanID, b: HumanID, value: f32) { + self.kinship.insert((a, b), value); + self.kinship.insert((b, a), value); + } + + /// If kinship is not set, returns 0.0 + pub fn kinship(&self, a: HumanID, b: HumanID) -> f32 { + self.kinship.get(&(a, b)).copied().unwrap_or(0.0) + } + + /// may return kinships to nonexistent humans + pub fn nonzero_kinships(&self, a: HumanID) -> impl Iterator + '_ { + self.kinship + .range((a, HumanID::default())..) + .take_while(move |(x, _)| x.0 == a) + .map(|(x, y)| (x.1, *y)) + } +} + +pub fn generate_social_events(world: &mut World, res: &mut Resources) { + let mut social = res.write::(); + + fn next_pivot(kinship: &BTreeMap<(HumanID, HumanID), f32>, pivot: &mut Option) { + let left_b = pivot + .map(|v| Bound::Excluded((v, HumanID::default()))) + .unwrap_or(Bound::Unbounded); + + *pivot = kinship + .range((left_b, Bound::Unbounded)) + .next() + .map(|(x, _)| x.0); + } + + let SocialNetworkRes { + ref kinship, + ref mut social_maker_pivot, + .. + } = *social; + + for _ in 0..10 { + next_pivot(kinship, social_maker_pivot); + let Some(v) = *social_maker_pivot else { + break; + }; + } +} + +pub fn clean_kinships_system(world: &mut World, res: &mut Resources) { + let mut social = res.write::(); + + let mut to_remove = Vec::new(); + + let SocialNetworkRes { + ref kinship, + ref mut cleaner, + .. + } = *social; + + for (pair, _) in cleaner.iter(&kinship).take(10) { + if !world.humans.contains_key(pair.0) || !world.humans.contains_key(pair.1) { + to_remove.push(pair.clone()); + } + } + + for pair in to_remove { + social.kinship.remove(&pair); + social.kinship.remove(&(pair.1, pair.0)); + } +} diff --git a/simulation/src/world.rs b/simulation/src/world.rs index d7661ecf..504b13a3 100644 --- a/simulation/src/world.rs +++ b/simulation/src/world.rs @@ -11,6 +11,7 @@ use crate::souls::human::{HumanDecision, PersonalInfo}; use crate::transportation::train::{Locomotive, LocomotiveReservation, RailWagon}; use crate::transportation::{Location, Pedestrian, Vehicle, VehicleKind, VehicleState}; use crate::utils::par_command_buffer::SimDrop; +use crate::utils::rand_provider::RandProvider; use crate::utils::resources::Resources; use crate::{impl_entity, impl_trans, SoulID}; use derive_more::{From, TryInto};