GUI for inputing config

This commit is contained in:
Andrew Golovashevich 2026-01-22 05:42:19 +03:00
parent 87cb8c3cf1
commit 0f2ec21bf7
3 changed files with 150 additions and 4 deletions

View File

@ -2,4 +2,6 @@ mod board;
mod misc;
mod simulation;
pub(crate) use board::Board;
pub(crate) use board::Board;
pub(crate) use simulation::AnnealingConfig;
pub(crate) use simulation::simulateAnnealing;

View File

@ -2,7 +2,7 @@ use crate::algo::misc::{initializeBoard, isOnDiagonal, swapRandomQueensOnce};
use crate::algo::Board;
use eframe::emath::Numeric;
pub(super) fn calculateEnergy(b: &Board) -> f64 {
fn calculateEnergy(b: &Board) -> f64 {
let mut conflictsCount = 0usize;
for i1 in 0..b.len() {
for i2 in (i1 + 1)..b.len() {

View File

@ -3,6 +3,150 @@
mod algo;
fn main() {
use eframe::egui;
use eframe::egui::Ui;
use eframe::emath::Numeric;
use rand::SeedableRng;
use std::ops::RangeInclusive;
use std::time::{SystemTime, UNIX_EPOCH};
}
fn main() -> eframe::Result {
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([640.0, 400.0]),
..Default::default()
};
eframe::run_native(
"Annealing Simulation for Chess Queens Task",
options,
Box::new(|cc| {
// This gives us image support:
// egui_extras::install_image_loaders(&cc.egui_ctx);
Ok(Box::<MyApp>::default())
}),
)
}
struct MyApp {
simulationConfig: algo::AnnealingConfig,
boardSize: usize,
_isFirstFrame: bool,
result: Option<algo::Board>,
}
impl Default for MyApp {
fn default() -> Self {
Self {
simulationConfig: algo::AnnealingConfig {
initialTemperature: 30.0,
targetTemperature: 0.5,
cooldownCoefficient: 0.99,
iterationsPerAge: 100,
},
boardSize: 20,
_isFirstFrame: true,
result: None,
}
}
}
fn _slider<T: Numeric>(
ui: &mut Ui,
name: &str,
storage: &mut T,
range: RangeInclusive<T>,
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| {
ui.add_enabled_ui(matches!(self.result, None), |ui| {
_slider(ui, "Board size:", &mut self.boardSize, 2..=50, 1.0);
ui.label("");
_slider(
ui,
"Initial temperature:",
&mut self.simulationConfig.initialTemperature,
self.simulationConfig.targetTemperature + 0.01..=100.0,
0.01,
);
ui.label("");
_slider(
ui,
"Target Temperature:",
&mut self.simulationConfig.targetTemperature,
0.0..=99.98,
0.01,
);
ui.label("");
_slider(
ui,
"Cooldown coefficient:",
&mut self.simulationConfig.cooldownCoefficient,
0.001..=0.999,
0.001,
);
ui.label("");
_slider(
ui,
"Iterations per age:",
&mut self.simulationConfig.iterationsPerAge,
1..=1000,
1.0,
);
ui.label("");
if ui.button("Calculate").clicked() {
self.result = Some(algo::simulateAnnealing(
self.boardSize,
&self.simulationConfig,
&mut rand::rngs::SmallRng::seed_from_u64(
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
),
))
}
});
match &self.result {
None => {}
Some(result) => ui.ctx().show_viewport_immediate(
egui::ViewportId::from_hash_of("immediate_viewport"),
egui::ViewportBuilder::default()
.with_title("Immediate Viewport")
.with_inner_size([200.0, 100.0]),
|ui, class| {
if class == egui::ViewportClass::Embedded {
/*ui.label(
"This viewport is embedded in the parent window, and cannot be moved outside of it.",
);*/
} else {
egui::CentralPanel::default().show(ui, |ui| {
ui.label("Hello from immediate viewport");
if ui.input(|i| i.viewport().close_requested()) {
self.result = None
}
});
}
},
),
}
});
}
}