|
@ -2,8 +2,12 @@ use crate::city::House; |
|
|
use rusqlite::{Connection, NO_PARAMS, params, Result}; |
|
|
use rusqlite::{Connection, NO_PARAMS, params, Result}; |
|
|
use std::collections::HashMap; |
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
|
pub struct LayoutDB { |
|
|
pub struct SqliteLayoutDB { |
|
|
connection: Connection, |
|
|
connection: Connection, |
|
|
|
|
|
memory_db: MemoryLayoutDB, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub struct MemoryLayoutDB { |
|
|
layouts: Vec<SavedLayout>, |
|
|
layouts: Vec<SavedLayout>, |
|
|
merge_lower_bounds: HashMap<(usize, usize, bool), MergeLowerBound>, |
|
|
merge_lower_bounds: HashMap<(usize, usize, bool), MergeLowerBound>, |
|
|
} |
|
|
} |
|
@ -57,7 +61,76 @@ impl SavedLayout { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
impl LayoutDB { |
|
|
impl MemoryLayoutDB { |
|
|
|
|
|
pub fn new(layouts: Vec<SavedLayout>, merge_lower_bounds: HashMap<(usize, usize, bool), MergeLowerBound>) -> Self { |
|
|
|
|
|
MemoryLayoutDB { layouts, merge_lower_bounds } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// This exists for use by the SqliteLayoutDB
|
|
|
|
|
|
fn add_layout_with_id(&mut self, houses: &Vec<House>, layout_id: usize, fully_optimized: bool) { |
|
|
|
|
|
self.layouts.push(SavedLayout { id: layout_id, houses: houses.clone() }); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub trait LayoutDB { |
|
|
|
|
|
fn layouts(&self) -> &Vec<SavedLayout>; |
|
|
|
|
|
fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool); |
|
|
|
|
|
fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32>; |
|
|
|
|
|
fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound); |
|
|
|
|
|
fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl LayoutDB for MemoryLayoutDB { |
|
|
|
|
|
fn layouts(&self) -> &Vec<SavedLayout> { |
|
|
|
|
|
&self.layouts |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) { |
|
|
|
|
|
let layout_id = self.layouts.iter().map(|x| x.id).max().unwrap_or_default() + 1; |
|
|
|
|
|
self.layouts.push(SavedLayout { id: layout_id, houses: houses.clone() }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> { |
|
|
|
|
|
if let Some(bound) = self.merge_lower_bounds.get(&(left_layout.id, right_layout.id, y_axis)) { |
|
|
|
|
|
return Some(bound.price); |
|
|
|
|
|
} |
|
|
|
|
|
None |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) { |
|
|
|
|
|
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) { |
|
|
|
|
|
for lower_bound in lower_bounds { |
|
|
|
|
|
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl LayoutDB for SqliteLayoutDB { |
|
|
|
|
|
fn layouts(&self) -> &Vec<SavedLayout> { |
|
|
|
|
|
self.layouts() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) { |
|
|
|
|
|
self.add_layout(houses, fully_optimized).unwrap(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> { |
|
|
|
|
|
self.get_merge_lower_bound(left_layout, right_layout, y_axis) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) { |
|
|
|
|
|
self.add_merge_lower_bound(lower_bound).unwrap() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) { |
|
|
|
|
|
self.add_merge_lower_bounds(lower_bounds).unwrap() |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl SqliteLayoutDB { |
|
|
pub fn from_file(filename: &str) -> Result<Self> { |
|
|
pub fn from_file(filename: &str) -> Result<Self> { |
|
|
let connection = Connection::open(filename)?; |
|
|
let connection = Connection::open(filename)?; |
|
|
let mut layouts: HashMap<u32, Vec<(u32, u32)>> = HashMap::new(); |
|
|
let mut layouts: HashMap<u32, Vec<(u32, u32)>> = HashMap::new(); |
|
@ -102,11 +175,12 @@ impl LayoutDB { |
|
|
} |
|
|
} |
|
|
).collect(); |
|
|
).collect(); |
|
|
|
|
|
|
|
|
Ok(LayoutDB { connection, layouts, merge_lower_bounds: merges }) |
|
|
let memory_db = MemoryLayoutDB::new(layouts, merges); |
|
|
|
|
|
Ok(SqliteLayoutDB { connection, memory_db}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn layouts(&self) -> &Vec<SavedLayout> { |
|
|
pub fn layouts(&self) -> &Vec<SavedLayout> { |
|
|
&self.layouts |
|
|
self.memory_db.layouts() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) -> Result<()> { |
|
|
pub fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) -> Result<()> { |
|
@ -119,15 +193,12 @@ impl LayoutDB { |
|
|
params![layout_id, house.x as u32, house.y as u32])?; |
|
|
params![layout_id, house.x as u32, house.y as u32])?; |
|
|
} |
|
|
} |
|
|
transaction.commit()?; |
|
|
transaction.commit()?; |
|
|
self.layouts.push(SavedLayout { id: layout_id as usize, houses: houses.clone() }); |
|
|
self.memory_db.add_layout_with_id(houses, layout_id as usize, fully_optimized); |
|
|
Ok(()) |
|
|
Ok(()) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> { |
|
|
pub fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> { |
|
|
if let Some(bound) = self.merge_lower_bounds.get(&(left_layout.id, right_layout.id, y_axis)) { |
|
|
self.memory_db.get_merge_lower_bound(left_layout, right_layout, y_axis) |
|
|
return Some(bound.price); |
|
|
|
|
|
} |
|
|
|
|
|
None |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) -> Result<()> { |
|
|
pub fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) -> Result<()> { |
|
@ -140,13 +211,13 @@ impl LayoutDB { |
|
|
], |
|
|
], |
|
|
)?; |
|
|
)?; |
|
|
transaction.commit()?; |
|
|
transaction.commit()?; |
|
|
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound); |
|
|
self.memory_db.add_merge_lower_bound(lower_bound); |
|
|
Ok(()) |
|
|
Ok(()) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) -> Result<()> { |
|
|
pub fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) -> Result<()> { |
|
|
let transaction = self.connection.transaction()?; |
|
|
let transaction = self.connection.transaction()?; |
|
|
for lower_bound in lower_bounds { |
|
|
for lower_bound in &lower_bounds { |
|
|
transaction.execute("INSERT INTO merge_lower_bounds (left_layout_id, right_layout_id, axis, price) VALUES (?1, ?2, ?3, ?4) ON CONFLICT(left_layout_id, right_layout_id) DO UPDATE SET price = ?4", |
|
|
transaction.execute("INSERT INTO merge_lower_bounds (left_layout_id, right_layout_id, axis, price) VALUES (?1, ?2, ?3, ?4) ON CONFLICT(left_layout_id, right_layout_id) DO UPDATE SET price = ?4", |
|
|
params![lower_bound.left_layout_id as u32, |
|
|
params![lower_bound.left_layout_id as u32, |
|
|
lower_bound.right_layout_id as u32, |
|
|
lower_bound.right_layout_id as u32, |
|
@ -154,9 +225,9 @@ impl LayoutDB { |
|
|
lower_bound.price |
|
|
lower_bound.price |
|
|
], |
|
|
], |
|
|
)?; |
|
|
)?; |
|
|
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound); |
|
|
|
|
|
} |
|
|
} |
|
|
transaction.commit()?; |
|
|
transaction.commit()?; |
|
|
|
|
|
self.memory_db.add_merge_lower_bounds(lower_bounds); |
|
|
Ok(()) |
|
|
Ok(()) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|