Compare commits

...

10 Commits

5 changed files with 123 additions and 121 deletions

View File

@ -1,8 +1,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::LazyLock;
use crate::{ use crate::{
controller::view_utils::{hamming_code_input_utils::*, input_utils::*}, controller::view_utils::{hamming_code_input_utils::*, input_utils::*},
model::models::*, model::{models::*, Result},
}; };
static SYNDROMES: LazyLock<HashMap<usize, (bool, bool, bool)>> = LazyLock::new(|| { static SYNDROMES: LazyLock<HashMap<usize, (bool, bool, bool)>> = LazyLock::new(|| {
@ -17,32 +18,31 @@ static SYNDROMES: LazyLock<HashMap<usize, (bool, bool, bool)>> = LazyLock::new(|
]) ])
}); });
pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String, String> { pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String> {
let length_of_code: usize = mode.clone() as usize; let length_of_code: usize = mode.clone() as usize;
let prepared_input: String = processing_input(&raw_input); let prepared_input: String = processing_input(&raw_input);
let (fc, sc): (bool, bool) = let (first_condition, second_condition): (bool, bool) =
check_correct_binary_code(&raw_input, &prepared_input, length_of_code); check_correct_binary_code(&raw_input, &prepared_input, length_of_code);
if !fc || !sc { if raw_input.is_empty() {
Err("Ошибка. Проверьте корректность ввода.".to_string()) Err("Введите код.".into())
} else if !first_condition || !second_condition {
Err("Проверьте корректность ввода.".into())
} else { } else {
let mut data: String = String::new();
let prepared_data: Vec<u8> = from_string_to_vec_bits(prepared_input); let prepared_data: Vec<u8> = from_string_to_vec_bits(prepared_input);
match mode { match mode {
HammingMode::Encrypt => hamming_encrypt_data(&prepared_data, &mut data, length_of_code), HammingMode::Encrypt => Ok(hamming_encrypt_data(&prepared_data, length_of_code)),
HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code), HammingMode::Decrypt => Ok(hamming_decrypt_data(&prepared_data, length_of_code)),
} }
Ok(data)
} }
} }
pub fn hamming_encrypt_data(data: &Vec<u8>, result_string: &mut String, length_of_code: usize) { pub fn hamming_encrypt_data(data: &[u8], length_of_code: usize) -> String {
let mut i: usize = length_of_code; let mut i: usize = length_of_code;
let mut result = String::new();
while i <= data.len() { while i <= data.len() {
let data_bits: &[u8] = &data[i - length_of_code..i]; let data_bits: &[u8] = &data[i - length_of_code..i];
@ -51,17 +51,23 @@ pub fn hamming_encrypt_data(data: &Vec<u8>, result_string: &mut String, length_o
data_bits[0] ^ data_bits[2] ^ data_bits[3], data_bits[0] ^ data_bits[2] ^ data_bits[3],
data_bits[1] ^ data_bits[2] ^ data_bits[3], data_bits[1] ^ data_bits[2] ^ data_bits[3],
); );
result_string.push_str(&*format!(
"{check_bit_1}{}{check_bit_2}{}{check_bit_3}{}{} ", result.push_str(
data_bits[0], data_bits[1], data_bits[2], data_bits[3] format!(
)); "{check_bit_1}{}{check_bit_2}{}{check_bit_3}{}{} ",
data_bits[0], data_bits[1], data_bits[2], data_bits[3]
)
.as_str(),
);
i += length_of_code; i += length_of_code;
} }
result
} }
pub fn hamming_decrypt_data(data: &Vec<u8>, result_string: &mut String, length_of_code: usize) { pub fn hamming_decrypt_data(data: &[u8], length_of_code: usize) -> String {
let mut general_length: usize = length_of_code; let mut general_length: usize = length_of_code;
let mut result = String::new();
let mut errors: String = String::new(); let mut errors: String = String::new();
@ -78,7 +84,7 @@ pub fn hamming_decrypt_data(data: &Vec<u8>, result_string: &mut String, length_o
general_length += length_of_code; general_length += length_of_code;
continue; continue;
} else { } else {
let error_position: &usize = syndromes let error_position: &usize = SYNDROMES
.iter() .iter()
.find(move |&(&_error_position, &error)| error == checked_bits) .find(move |&(&_error_position, &error)| error == checked_bits)
.unwrap() .unwrap()
@ -114,11 +120,11 @@ pub fn hamming_decrypt_data(data: &Vec<u8>, result_string: &mut String, length_o
if !data.is_empty() { if !data.is_empty() {
if errors.is_empty() { if errors.is_empty() {
result_string.push_str("Все коды корректны."); result.push_str("Все коды корректны.");
} else { } else {
result_string.push_str(errors.as_str()); result.push_str(errors.as_str());
} }
} else {
result_string.push_str("Введите код для проверки.")
} }
result
} }

View File

@ -1,9 +1,12 @@
use gtk4 as gtk; use gtk4 as gtk;
use crate::{model::models::*, model_utils::hamming_code_seven_four::*}; use crate::{
model::{models::*, Result},
model_utils::hamming_code_seven_four::*,
};
use gtk::{prelude::*, *}; use gtk::{prelude::*, *};
pub fn start_hamming_algorithm(input: &TextView, output: &TextView, mode: bool) { pub fn start_hamming_algorithm(input: &TextView, state: bool) -> Result<String> {
let (iter_start, iter_end) = input.buffer().bounds(); let (iter_start, iter_end) = input.buffer().bounds();
let parsed_input: String = input let parsed_input: String = input
.buffer() .buffer()
@ -13,29 +16,19 @@ pub fn start_hamming_algorithm(input: &TextView, output: &TextView, mode: bool)
.parse() .parse()
.unwrap(); .unwrap();
let operation = if mode { let operation = if !state {
HammingMode::Encrypt HammingMode::Encrypt
} else { } else {
HammingMode::Decrypt HammingMode::Decrypt
}; };
match hamming(parsed_input, operation) { hamming(parsed_input, operation)
Ok(res) => output.buffer().set_text(res.trim_end()),
Err(rej) => output.buffer().set_text(rej.as_str()),
}
} }
pub fn check_correct_binary_code( pub fn check_correct_binary_code(input: &str, prepared_input: &str, l: usize) -> (bool, bool) {
input: &String, let first_condition: bool = prepared_input.len() % l == 0;
prepared_input: &String,
l: usize,
) -> (bool, bool) {
let first_condition: bool = input
.as_str()
.chars()
.all(|c| c == '1' || c == '0' || c == ' ');
let second_condition: bool = prepared_input.len() % l == 0; let second_condition: bool = input.chars().all(|c| c == '1' || c == '0' || c == ' ');
(first_condition, second_condition) (first_condition, second_condition)
} }

View File

@ -4,14 +4,11 @@ use std::{collections::VecDeque, sync::LazyLock};
use gtk::{ use gtk::{
builders::{BoxBuilder, ButtonBuilder, LabelBuilder}, builders::{BoxBuilder, ButtonBuilder, LabelBuilder},
prelude::{BoxExt, ObjectExt, WidgetExt}, prelude::{BoxExt, ButtonExt, ObjectExt, WidgetExt},
Box, Button, Label, Revealer, RevealerTransitionType, Box, Button, Label, Revealer, RevealerTransitionType,
}; };
use crate::{ use crate::model::builder_traits::Product;
event_handlers::button_event_handlers::BtnEventHandler,
model::{builder_traits::Product, models::EventHandler},
};
use tokio::{ use tokio::{
task::{spawn, JoinHandle}, task::{spawn, JoinHandle},
@ -110,10 +107,9 @@ impl InfoBarBuilder {
let info_bar_to_close = info_bar.clone(); let info_bar_to_close = info_bar.clone();
EventHandler::new(info_bar_close_btn.clone(), move |_| { info_bar_close_btn.connect_clicked(move |_| {
info_bar_to_close.set_reveal_child(false); info_bar_to_close.set_reveal_child(false);
}) });
.on_click();
&INFO_BAR_INSTANCE &INFO_BAR_INSTANCE
} }
@ -131,7 +127,7 @@ impl InfoBarBuilder {
} }
} }
impl Product<InfoBarBuilder, &'static Revealer> for InfoBar { impl Product<InfoBarBuilder, Revealer> for InfoBar {
fn builder() -> InfoBarBuilder { fn builder() -> InfoBarBuilder {
InfoBarBuilder { InfoBarBuilder {
label: Label::builder(), label: Label::builder(),
@ -140,7 +136,7 @@ impl Product<InfoBarBuilder, &'static Revealer> for InfoBar {
} }
} }
fn get(self) -> &'static Revealer { fn get(&self) -> &'static Revealer {
&INFO_BAR_INSTANCE.instance &INFO_BAR_INSTANCE.instance
} }
} }

