From 16444210e20eae1b7d07f61a7eeeb3431e0025dd Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Sun, 8 Feb 2026 08:37:51 +0300 Subject: [PATCH] [lab3] Edit panel (without actions) --- lab3/src/algo/edges.rs | 8 +- lab3/src/algo/mod.rs | 9 ++- lab3/src/main.rs | 176 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 lab3/src/main.rs diff --git a/lab3/src/algo/edges.rs b/lab3/src/algo/edges.rs index 732bfbb..7d5a41e 100644 --- a/lab3/src/algo/edges.rs +++ b/lab3/src/algo/edges.rs @@ -16,7 +16,13 @@ pub struct EdgesVec { storage: Vec, } -impl EdgesVec {} +impl EdgesVec { + pub fn new() -> Self { + return Self { + storage: Vec::new(), + }; + } +} impl Index for EdgesVec { type Output = Edge; diff --git a/lab3/src/algo/mod.rs b/lab3/src/algo/mod.rs index b280f2d..5823aa5 100644 --- a/lab3/src/algo/mod.rs +++ b/lab3/src/algo/mod.rs @@ -1,4 +1,11 @@ mod edges; mod state; -pub use edges::EdgesVec; \ No newline at end of file +pub use edges::EdgesVec; + +pub struct AntsSimulationConfig { + pub ferment_weight: f64, + pub heuristic_coefficient: f64, + pub q: f64, + pub r: f64, +} diff --git a/lab3/src/main.rs b/lab3/src/main.rs new file mode 100644 index 0000000..5735a09 --- /dev/null +++ b/lab3/src/main.rs @@ -0,0 +1,176 @@ +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release + +mod algo; + +use crate::algo::{AntsSimulationConfig, EdgesVec}; +use eframe::egui; +use eframe::egui::scroll_area::ScrollBarVisibility; +use eframe::egui::{ScrollArea, Ui}; +use eframe::emath::Numeric; +use egui_extras::{Column, TableBuilder}; +use std::collections::HashSet; +use std::ops::RangeInclusive; +use std::ptr; +use std::ptr::{NonNull, fn_addr_eq}; + +fn main() -> eframe::Result { + let options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default().with_inner_size([640.0, 400.0]), + ..Default::default() + }; + eframe::run_native( + "Ants simulation", + options, + Box::new(|_cc| Ok(Box::::default())), + ) +} + +enum UpdatePending { + NoChange, + Add, + Remove(usize), +} + +enum ViewState { + Stop, + Running { lastUpdateTimestamp: u64 }, + VertexMove { vertexId: usize }, +} + +enum GlobalState { + Edit {}, + Running { view_state: ViewState }, +} + +struct MyApp { + edges: EdgesVec, + vertices: Vec>, + config: AntsSimulationConfig, + vertex_update: UpdatePending, + speed: u32, + state: GlobalState, +} + +impl Default for MyApp { + fn default() -> Self { + return Self { + edges: EdgesVec::new(), + vertices: Vec::new(), + vertex_update: UpdatePending::NoChange, + speed: 1, + config: AntsSimulationConfig { + ferment_weight: 0.5, + heuristic_coefficient: 0.5, + q: 1.0, + r: 0.5, + }, + state: GlobalState::Edit {}, + }; + } +} + +fn _slider( + ui: &mut Ui, + name: &str, + storage: &mut T, + range: RangeInclusive, + step: f64, +) { + let label = ui.label(name); + + ui.scope(|ui| { + ui.spacing_mut().slider_width = ui.available_width() + - ui.spacing().interact_size.x + - ui.spacing().button_padding.x * 2.0; + ui.add(egui::Slider::new(storage, range).step_by(step)) + .labelled_by(label.id); + }); +} + +impl eframe::App for MyApp { + fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) { + egui::CentralPanel::default().show(ui, |ui| { + edit_panel(self, ui) + }); + } +} + +fn edit_panel(data: &mut MyApp, ui: &mut Ui) { + let run: bool; + + _slider( + ui, + "Ferment weight", + &mut data.config.ferment_weight, + 0.0..=1.0, + 0.001, + ); + ui.label(""); + _slider( + ui, + "Heuristic coefficient", + &mut data.config.heuristic_coefficient, + 0.0..=1.0, + 0.001, + ); + ui.label(""); + _slider(ui, "Q", &mut data.config.q, 0.0..=1.0, 0.001); + ui.label(""); + _slider(ui, "r", &mut data.config.r, 0.0..=1.0, 0.001); + ui.label(""); + ui.horizontal(|ui| { + if ui.button("Add vertex").clicked() { + data.vertex_update = UpdatePending::Add; + } + ui.separator(); + let run = ui.button("Run").clicked(); + }); + + ScrollArea::both() + .auto_shrink([false, false]) + .show_viewport(ui, |ui, _area| { + TableBuilder::new(ui) + .striped(true) // Alternating row colors + .resizable(true) + .vscroll(false) + .columns(Column::remainder(), data.vertices.len()) + .header(20.0, |mut header| { + for (i, _) in data.vertices.iter().enumerate() { + header.col(|ui| { + ui.horizontal(|ui| { + ui.label(i.to_string()); + if ui.button("-").clicked() { + data.vertex_update = UpdatePending::Remove(i); + } + }); + }); + } + }) + .body(|body| { + body.rows(20.0, data.vertices.len(), |mut row| { + let vi = row.index(); + let mut edges = + Vec::<(usize, NonNull)>::with_capacity(data.vertices[vi].len()); + for ei in data.vertices[vi].iter() { + let e = &mut data.edges[*ei]; + let p; + if vi == e.vertex1_index { + p = (e.vertex2_index, &mut e.length); + } else { + p = (e.vertex1_index, &mut e.length); + } + edges.push((p.0, NonNull::from_mut(p.1))); + } + edges.sort_by_key(|(k, _)| *k); + for (_, mut v) in edges { + row.col(|ui| { + ui.add( + egui::Slider::new(unsafe { v.as_mut() }, 0.0..=10.0) + .step_by(0.1), + ); + }); + } + }) + }); + }); +}