protohackers/problem_06/src/db.rs

187 lines
4.8 KiB
Rust
Raw Normal View History

use std::{
2023-05-20 18:16:09 +00:00
collections::{HashMap, HashSet},
net::SocketAddr,
};
use tokio::sync::mpsc;
2023-05-22 08:10:57 +00:00
use tracing::info;
use crate::frame::ServerFrames;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct DispatcherId(pub(crate) SocketAddr);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct CameraId(pub(crate) SocketAddr);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct Plate {
2023-05-21 18:27:51 +00:00
pub(crate) plate: PlateName,
2023-05-20 18:16:09 +00:00
pub(crate) timestamp: Timestamp,
}
2023-05-21 18:27:51 +00:00
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct PlateName(pub(crate) String);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct Camera {
2023-05-20 18:16:09 +00:00
pub(crate) road: Road,
pub(crate) mile: Mile,
pub(crate) limit: Limit,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct Ticket {
pub(crate) plate: String,
pub(crate) road: u16,
2023-05-20 18:16:09 +00:00
pub(crate) mile1: u16,
pub(crate) timestamp1: u32,
pub(crate) mile2: u16,
pub(crate) timestamp2: u32,
pub(crate) speed: u16,
}
impl From<Ticket> for ServerFrames {
fn from(ticket: Ticket) -> Self {
ServerFrames::Ticket {
plate: ticket.plate,
road: ticket.road,
mile1: ticket.mile1,
timestamp1: ticket.timestamp1,
mile2: ticket.mile2,
timestamp2: ticket.timestamp2,
speed: ticket.speed,
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
2023-05-20 18:16:09 +00:00
pub(crate) struct Road(pub(crate) u16);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct Limit(pub(crate) u16);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct Timestamp(pub(crate) u32);
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
pub(crate) struct Mile(pub(crate) u16);
#[derive(Debug)]
2023-05-22 12:05:42 +00:00
pub(crate) struct Db {
cameras: HashMap<CameraId, Camera>,
dispatchers: HashMap<Road, Vec<(DispatcherId, mpsc::Sender<ServerFrames>)>>,
2023-05-21 18:27:51 +00:00
plates: HashMap<(PlateName, Road), Vec<(Mile, Timestamp)>>,
2023-05-20 18:16:09 +00:00
ticketed_plates_by_day: HashSet<(Timestamp, String)>,
open_tickets: HashMap<Road, Vec<Ticket>>,
}
impl Db {
pub(crate) fn new() -> Db {
2023-05-22 12:05:42 +00:00
Db {
cameras: HashMap::new(),
dispatchers: HashMap::new(),
plates: HashMap::new(),
2023-05-20 18:16:09 +00:00
ticketed_plates_by_day: HashSet::new(),
open_tickets: HashMap::new(),
2023-05-22 12:05:42 +00:00
}
}
2023-05-20 18:16:09 +00:00
pub(crate) fn get_camera(&self, camera_id: CameraId) -> Option<Camera> {
2023-05-22 12:05:42 +00:00
self.cameras.get(&camera_id).cloned()
2023-05-20 18:16:09 +00:00
}
2023-05-22 12:05:42 +00:00
pub(crate) fn add_camera(&mut self, camera_id: CameraId, camera: Camera) {
self.cameras.insert(camera_id, camera);
}
pub(crate) fn add_dispatcher(
2023-05-22 12:05:42 +00:00
&mut self,
dispatcher_id: DispatcherId,
roads: Vec<u16>,
writer_stream: mpsc::Sender<ServerFrames>,
) {
2023-05-22 08:18:16 +00:00
info!("Adding new dispatcher for roads: {roads:?}");
for r in roads.iter() {
2023-05-22 12:05:42 +00:00
self.dispatchers
2023-05-20 18:16:09 +00:00
.entry(Road(*r))
.or_insert(Vec::new())
.push((dispatcher_id.clone(), writer_stream.clone()));
}
}
pub(crate) fn get_dispatcher_for_road(&self, road: Road) -> Option<mpsc::Sender<ServerFrames>> {
2023-05-22 12:05:42 +00:00
let senders = self.dispatchers.get(&road);
2023-05-20 18:16:09 +00:00
if senders.is_none() {
return None;
}
senders.unwrap().first().map(|(_, s)| s.clone())
}
2023-05-22 12:05:42 +00:00
pub(crate) fn add_open_ticket(&mut self, ticket: Ticket) {
2023-05-22 08:18:16 +00:00
info!("Adding open ticket: {ticket:?}");
2023-05-22 12:05:42 +00:00
self.open_tickets
2023-05-20 18:16:09 +00:00
.entry(Road(ticket.road))
.or_insert(Vec::new())
.push(ticket);
}
2023-05-21 15:58:51 +00:00
pub(crate) fn get_open_tickets(&self) -> Vec<Ticket> {
2023-05-22 12:05:42 +00:00
self.open_tickets.values().flatten().cloned().collect()
2023-05-21 15:58:51 +00:00
}
2023-05-22 12:05:42 +00:00
pub(crate) fn remove_open_ticket(&mut self, road: Road, ticket: Ticket) -> bool {
2023-05-22 08:18:16 +00:00
info!("Removing open ticket: {ticket:?}");
2023-05-22 12:05:42 +00:00
if let Some(tickets) = self.open_tickets.get_mut(&road) {
2023-05-22 05:20:10 +00:00
tickets.retain(|t| t.plate != ticket.plate);
2023-05-22 07:38:33 +00:00
if tickets.is_empty() {
2023-05-22 12:05:42 +00:00
self.open_tickets.remove(&road);
2023-05-22 07:38:33 +00:00
}
2023-05-22 05:20:10 +00:00
return true;
}
false
}
2023-05-20 18:16:09 +00:00
pub(crate) fn get_plates_by_road(
&self,
plate: Plate,
road: Road,
) -> Option<Vec<(Mile, Timestamp)>> {
2023-05-22 12:05:42 +00:00
self.plates.get(&(plate.plate, road)).cloned()
2023-05-20 18:16:09 +00:00
}
2023-05-22 12:05:42 +00:00
pub(crate) fn add_plate(&mut self, camera_id: CameraId, plate: Plate) {
2023-05-21 18:27:51 +00:00
//TODO: Check if the same plate was already added for the road AND MILE
2023-05-20 18:16:09 +00:00
let camera = self.get_camera(camera_id).unwrap();
2023-05-22 12:05:42 +00:00
match self
2023-05-20 18:16:09 +00:00
.plates
2023-05-21 18:27:51 +00:00
.get_mut(&(plate.plate.clone(), camera.road.clone()))
2023-05-20 18:16:09 +00:00
{
Some(v) => v.push((camera.mile, plate.timestamp)),
None => {
2023-05-22 12:05:42 +00:00
self.plates.insert(
2023-05-21 18:27:51 +00:00
(plate.clone().plate, camera.road),
2023-05-20 18:16:09 +00:00
vec![(camera.mile, plate.timestamp)],
);
}
}
}
2023-05-22 12:05:42 +00:00
pub(crate) fn ticket_plate(&mut self, day: u32, plate_name: PlateName) {
2023-05-22 08:53:24 +00:00
info!("Add {plate_name:?} for day:{day} ");
2023-05-22 12:05:42 +00:00
self.ticketed_plates_by_day
2023-05-21 18:27:51 +00:00
.insert((Timestamp(day), plate_name.0));
}
2023-05-20 18:16:09 +00:00
2023-05-21 18:27:51 +00:00
pub(crate) fn is_plate_ticketed_for_day(&self, day: u32, plate_name: PlateName) -> bool {
2023-05-22 08:53:24 +00:00
info!(
"Current ticketed plates, by day: {:?}",
2023-05-22 12:05:42 +00:00
self.ticketed_plates_by_day
2023-05-22 08:53:24 +00:00
);
2023-05-22 12:05:42 +00:00
self.ticketed_plates_by_day
2023-05-21 18:27:51 +00:00
.contains(&(Timestamp(day), plate_name.0))
2023-05-20 18:16:09 +00:00
}
}