[lab3] Decomposed gui
This commit is contained in:
parent
642bb6619d
commit
50db706436
37
lab3/src/gui/data.rs
Normal file
37
lab3/src/gui/data.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use bgtu_ai_utility::graph::CompleteGraph;
|
||||||
|
use bgtu_ai_utility::UpdatePending;
|
||||||
|
use crate::algo::{AntsSimulationConfig, AntsSimulationState};
|
||||||
|
|
||||||
|
pub(crate)enum GlobalState {
|
||||||
|
Edit,
|
||||||
|
Running,
|
||||||
|
}
|
||||||
|
pub(crate) struct MyApp {
|
||||||
|
pub simulation: AntsSimulationState,
|
||||||
|
pub config: AntsSimulationConfig,
|
||||||
|
pub vertex_update: UpdatePending,
|
||||||
|
pub state: GlobalState,
|
||||||
|
pub vertex_locations: Vec<(f32, f32)>,
|
||||||
|
pub ants_per_vertex: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyApp {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
return Self {
|
||||||
|
simulation: AntsSimulationState {
|
||||||
|
graph: CompleteGraph::new(),
|
||||||
|
ants: Vec::new(),
|
||||||
|
},
|
||||||
|
vertex_update: UpdatePending::NoChange,
|
||||||
|
config: AntsSimulationConfig {
|
||||||
|
ferment_weight: 0.5,
|
||||||
|
heuristic_coefficient: 0.5,
|
||||||
|
q: 1.0,
|
||||||
|
r: 0.5,
|
||||||
|
},
|
||||||
|
state: GlobalState::Edit {},
|
||||||
|
vertex_locations: Vec::new(),
|
||||||
|
ants_per_vertex: 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
47
lab3/src/gui/graph.rs
Normal file
47
lab3/src/gui/graph.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use super::{GlobalState, MyApp};
|
||||||
|
use crate::algo::updateState;
|
||||||
|
use bgtu_ai_utility::gui::render_graph;
|
||||||
|
use eframe::egui::Ui;
|
||||||
|
|
||||||
|
pub(crate) fn graph_with_controls(ui: &mut Ui, data: &mut MyApp) {
|
||||||
|
ui.vertical(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Exit").clicked() {
|
||||||
|
data.state = GlobalState::Edit
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.button("Step").clicked() {
|
||||||
|
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
|
||||||
|
}
|
||||||
|
ui.label("");
|
||||||
|
});
|
||||||
|
draw_ants(ui, data);
|
||||||
|
if ui.input(|i| i.viewport().close_requested()) {
|
||||||
|
data.state = GlobalState::Edit
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_ants(ui: &mut Ui, data: &mut MyApp) {
|
||||||
|
let mut cap: f64 = 0.000000000001;
|
||||||
|
|
||||||
|
for w in data
|
||||||
|
.simulation
|
||||||
|
.graph
|
||||||
|
.edges
|
||||||
|
.iter()
|
||||||
|
.map(|e| e.extra.ferment_intensity)
|
||||||
|
{
|
||||||
|
if w > cap {
|
||||||
|
cap = w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_graph(
|
||||||
|
ui,
|
||||||
|
&data.simulation.graph.vertices,
|
||||||
|
data.vertex_locations.as_mut_slice(),
|
||||||
|
&data.simulation.graph.edges,
|
||||||
|
|e| e.extra.ferment_intensity / cap,
|
||||||
|
)
|
||||||
|
}
|
||||||
83
lab3/src/gui/input.rs
Normal file
83
lab3/src/gui/input.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
use eframe::egui::Ui;
|
||||||
|
use bgtu_ai_utility::gui::labeled_slider;
|
||||||
|
use bgtu_ai_utility::gui::lengths_table::draw_lengths_table;
|
||||||
|
use bgtu_ai_utility::UpdatePending;
|
||||||
|
use crate::algo::Ant;
|
||||||
|
use super::{GlobalState, MyApp};
|
||||||
|
|
||||||
|
pub(crate) fn input(ui: &mut Ui, data: &mut MyApp) {
|
||||||
|
let mut run: bool = false;
|
||||||
|
|
||||||
|
labeled_slider(
|
||||||
|
ui,
|
||||||
|
"Ferment weight",
|
||||||
|
&mut data.config.ferment_weight,
|
||||||
|
0.0..=1.0,
|
||||||
|
0.001,
|
||||||
|
);
|
||||||
|
ui.label("");
|
||||||
|
labeled_slider(
|
||||||
|
ui,
|
||||||
|
"Heuristic coefficient",
|
||||||
|
&mut data.config.heuristic_coefficient,
|
||||||
|
0.0..=1.0,
|
||||||
|
0.001,
|
||||||
|
);
|
||||||
|
ui.label("");
|
||||||
|
labeled_slider(ui, "Q", &mut data.config.q, 0.0..=1.0, 0.001);
|
||||||
|
ui.label("");
|
||||||
|
labeled_slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001);
|
||||||
|
ui.label("");
|
||||||
|
labeled_slider(
|
||||||
|
ui,
|
||||||
|
"Ants per vertex",
|
||||||
|
&mut data.ants_per_vertex,
|
||||||
|
1..=100,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
ui.label("");
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Add vertex").clicked() {
|
||||||
|
data.vertex_update = UpdatePending::Add;
|
||||||
|
}
|
||||||
|
ui.separator();
|
||||||
|
run = ui.button("Run").clicked();
|
||||||
|
});
|
||||||
|
|
||||||
|
draw_lengths_table(
|
||||||
|
ui,
|
||||||
|
&mut data.simulation.graph.vertices,
|
||||||
|
&mut data.simulation.graph.edges,
|
||||||
|
&mut data.vertex_update,
|
||||||
|
);
|
||||||
|
|
||||||
|
if run {
|
||||||
|
let mut coords = vec![(0.0, 0.0); data.simulation.graph.vertices.capacity()];
|
||||||
|
|
||||||
|
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
||||||
|
coords[i] = (
|
||||||
|
rand::random::<f32>() * 0.8 + 0.1,
|
||||||
|
rand::random::<f32>() * 0.8 + 0.1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data.state = GlobalState::Running;
|
||||||
|
data.vertex_locations = coords;
|
||||||
|
|
||||||
|
let allowed_locations = data
|
||||||
|
.simulation
|
||||||
|
.graph.vertices
|
||||||
|
.iter_indexed()
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.collect::<HashSet<usize>>();
|
||||||
|
|
||||||
|
let mut ants = Vec::new();
|
||||||
|
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
||||||
|
for _ in 0..data.ants_per_vertex {
|
||||||
|
ants.push(Ant::new(i, allowed_locations.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.simulation.ants = ants;
|
||||||
|
}
|
||||||
|
}
|
||||||
7
lab3/src/gui/mod.rs
Normal file
7
lab3/src/gui/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
mod data;
|
||||||
|
mod input;
|
||||||
|
mod graph;
|
||||||
|
|
||||||
|
pub(crate) use data::{MyApp, GlobalState};
|
||||||
|
pub(crate) use input::input;
|
||||||
|
pub(crate) use graph::graph_with_controls;
|
||||||
199
lab3/src/main.rs
199
lab3/src/main.rs
@ -1,66 +1,22 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
|
|
||||||
mod algo;
|
mod algo;
|
||||||
|
mod gui;
|
||||||
|
|
||||||
use crate::algo::{
|
use crate::algo::EdgeExtraData;
|
||||||
Ant, AntsSimulationConfig, AntsSimulationState, EdgeExtraData, EdgesVec, VerticesVec,
|
use bgtu_ai_utility::gui::boot_eframe;
|
||||||
updateState,
|
use bgtu_ai_utility::gui::subwindow;
|
||||||
};
|
|
||||||
use bgtu_ai_utility::UpdatePending;
|
use bgtu_ai_utility::UpdatePending;
|
||||||
use bgtu_ai_utility::gui::lengths_table::draw_lengths_table;
|
|
||||||
use bgtu_ai_utility::gui::render_graph;
|
|
||||||
use bgtu_ai_utility::gui::{boot_eframe, labeled_slider};
|
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use eframe::egui::{Frame, Ui};
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use bgtu_ai_utility::graph::CompleteGraph;
|
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
return boot_eframe(
|
return boot_eframe("Ants simulation", || gui::MyApp::new());
|
||||||
"Ants simulation",
|
|
||||||
|| MyApp::new()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GlobalState {
|
impl eframe::App for gui::MyApp {
|
||||||
Edit,
|
|
||||||
Running,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MyApp {
|
|
||||||
simulation: AntsSimulationState,
|
|
||||||
config: AntsSimulationConfig,
|
|
||||||
vertex_update: UpdatePending,
|
|
||||||
state: GlobalState,
|
|
||||||
vertex_locations: Vec<(f32, f32)>,
|
|
||||||
ants_per_vertex: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MyApp {
|
|
||||||
fn new() -> Self {
|
|
||||||
return Self {
|
|
||||||
simulation: AntsSimulationState {
|
|
||||||
graph: CompleteGraph::new(),
|
|
||||||
ants: Vec::new(),
|
|
||||||
},
|
|
||||||
vertex_update: UpdatePending::NoChange,
|
|
||||||
config: AntsSimulationConfig {
|
|
||||||
ferment_weight: 0.5,
|
|
||||||
heuristic_coefficient: 0.5,
|
|
||||||
q: 1.0,
|
|
||||||
r: 0.5,
|
|
||||||
},
|
|
||||||
state: GlobalState::Edit {},
|
|
||||||
vertex_locations: Vec::new(),
|
|
||||||
ants_per_vertex: 1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl eframe::App for MyApp {
|
|
||||||
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
||||||
egui::CentralPanel::default().show(ui, |ui| match self.state {
|
egui::CentralPanel::default().show(ui, |ui| match self.state {
|
||||||
GlobalState::Edit {} => {
|
gui::GlobalState::Edit {} => {
|
||||||
match self.vertex_update {
|
match self.vertex_update {
|
||||||
UpdatePending::NoChange => {}
|
UpdatePending::NoChange => {}
|
||||||
UpdatePending::Add => {
|
UpdatePending::Add => {
|
||||||
@ -74,141 +30,16 @@ impl eframe::App for MyApp {
|
|||||||
self.vertex_update = UpdatePending::NoChange;
|
self.vertex_update = UpdatePending::NoChange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
edit_panel(self, ui)
|
gui::input(ui, self)
|
||||||
}
|
}
|
||||||
GlobalState::Running { .. } => {
|
gui::GlobalState::Running { .. } => {
|
||||||
ui.add_enabled_ui(false, |ui| edit_panel(self, ui));
|
ui.add_enabled_ui(false, |ui| gui::input(ui, self));
|
||||||
ui.ctx().show_viewport_immediate(
|
subwindow(
|
||||||
egui::ViewportId::from_hash_of("Visualisation"),
|
ui, "visualisation", "Visualisation",
|
||||||
egui::ViewportBuilder::default()
|
|vb| vb.with_inner_size([640.0, 480.0]),
|
||||||
.with_title("Visualisation")
|
|ui| gui::graph_with_controls(ui, self),
|
||||||
.with_inner_size([640.0, 480.0])
|
).on_close(|| self.state = gui::GlobalState::Edit);
|
||||||
.with_resizable(false),
|
|
||||||
|ui, _| {
|
|
||||||
egui::CentralPanel::default()
|
|
||||||
.frame(Frame::default().inner_margin(0.0))
|
|
||||||
.show(ui, |ui| visualization_panel(self, ui));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edit_panel(data: &mut MyApp, ui: &mut Ui) {
|
|
||||||
let mut run: bool = false;
|
|
||||||
|
|
||||||
labeled_slider(
|
|
||||||
ui,
|
|
||||||
"Ferment weight",
|
|
||||||
&mut data.config.ferment_weight,
|
|
||||||
0.0..=1.0,
|
|
||||||
0.001,
|
|
||||||
);
|
|
||||||
ui.label("");
|
|
||||||
labeled_slider(
|
|
||||||
ui,
|
|
||||||
"Heuristic coefficient",
|
|
||||||
&mut data.config.heuristic_coefficient,
|
|
||||||
0.0..=1.0,
|
|
||||||
0.001,
|
|
||||||
);
|
|
||||||
ui.label("");
|
|
||||||
labeled_slider(ui, "Q", &mut data.config.q, 0.0..=1.0, 0.001);
|
|
||||||
ui.label("");
|
|
||||||
labeled_slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001);
|
|
||||||
ui.label("");
|
|
||||||
labeled_slider(
|
|
||||||
ui,
|
|
||||||
"Ants per vertex",
|
|
||||||
&mut data.ants_per_vertex,
|
|
||||||
1..=100,
|
|
||||||
1.0,
|
|
||||||
);
|
|
||||||
ui.label("");
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
if ui.button("Add vertex").clicked() {
|
|
||||||
data.vertex_update = UpdatePending::Add;
|
|
||||||
}
|
|
||||||
ui.separator();
|
|
||||||
run = ui.button("Run").clicked();
|
|
||||||
});
|
|
||||||
|
|
||||||
draw_lengths_table(
|
|
||||||
ui,
|
|
||||||
&mut data.simulation.graph.vertices,
|
|
||||||
&mut data.simulation.graph.edges,
|
|
||||||
&mut data.vertex_update,
|
|
||||||
);
|
|
||||||
|
|
||||||
if run {
|
|
||||||
let mut coords = vec![(0.0, 0.0); data.simulation.graph.vertices.capacity()];
|
|
||||||
|
|
||||||
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
|
||||||
coords[i] = (
|
|
||||||
rand::random::<f32>() * 0.8 + 0.1,
|
|
||||||
rand::random::<f32>() * 0.8 + 0.1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.state = GlobalState::Running;
|
|
||||||
data.vertex_locations = coords;
|
|
||||||
|
|
||||||
let allowed_locations = data
|
|
||||||
.simulation
|
|
||||||
.graph.vertices
|
|
||||||
.iter_indexed()
|
|
||||||
.map(|(i, _)| i)
|
|
||||||
.collect::<HashSet<usize>>();
|
|
||||||
|
|
||||||
let mut ants = Vec::new();
|
|
||||||
for (i, _) in data.simulation.graph.vertices.iter_indexed() {
|
|
||||||
for _ in 0..data.ants_per_vertex {
|
|
||||||
ants.push(Ant::new(i, allowed_locations.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.simulation.ants = ants;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visualization_panel(data: &mut MyApp, ui: &mut Ui) {
|
|
||||||
ui.vertical(|ui| {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
if ui.button("Exit").clicked() {
|
|
||||||
data.state = GlobalState::Edit
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui.button("Step").clicked() {
|
|
||||||
updateState(&mut data.simulation, &mut data.config, &mut rand::rng());
|
|
||||||
}
|
|
||||||
ui.label("");
|
|
||||||
});
|
|
||||||
draw_ants(data, ui);
|
|
||||||
if ui.input(|i| i.viewport().close_requested()) {
|
|
||||||
data.state = GlobalState::Edit
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_ants(data: &mut MyApp, ui: &mut Ui) {
|
|
||||||
let mut cap: f64 = 0.000000000001;
|
|
||||||
|
|
||||||
for w in data
|
|
||||||
.simulation
|
|
||||||
.graph.edges
|
|
||||||
.iter()
|
|
||||||
.map(|e| e.extra.ferment_intensity)
|
|
||||||
{
|
|
||||||
if w > cap {
|
|
||||||
cap = w
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render_graph(
|
|
||||||
ui,
|
|
||||||
&data.simulation.graph.vertices,
|
|
||||||
data.vertex_locations.as_mut_slice(),
|
|
||||||
&data.simulation.graph.edges,
|
|
||||||
|e| e.extra.ferment_intensity / cap,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user