[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
|
||||
|
||||
mod algo;
|
||||
mod gui;
|
||||
|
||||
use crate::algo::BitVector;
|
||||
use bgtu_ai_utility::gui::{boot_eframe, labeled_slider};
|
||||
use bgtu_ai_utility::gui::boot_eframe;
|
||||
use eframe::egui;
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
use bgtu_ai_utility::{UpdatePending, UpdateTarget};
|
||||
|
||||
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 {
|
||||
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 {
|
||||
impl eframe::App for gui::MyApp {
|
||||
fn update(&mut self, ui: &eframe::egui::Context, _frame: &mut eframe::Frame) {
|
||||
self.columnUpdate.apply_many_and_clear(
|
||||
self.data.iter_mut(),
|
||||
self.columnUpdate.apply(
|
||||
&mut self.update_columns(),
|
||||
|| false
|
||||
);
|
||||
|
||||
@ -52,104 +26,7 @@ impl eframe::App for MyApp {
|
||||
);
|
||||
|
||||
egui::CentralPanel::default().show(ui, |ui| {
|
||||
ui.add_enabled_ui(matches!(self.result, None), |ui| {
|
||||
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], "");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
gui::input(ui, self);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user