Skip to content

Commit

Permalink
feat: add checkpoints to the map and support for them when en/decodin…
Browse files Browse the repository at this point in the history
…g json
  • Loading branch information
CalliEve committed Dec 16, 2024
1 parent 3bbbbbc commit 42c543d
Show file tree
Hide file tree
Showing 21 changed files with 394 additions and 116 deletions.
2 changes: 2 additions & 0 deletions existing_maps/small_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
{
"source": "s0",
"target": "s1",
"nodes": [],
"lines": ["l0"]
},
{
"source": "s1",
"target": "s2",
"nodes": [],
"lines": ["l0"]
}
]
Expand Down
20 changes: 15 additions & 5 deletions src/algorithm/recalculate_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ pub enum Updater {

/// Attempt to route the edges of the map, retrying with different, random, edge
/// orders if it fails.
fn attempt_edge_routing(
async fn attempt_edge_routing(
settings: AlgorithmSettings,
map: &mut Map,
occupied: &mut OccupiedNodes,
mut edges: Vec<Edge>,
midway_updater: Updater,
) -> Result<()> {
let mut attempt = 0;
let mut found = false;
Expand All @@ -65,7 +66,9 @@ fn attempt_edge_routing(
&mut alg_map,
edges.clone(),
occupied.clone(),
);
midway_updater.clone(),
)
.await;

if let Err(e) = res {
log_print(
Expand Down Expand Up @@ -140,12 +143,12 @@ pub async fn recalculate_map(
super::LogType::Debug,
);

unsettle_map(map);

if let Updater::Updater(updater) = midway_updater.clone() {
updater(map.clone(), IDManager::to_data()).await;
}

unsettle_map(map);

let edges = order_edges(map)?;

log_print(
Expand All @@ -158,7 +161,14 @@ pub async fn recalculate_map(
updater(map.clone(), IDManager::to_data()).await;
}

attempt_edge_routing(settings, map, &mut occupied, edges)?;
attempt_edge_routing(
settings,
map,
&mut occupied,
edges,
midway_updater.clone(),
)
.await?;

if let Updater::Updater(updater) = midway_updater.clone() {
updater(map.clone(), IDManager::to_data()).await;
Expand Down
23 changes: 18 additions & 5 deletions src/algorithm/route_edges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use super::{
log_print,
occupation::OccupiedNodes,
AlgorithmSettings,
Updater,
};
use crate::{
models::{
Expand All @@ -14,7 +15,10 @@ use crate::{
Map,
Station,
},
utils::Result,
utils::{
IDManager,
Result,
},
Error,
};

Expand Down Expand Up @@ -112,11 +116,12 @@ fn split_overlap(
/// Route all the edges on the map (as given by the input list of edges) and
/// return them. This is the Route Edges algorithm in the paper.
#[allow(clippy::too_many_lines)] // mostly due to large calls like debug prints
pub fn route_edges(
pub async fn route_edges(
settings: AlgorithmSettings,
map: &mut Map,
mut edges: Vec<Edge>,
mut occupied: OccupiedNodes,
midway_updater: Updater,
) -> Result<OccupiedNodes> {
for edge in &mut edges {
if edge.is_locked() {
Expand Down Expand Up @@ -251,6 +256,10 @@ pub fn route_edges(
end_station.add_cost(*cost);
}
map.add_edge(edge.clone());

if let Updater::Updater(updater) = midway_updater.clone() {
updater(map.clone(), IDManager::to_data()).await;
}
}
Ok(occupied)
}
Expand All @@ -259,11 +268,13 @@ pub fn route_edges(
mod tests {
use std::collections::HashMap;

use futures_test::test;

use super::*;
use crate::models::Station;

#[test]
fn test_get_node_set() {
async fn test_get_node_set() {
let mut map = Map::new();
let station = Station::new((0, 0).into(), None);
map.add_station(station.clone());
Expand Down Expand Up @@ -308,7 +319,7 @@ mod tests {
}

#[test]
fn test_split_overlap() {
async fn test_split_overlap() {
let from = Station::new((0, 0).into(), None);
let from_set = vec![
(GridNode::from((0, 0)), 0.0),
Expand Down Expand Up @@ -356,7 +367,7 @@ mod tests {
}

#[test]
fn test_route_edges() {
async fn test_route_edges() {
let mut map = Map::new();
let edges = vec![];

Expand All @@ -365,7 +376,9 @@ mod tests {
&mut map,
edges,
HashMap::new(),
Updater::NoUpdates,
)
.await
.unwrap();

assert_eq!(result, HashMap::new());
Expand Down
11 changes: 8 additions & 3 deletions src/algorithm/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@ use crate::models::{
/// for moving in the algorithm.
pub fn unsettle_map(map: &mut Map) {
for station in map.get_mut_stations() {
station.unsettle();
station.set_cost(0.0);
if !station.is_locked() {
station.unsettle();
station.set_cost(0.0);
}
}
for edge in map.get_mut_edges() {
edge.unsettle();
if !edge.is_locked() {
edge.unsettle();
edge.set_nodes(Vec::new());
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/atoms/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ pub fn Button(
class += " rounded";

if smaller {
class += " text-xs";
class += " text-xs font-semibold";
} else if bigger {
class += " text-xl";
class += " text-xl font-semibold";
} else {
class += " text-sm font-semibold";
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/atoms/button_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ pub fn ButtonGroup(
/// These will be transformed into [`super::Button`] elements.
children: Vec<ButtonProps>,
) -> impl IntoView {
let class = "max-w-full flex align-center gap-px [&>*]:flex-1 \
let class = "max-w-full flex align-center gap-px \
[&>*]:flex-1 [&>*]:max-w-[50%] \
[&>*:not(:first-child):not(:last-child)]:ml-0 \
[&>*:not(:first-child):not(:last-child)]:rounded-none \
[&>*:not(:only-child):first-child]:rounded-r-none \
Expand Down
2 changes: 1 addition & 1 deletion src/components/canvas/mouse_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn on_mouse_up(map_state: &mut MapState, ev: &UiEvent, shift_key: bool) {
// Handle a click while having an operation selected
if let Some(action_type) = map_state.get_selected_action() {
match action_type {
ActionType::RemoveStation => {
ActionType::RemoveStation | ActionType::RemoveCheckpoint => {
if let Some(station_id) = station_at_node {
map.remove_station(station_id);
}
Expand Down
23 changes: 23 additions & 0 deletions src/components/molecules/station_info_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,17 @@ pub fn StationInfoBox() -> impl IntoView {
map_state
.get()
.get_clicked_on_station()
.filter(|s| !s.is_checkpoint())
.is_some()
};
let checkpoint_was_clicked = move || {
map_state
.get()
.get_clicked_on_station()
.filter(|s| s.is_checkpoint())
.is_some()
};

let position = Signal::derive(move || {
map_state
.get()
Expand Down Expand Up @@ -85,6 +94,7 @@ pub fn StationInfoBox() -> impl IntoView {
};

view! {
<>
<Show when=station_was_clicked>
<CanvasInfoBox
title="Station Info"
Expand All @@ -104,5 +114,18 @@ pub fn StationInfoBox() -> impl IntoView {
</div>
</CanvasInfoBox>
</Show>
<Show when=checkpoint_was_clicked>
<CanvasInfoBox
title="Checkpoint"
click_position=position
on_close=move || {
map_state.update(|state| {
state.clear_clicked_on_station();
});
}>
<></>
</CanvasInfoBox>
</Show>
</>
}
}
23 changes: 23 additions & 0 deletions src/components/organisms/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ pub fn Sidebar() -> impl IntoView {
});
};

let add_checkpoint = move |_| {
map_state.update(|state| {
state.select_station(SelectedStation::new_checkpoint());
});
};

let add_line = move |_| {
map_state.update(|state| {
let line = SelectedLine::new_line(state.get_mut_map());
Expand All @@ -68,6 +74,9 @@ pub fn Sidebar() -> impl IntoView {
let remove_station = move |_| update_action(ActionType::RemoveStation);
let remove_station_selected = action_selected(ActionType::RemoveStation);

let remove_checkpoint = move |_| update_action(ActionType::RemoveCheckpoint);
let remove_checkpoint_selected = action_selected(ActionType::RemoveCheckpoint);

let remove_line = move |_| update_action(ActionType::RemoveLine);
let remove_line_selected = action_selected(ActionType::RemoveLine);

Expand Down Expand Up @@ -159,6 +168,20 @@ pub fn Sidebar() -> impl IntoView {
.danger(true)
.build(),
]}/>
<ButtonGroup
children={vec![
ButtonProps::builder()
.text("Add Checkpoint")
.on_click(Box::new(add_checkpoint))
.can_focus(true)
.build(),
ButtonProps::builder()
.text("Remove Checkpoint")
.on_click(Box::new(remove_checkpoint))
.active(remove_checkpoint_selected)
.danger(true)
.build(),
]}/>
</div>
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/home.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn Home() -> impl IntoView {
<Navbar/>
</header>
<div class="grow flex flex-row justify-start">
<div class="flex-none self-start self-stretch w-1/5 md:w-52">
<div class="flex-none self-start self-stretch w-1/5 md:w-60">
<Sidebar/>
</div>
<div class="grow flex self-stretch">
Expand Down
4 changes: 4 additions & 0 deletions src/components/state/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ pub enum ActionType {
///
/// [`Station`]: crate::models::Station
RemoveStation,
/// User wants to remove a checkpoint [`Station`].
///
/// [`Station`]: crate::models::Station
RemoveCheckpoint,
/// User wants to remove a [`Line`].
///
/// [`Line`]: crate::models::Line
Expand Down
Loading

0 comments on commit 42c543d

Please sign in to comment.