use crate::city::House; use rusqlite::{Connection, NO_PARAMS, params, Result, Transaction}; use std::collections::HashMap; pub struct LayoutDB { connection: Connection, layouts: Vec } pub struct SavedLayout { id: usize, houses: Vec } impl SavedLayout { pub fn houses(&self) -> &Vec { &self.houses } } impl LayoutDB { pub fn from_file(filename: &str) -> Result { let connection = Connection::open(filename)?; let mut layouts: HashMap> = HashMap::new(); // We need to dispose the statement so we can move the connection later { let mut stmt = connection.prepare("SELECT layout_id, x, y FROM houses")?; let mut rows = stmt.query(NO_PARAMS)?; while let Some(row) = rows.next()? { let id: u32 = row.get(0)?; let x: u32 = row.get(1)?; let y: u32 = row.get(2)?; layouts.entry(id).or_default().push((x, y)); } } let layouts = layouts.into_iter().map(|(id, xy_pairs)| SavedLayout { id: id as usize, houses: xy_pairs.into_iter().map(|(x, y)| House { x: x as usize, y: y as usize }).collect(), } ).collect(); Ok(LayoutDB { connection, layouts }) } pub fn layouts(&self) -> &Vec { &self.layouts } pub fn add_layout(&mut self, houses: &Vec, fully_optimized: bool) -> Result<()> { let transaction = self.connection.transaction()?; transaction.execute("INSERT INTO layouts (is_fully_optimized) VALUES (?1)", params![fully_optimized])?; let layout_id = transaction.last_insert_rowid(); for house in houses { transaction.execute("INSERT INTO houses (layout_id, x, y) VALUES (?1, ?2, ?3)", params![layout_id, house.x as u32, house.y as u32])?; } transaction.commit()?; self.layouts.push(SavedLayout {id: layout_id as usize, houses: houses.clone()}); Ok(()) } }