|
|
@ -1,8 +1,14 @@ |
|
|
|
use rand::Rng; |
|
|
|
use crate::city::{SIZE, House, HouseLayout}; |
|
|
|
use rand::prelude::StdRng; |
|
|
|
use crate::city::{SIZE, House, HouseLayout, City}; |
|
|
|
use rand::prelude::*; |
|
|
|
use crate::db::LayoutDB; |
|
|
|
use crate::city; |
|
|
|
use std::collections::HashMap; |
|
|
|
use std::ops::Add; |
|
|
|
use itertools::Itertools; |
|
|
|
use rand::distributions::WeightedIndex; |
|
|
|
|
|
|
|
pub(crate) fn populate_random(layout: &mut HouseLayout, rng: &mut StdRng) { |
|
|
|
pub fn populate_random(layout: &mut HouseLayout, rng: &mut StdRng) { |
|
|
|
loop { |
|
|
|
loop { |
|
|
|
let x = rng.gen_range(0..SIZE); |
|
|
@ -19,3 +25,52 @@ pub(crate) fn populate_random(layout: &mut HouseLayout, rng: &mut StdRng) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub fn build_house_probabilities(city: &City, db: &LayoutDB, min_score: f64, max_score: f64) -> (WeightedIndex<f64>, Vec<House>){ |
|
|
|
let mut counts: HashMap<House, f64> = HashMap::new(); |
|
|
|
for layout in db.layouts() { |
|
|
|
let price = city::get_price(&city, layout.houses()) as f64; |
|
|
|
let value_range = max_score - min_score; |
|
|
|
let value = 1. - ((price - min_score) / value_range).max(0.).min(1.); |
|
|
|
|
|
|
|
for house in layout.houses() { |
|
|
|
*counts.entry(*house).or_default() += value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let houses: Vec<_> = counts.into_iter().filter(|(house, price)| *price != 0.).collect(); |
|
|
|
let index = WeightedIndex::new(houses.iter().map(|(house, price)| price)).unwrap(); |
|
|
|
|
|
|
|
(index, houses.iter().map(|(house, _)| *house).collect()) |
|
|
|
} |
|
|
|
|
|
|
|
pub fn populate_using_db(layout: &mut HouseLayout, mut rng: &mut StdRng, db: &LayoutDB, min_score: f64, max_score: f64, db_probability: f64) { |
|
|
|
let (mut index, houses) = build_house_probabilities(&layout.city, &db, min_score, max_score); |
|
|
|
|
|
|
|
loop { |
|
|
|
if rng.gen::<f64>() < db_probability { |
|
|
|
// TODO: Test without allowing buying covered tiles
|
|
|
|
let house = houses[index.sample(&mut rng)]; |
|
|
|
|
|
|
|
layout.add_house(house); |
|
|
|
|
|
|
|
if layout.is_valid() { |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
loop { |
|
|
|
let x = rng.gen_range(0..SIZE); |
|
|
|
let y = rng.gen_range(0..SIZE); |
|
|
|
let house = House::new(x, y); |
|
|
|
if layout.city.is_house_xy(x, y) && !layout.is_covered(house) { |
|
|
|
layout.add_house(house); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if layout.is_valid() { |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|