View File

@ -5,10 +5,12 @@ use gtk::{prelude::*, *};
pub type InputLabel = String; pub type InputLabel = String;
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Input { pub struct Input {
component: Box, component: Box,
input: TextView, input: TextView,
input_label: Label,
input_frame: Frame,
} }
pub struct InputBuilder { pub struct InputBuilder {
@ -29,31 +31,39 @@ impl Product<InputBuilder, Box> for Input {
} }
} }
fn get(self) -> Box { fn get(&self) -> &Box {
self.component &self.component
} }
} }
impl Input { impl Input {
pub fn get_input(self) -> TextView { pub fn get_input(&self) -> &TextView {
self.input &self.input
}
pub fn get_frame(&self) -> &Frame {
&self.input_frame
}
pub fn get_label(&self) -> &Label {
&self.input_label
} }
} }
impl InputBuilder { impl InputBuilder {
pub fn set_label(mut self, label: &str) -> Self { pub fn label(mut self, label: &str) -> Self {
self.label = String::from(label); self.label = label.into();
self self
} }
pub fn set_align(mut self, align: Alignment) -> Self { pub fn align(mut self, align: Alignment) -> Self {
self.align = align; self.align = align;
self self
} }
pub fn set_margins(mut self, margin: MarginData) -> Self { pub fn margins(mut self, margin: MarginData) -> Self {
self.margins = margin; self.margins = margin;
self self
@ -62,7 +72,7 @@ impl InputBuilder {
pub fn build(self, monospace: bool, wrap_mode: WrapMode, input_height: i32) -> Input { pub fn build(self, monospace: bool, wrap_mode: WrapMode, input_height: i32) -> Input {
let input_component = Box::new(Orientation::Vertical, 0); let input_component = Box::new(Orientation::Vertical, 0);
let input_label = Label::builder() let text_view_label = Label::builder()
.halign(self.align.horizontal) .halign(self.align.horizontal)
.valign(self.align.vertical) .valign(self.align.vertical)
.set_margin(self.margins) .set_margin(self.margins)
@ -81,12 +91,14 @@ impl InputBuilder {
.set_margin(MarginData::MultipleMargin((0, 5, 0, 5))) .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
.build(); .build();
input_component.append(&input_label); input_component.append(&text_view_label);
input_component.append(&text_view_input_frame); input_component.append(&text_view_input_frame);
Input { Input {
component: input_component, component: input_component,
input: text_view_input, input: text_view_input.clone(),
input_frame: text_view_input_frame.clone(),
input_label: text_view_label.clone(),
} }
} }
} }

View File

@ -1,12 +1,8 @@
use std::{cell::Cell, rc::Rc}; use std::cell::Cell;
use std::rc::Rc;
use crate::{ use crate::{
event_handlers::button_event_handlers::BtnEventHandler, model::{builder_traits::Product, models::SignalReduce, Frequency},
model::{
builder_traits::Product,
models::{EventHandler, SignalReduce},
ResultValue,
},
model_utils::signal_reducer::{ model_utils::signal_reducer::{
coef_of_signal_reduce, full_resistance_of_capacitor, reactive_resistance_of_capacitor, coef_of_signal_reduce, full_resistance_of_capacitor, reactive_resistance_of_capacitor,
voltage_from_signal_source, voltage_from_signal_source,
@ -19,7 +15,7 @@ use crate::{
}; };
use gtk::{ use gtk::{
prelude::{BoxExt, Cast, CastNone, GridExt, ListItemExt}, prelude::{BoxExt, ButtonExt, Cast, CastNone, GridExt, ListItemExt, ListModelExt},
Align, WrapMode, *, Align, WrapMode, *,
}; };
use gtk4 as gtk; use gtk4 as gtk;
@ -27,8 +23,6 @@ use gtk4 as gtk;
pub fn signal_reducing_page(wrapper: &Box) { pub fn signal_reducing_page(wrapper: &Box) {
let values = Rc::new(Cell::new(SignalReduce::default())); let values = Rc::new(Cell::new(SignalReduce::default()));
let last_query: Vec<TreeIter> = Vec::new();
let info_bar = InfoBar::get_instance(); let info_bar = InfoBar::get_instance();
let (input_height, monospace, input_wrapping): (i32, bool, WrapMode) = let (input_height, monospace, input_wrapping): (i32, bool, WrapMode) =
@ -44,22 +38,15 @@ pub fn signal_reducing_page(wrapper: &Box) {
vertical: Align::Fill, vertical: Align::Fill,
}; };
let input_labels: [&str; 6] = [ let input_labels: [&str; 6] = ["l, м:", "Rм, Ом", "Cм, пФ:", "Rи, Ом:", "Vи, мВ", "f, мГц:"];
"l, м:",
"Rм, Ом:",
"Cм, пФ:",
"Vи, мВ",
"Rи, Ом:",
"f, мГц:",
];
let all_inputs: Vec<Input> = input_labels let all_inputs: Vec<Input> = input_labels
.iter() .iter()
.map(move |label| { .map(move |label| {
Input::builder() Input::builder()
.set_label(label) .label(label)
.set_margins(MarginData::EqualsMargin(5)) .margins(MarginData::EqualsMargin(6))
.set_align(input_label_alignment) .align(input_label_alignment)
.build(monospace, input_wrapping, input_height) .build(monospace, input_wrapping, input_height)
}) })
.collect(); .collect();
@ -72,7 +59,7 @@ pub fn signal_reducing_page(wrapper: &Box) {
} }
input_block.attach( input_block.attach(
&elem.clone().get(), elem.clone().get(),
(id as i32) - (3 * row_position), (id as i32) - (3 * row_position),
row_position, row_position,
1, 1,
@ -82,16 +69,24 @@ pub fn signal_reducing_page(wrapper: &Box) {
let calculate_button = Button::builder().label("Расчитать").build(); let calculate_button = Button::builder().label("Расчитать").build();
let result_table_headers_labels: [&str; 4] = ["f, МГц", "Xc, пФ", "Vп, мВ", "ζ"]; let result_table_headers_labels: [&str; 4] = ["f, МГц", "Xc, Ом", "Vп, мВ", "ζ"];
let model = gio::ListStore::new::<ResultValue>(); let model = gio::ListStore::new::<Frequency>();
let model_for_events = model.clone();
let cloned_model = model.clone(); for number in (0..=100).step_by(5) {
if number == 0 {
model.append(&Frequency::new(1.0));
} else if (number >= 70 && number % 10 == 0) || (number < 70 && number % 5 == 0) {
model.append(&Frequency::new(number as f64));
}
}
let selection_model = SingleSelection::new(Some(model)); let selection_model = NoSelection::new(Some(model));
let result_table = ColumnView::builder() let result_table = ColumnView::builder()
.reorderable(true) .reorderable(true)
.show_row_separators(true)
.model(&selection_model) .model(&selection_model)
.build(); .build();
@ -112,7 +107,7 @@ pub fn signal_reducing_page(wrapper: &Box) {
.downcast_ref::<ListItem>() .downcast_ref::<ListItem>()
.expect("Needs to be ListItem") .expect("Needs to be ListItem")
.item() .item()
.and_downcast::<ResultValue>() .and_downcast::<Frequency>()
.expect("The item has to be an `IntegerObject`."); .expect("The item has to be an `IntegerObject`.");
let cell_label = list_item let cell_label = list_item
@ -122,38 +117,42 @@ pub fn signal_reducing_page(wrapper: &Box) {
.and_downcast::<Label>() .and_downcast::<Label>()
.expect("The child has to be a `Label`."); .expect("The child has to be a `Label`.");
let result_values = values_for_factory.clone().get(); let result_values = values_for_factory.get();
let reactive_resist: f64 = reactive_resistance_of_capacitor( let reactive_resist: f64 = reactive_resistance_of_capacitor(
result_values.2, result_values.wire_capacity * 10f64.powi(-12),
result_values.0, result_values.length,
cell_value.value(), cell_value.frequency() * 10f64.powi(6),
); );
let full_resistance: f64 = full_resistance_of_capacitor( let full_resistance: f64 = full_resistance_of_capacitor(
reactive_resist, reactive_resist,
result_values.4, result_values.source_resistance,
result_values.1, result_values.wire_resistance,
result_values.0, result_values.length,
); );
let signal_source_voltage: f64 = let signal_source_voltage: f64 = voltage_from_signal_source(
voltage_from_signal_source(result_values.3, reactive_resist, full_resistance); result_values.source_voltage * 10f64.powi(-3),
reactive_resist,
let coef: f64 = coef_of_signal_reduce(signal_source_voltage, signal_source_voltage); full_resistance,
) * 1000.0;
match label { match label {
"f, МГц" => { "f, МГц" => {
cell_label.set_label(&cell_value.value().to_string()); cell_label.set_label(&cell_value.frequency().to_string());
} }
"Xc, пФ" => { "Xc, Ом" => {
cell_label.set_label(&reactive_resist.to_string()); cell_label.set_label(format!("{0:.1$}", reactive_resist, 6).as_str());
} }
"Vп, мВ" => { "Vп, мВ" => {
cell_label.set_label(&signal_source_voltage.to_string()); cell_label.set_label(format!("{0:.1$}", signal_source_voltage, 6).as_str());
} }
"ζ" => { "ζ" => {
cell_label.set_label(&coef.to_string()); let coef: f64 =
coef_of_signal_reduce(result_values.source_voltage, signal_source_voltage);
cell_label.set_label(format!("{0:.1$}", coef, 6).as_str());
} }
_ => {} _ => {}
} }
@ -179,24 +178,20 @@ pub fn signal_reducing_page(wrapper: &Box) {
.vexpand(true) .vexpand(true)
.build(); .build();
EventHandler::new(calculate_button.clone(), move |_| { calculate_button.connect_clicked(move |_| match parse_fields(all_inputs.clone()) {
match parse_fields(all_inputs.clone()) { Ok(results) => {
Ok(results) => { values.set(results);
values.set(results);
let tree_iter: TreeIter = cloned_model.append(&ResultValue::new(results.5)); model_for_events.items_changed(0, 0, 18);
model_for_events.items_changed(18, 18, 0);
last_query.append(tree_iter);
}
Err(error) => {
let error_kind: Option<&str> = get_error_message(error);
info_bar.set_text_label(error_kind);
info_bar.show_infobar(5u64);
}
} }
}) Err(error) => {
.on_click(); let error_kind: Option<&str> = get_error_message(error);
info_bar.set_text_label(error_kind);
info_bar.show_infobar(5u64);
}
});
wrapper.append(&input_block); wrapper.append(&input_block);
wrapper.append(&calculate_button); wrapper.append(&calculate_button);