[lab2] Gui decomposition
This commit is contained in:
parent
60450ee342
commit
837dfe9ba0
54
lab2/src/gui/data.rs
Normal file
54
lab2/src/gui/data.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use crate::algo::BitVector;
|
||||||
|
use bgtu_ai_utility::{UpdatePending, UpdateTarget};
|
||||||
|
|
||||||
|
pub(crate) struct MyApp {
|
||||||
|
pub _isFirstFrame: bool,
|
||||||
|
pub bitCount: usize,
|
||||||
|
pub beta: usize,
|
||||||
|
pub attentiveness: f64,
|
||||||
|
pub data: Vec<BitVector>,
|
||||||
|
pub result: Option<Box<[usize]>>,
|
||||||
|
pub columnUpdate: UpdatePending,
|
||||||
|
pub rowUpdate: UpdatePending,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyApp {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
return Self {
|
||||||
|
_isFirstFrame: true,
|
||||||
|
bitCount: 0,
|
||||||
|
beta: 1,
|
||||||
|
attentiveness: 0.5,
|
||||||
|
data: Vec::new(),
|
||||||
|
result: None,
|
||||||
|
columnUpdate: UpdatePending::NoChange,
|
||||||
|
rowUpdate: UpdatePending::NoChange,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_columns<'s>(&'s mut self) -> ColumnsUpdateTarget<'s> {
|
||||||
|
return ColumnsUpdateTarget { data: self };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ColumnsUpdateTarget<'d> {
|
||||||
|
data: &'d mut MyApp,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UpdateTarget for ColumnsUpdateTarget<'_> {
|
||||||
|
type Elem = bool;
|
||||||
|
|
||||||
|
fn add(&mut self, value: Self::Elem) {
|
||||||
|
for bv in self.data.data.iter_mut() {
|
||||||
|
UpdateTarget::add(bv, value)
|
||||||
|
}
|
||||||
|
self.data.bitCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, index: usize) {
|
||||||
|
for bv in self.data.data.iter_mut() {
|
||||||
|
UpdateTarget::remove(bv, index)
|
||||||
|
}
|
||||||
|
self.data.bitCount -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
111
lab2/src/gui/input.rs
Normal file
111
lab2/src/gui/input.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use super::MyApp;
|
||||||
|
use crate::algo;
|
||||||
|
use bgtu_ai_utility::UpdatePending;
|
||||||
|
use bgtu_ai_utility::gui::labeled_slider;
|
||||||
|
use eframe::egui::Ui;
|
||||||
|
use egui_extras::{Column, TableBuilder};
|
||||||
|
|
||||||
|
pub(crate) fn input(ui: &mut Ui, data: &mut MyApp) {
|
||||||
|
ui.add_enabled_ui(matches!(data.result, None), |ui| {
|
||||||
|
labeled_slider(ui, "beta", &mut data.beta, 1..=10, 1f64);
|
||||||
|
ui.label("");
|
||||||
|
labeled_slider(
|
||||||
|
ui,
|
||||||
|
"attentiveness",
|
||||||
|
&mut data.attentiveness,
|
||||||
|
0f64..=1f64,
|
||||||
|
0.001,
|
||||||
|
);
|
||||||
|
ui.label("");
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add_enabled_ui(matches!(data.result, None), |ui| {
|
||||||
|
if ui.button("Add row").clicked() {
|
||||||
|
data.rowUpdate = UpdatePending::Add;
|
||||||
|
}
|
||||||
|
if ui.button("Add column").clicked() {
|
||||||
|
data.columnUpdate = UpdatePending::Add;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
|
ui.add_enabled_ui(matches!(data.result, None), |ui| {
|
||||||
|
if ui.button("Classify").clicked() {
|
||||||
|
data.result = Some(algo::adaptiveResonanceTheoryImpl(
|
||||||
|
data.data.as_slice(),
|
||||||
|
data.beta,
|
||||||
|
data.attentiveness,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.add_enabled_ui(!matches!(data.result, None), |ui| {
|
||||||
|
if ui.button("Edit").clicked() {
|
||||||
|
data.result = None;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.label("");
|
||||||
|
|
||||||
|
table(ui, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn table(ui: &mut Ui, data: &mut MyApp) {
|
||||||
|
TableBuilder::new(ui)
|
||||||
|
.striped(true) // Alternating row colors
|
||||||
|
.resizable(true)
|
||||||
|
.column(Column::remainder())
|
||||||
|
.column(Column::remainder())
|
||||||
|
.columns(Column::remainder(), data.bitCount)
|
||||||
|
.header(20.0, |mut header| {
|
||||||
|
header.col(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("#");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
header.col(|ui| {
|
||||||
|
ui.label("Group");
|
||||||
|
});
|
||||||
|
for i in 0..data.bitCount {
|
||||||
|
header.col(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(i.to_string());
|
||||||
|
ui.add_enabled_ui(matches!(data.result, None), |ui| {
|
||||||
|
if ui.button("-").clicked() {
|
||||||
|
data.columnUpdate = UpdatePending::Remove(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.body(|body| {
|
||||||
|
body.rows(20.0, data.data.len(), |mut row| {
|
||||||
|
let i = row.index();
|
||||||
|
row.col(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("-").clicked() {
|
||||||
|
data.rowUpdate = UpdatePending::Remove(i);
|
||||||
|
}
|
||||||
|
ui.label(i.to_string());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
row.col(|ui| {
|
||||||
|
if let Some(result) = &data.result {
|
||||||
|
ui.label(result[i].to_string());
|
||||||
|
} else {
|
||||||
|
ui.label("?");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for j in 0..data.bitCount {
|
||||||
|
row.col(|ui| {
|
||||||
|
ui.add_enabled_ui(matches!(data.result, None), |ui| {
|
||||||
|
ui.checkbox(&mut data.data[i][j], "");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
5
lab2/src/gui/mod.rs
Normal file
5
lab2/src/gui/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod data;
|
||||||
|
mod input;
|
||||||
|
|
||||||
|
pub(crate) use data::MyApp;
|
||||||
|
pub(crate) use input::input;
|
||||||
137
lab2/src/main.rs
137
lab2/src/main.rs
@ -1,48 +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::BitVector;
|
use crate::algo::BitVector;
|
||||||
use bgtu_ai_utility::gui::{boot_eframe, labeled_slider};
|
use bgtu_ai_utility::gui::boot_eframe;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui_extras::{Column, TableBuilder};
|
|
||||||
use bgtu_ai_utility::{UpdatePending, UpdateTarget};
|
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
return boot_eframe(|| MyApp::new());
|
return boot_eframe(|| gui::MyApp::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct MyApp {
|
|
||||||
_isFirstFrame: bool,
|
|
||||||
bitCount: usize,
|
|
||||||
beta: usize,
|
|
||||||
attentiveness: f64,
|
|
||||||
data: Vec<BitVector>,
|
|
||||||
result: Option<Box<[usize]>>,
|
|
||||||
columnUpdate: UpdatePending,
|
|
||||||
rowUpdate: UpdatePending,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MyApp {
|
impl eframe::App for gui::MyApp {
|
||||||
fn new() -> Self {
|
|
||||||
return Self {
|
|
||||||
_isFirstFrame: true,
|
|
||||||
bitCount: 0,
|
|
||||||
beta: 1,
|
|
||||||
attentiveness: 0.5,
|
|
||||||
data: Vec::new(),
|
|
||||||
result: None,
|
|
||||||
columnUpdate: UpdatePending::NoChange,
|
|
||||||
rowUpdate: UpdatePending::NoChange,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
||||||
self.columnUpdate.apply_many_and_clear(
|
self.columnUpdate.apply(
|
||||||
self.data.iter_mut(),
|
&mut self.update_columns(),
|
||||||
|| false
|
|| false
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -52,104 +26,7 @@ impl eframe::App for MyApp {
|
|||||||
);
|
);
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ui, |ui| {
|
egui::CentralPanel::default().show(ui, |ui| {
|
||||||
ui.add_enabled_ui(matches!(self.result, None), |ui| {
|
gui::input(ui, self);
|
||||||
labeled_slider(ui, "beta", &mut self.beta, 1..=10, 1f64);
|
|
||||||
ui.label("");
|
|
||||||
labeled_slider(
|
|
||||||
ui,
|
|
||||||
"attentiveness",
|
|
||||||
&mut self.attentiveness,
|
|
||||||
0f64..=1f64,
|
|
||||||
0.001,
|
|
||||||
);
|
|
||||||
ui.label("");
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.add_enabled_ui(matches!(self.result, None), |ui| {
|
|
||||||
if ui.button("Add row").clicked() {
|
|
||||||
self.rowUpdate = UpdatePending::Add;
|
|
||||||
}
|
|
||||||
if ui.button("Add column").clicked() {
|
|
||||||
self.columnUpdate = UpdatePending::Add;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
ui.add_enabled_ui(matches!(self.result, None), |ui| {
|
|
||||||
if ui.button("Classify").clicked() {
|
|
||||||
self.result = Some(algo::adaptiveResonanceTheoryImpl(
|
|
||||||
self.data.as_slice(),
|
|
||||||
self.beta,
|
|
||||||
self.attentiveness,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.add_enabled_ui(!matches!(self.result, None), |ui| {
|
|
||||||
if ui.button("Edit").clicked() {
|
|
||||||
self.result = None;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.label("");
|
|
||||||
|
|
||||||
TableBuilder::new(ui)
|
|
||||||
.striped(true) // Alternating row colors
|
|
||||||
.resizable(true)
|
|
||||||
.column(Column::remainder())
|
|
||||||
.column(Column::remainder())
|
|
||||||
.columns(Column::remainder(), self.bitCount)
|
|
||||||
.header(20.0, |mut header| {
|
|
||||||
header.col(|ui| {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label("#");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
header.col(|ui| {
|
|
||||||
ui.label("Group");
|
|
||||||
});
|
|
||||||
for i in 0..self.bitCount {
|
|
||||||
header.col(|ui| {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label(i.to_string());
|
|
||||||
ui.add_enabled_ui(matches!(self.result, None), |ui| {
|
|
||||||
if ui.button("-").clicked() {
|
|
||||||
self.columnUpdate = UpdatePending::Remove(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.body(|body| {
|
|
||||||
body.rows(20.0, self.data.len(), |mut row| {
|
|
||||||
let i = row.index();
|
|
||||||
row.col(|ui| {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
if ui.button("-").clicked() {
|
|
||||||
self.rowUpdate = UpdatePending::Remove(i);
|
|
||||||
}
|
|
||||||
ui.label(i.to_string());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
row.col(|ui| {
|
|
||||||
if let Some(result) = &self.result {
|
|
||||||
ui.label(result[i].to_string());
|
|
||||||
} else {
|
|
||||||
ui.label("?");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for j in 0..self.bitCount {
|
|
||||||
row.col(|ui| {
|
|
||||||
ui.add_enabled_ui(matches!(self.result, None), |ui| {
|
|
||||||
ui.checkbox(&mut self.data[i][j], "");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user