P3UIUIKP5EB53CPLHJMN6XGJWKUAPZYMOXF5DB6SBRYFPFUFVVAAC use eframe::egui;use eframe::egui::mutex::RwLock;use eframe::egui::vec2;use eframe::egui::Button;use eframe::egui::Color32;use eframe::egui::Label;use eframe::egui::Link;use eframe::egui::RichText;use eframe::egui::ScrollArea;use eframe::egui::Stroke;use eframe::egui::TextEdit;// use eframe::Frame;use egui_flex::item;use egui_flex::Flex;use serde::Deserialize;use serde::Serialize;use std::collections::BTreeMap;use std::fs::File;use std::io::Read;use std::io::Write;use std::iter::zip;use std::sync::Arc;use std::sync::OnceLock;use super::activities::activities;use super::activities::activity_form::act_teachers;use super::activities::activity_form::filtered_teachers;// use super::activities::activity_form::filtered_teachers;use super::activities::activity_form::teachers_ui::set_teachers_filter;use super::activities::save_activities;use super::activities::Activity;use super::limitations::limitations_ui::create_teachers_sched;use super::limitations::limitations_ui::save_teachers_limitations;use super::limitations::limitations_ui::teachers_limitations;use super::limitations::limitations_ui::teachers_scheds;use super::limitations::limitations_ui::TeacherLimitation;#[derive(Clone, Serialize, Deserialize)]pub struct Teacher {pub id: i32,pub name: String,pub short_name: String,}pub fn selected_teacher() -> &'static Arc<RwLock<Option<i32>>> {static SELECTED: OnceLock<Arc<RwLock<Option<i32>>>> = OnceLock::new();SELECTED.get_or_init(|| Arc::new(RwLock::new(None)))}pub fn get_teachers() -> &'static Arc<RwLock<BTreeMap<i32, Teacher>>> {static TEACHERS: OnceLock<Arc<RwLock<BTreeMap<i32, Teacher>>>> = OnceLock::new();TEACHERS.get_or_init(|| Arc::new(RwLock::new(read_teachers())))}pub fn del_teachers_state() -> &'static Arc<RwLock<Vec<bool>>> {static TEACHERS: OnceLock<Arc<RwLock<Vec<bool>>>> = OnceLock::new();TEACHERS.get_or_init(|| Arc::new(RwLock::new(vec![false; filtered_teachers().read().len()])))}pub fn teachers_acts() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Activity>>>> {static CLASSES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Activity>>>>> = OnceLock::new();CLASSES.get_or_init(|| Arc::new(RwLock::new(create_teacher_acts())))}pub fn create_teacher_acts() -> BTreeMap<i32, Vec<Activity>> {let acts = &*activities().read();let mut map = BTreeMap::new();for t in &*get_teachers().read() {let mut c_acts = acts// .clone().values().filter(|a| {a.teachers.iter().any(|ac| ac == &t.1.id)|| a.teachers.is_empty()|| a.classes.is_empty()}).map(|a| a.clone()).collect::<Vec<Activity>>();c_acts.sort_by(|a, b| a.lecture.cmp(&b.lecture));map.insert(t.1.id, c_acts);}map}pub fn teacher_name() -> &'static Arc<RwLock<String>> {static NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}fn teacher_short_name() -> &'static Arc<RwLock<String>> {static SHORT_NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}fn update_teacher_form() -> &'static Arc<RwLock<bool>> {static SHORT_NAME: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new(false)))}fn update_teacher(ui: &mut eframe::egui::Ui) {egui::Window::new("Select Teacher").open(&mut *update_teacher_form().write()).resizable([true, true]).show(ui.ctx(), |ui| {ui.add(TextEdit::singleline(&mut *teacher_name().write()));ui.add(TextEdit::singleline(&mut *teacher_short_name().write()));if ui.add(Button::new("Güncelle")).clicked() {if let Some(t) = get_teachers().write().get_mut(&selected_teacher().read().unwrap()){t.name = teacher_name().read().clone();t.short_name = teacher_short_name().read().clone();save_teachers();}}});}pub fn teachers_page(ui: &mut eframe::egui::Ui) {// let mut name = get_name().lock().unwrap();ui.vertical_centered(|ui| {if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *teacher_name().write()).hint_text("Öğretmenin Adı ve Soyadı"),).changed(){set_teachers_filter();};if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *teacher_short_name().write()).hint_text("Kısa Ad"),).changed(){};if ui.add_sized(vec2(250., 30.), Button::new("Öğretmeni Ekle")).clicked(){add_teacher();save_teachers();}});ui.separator();teachers_ui(ui);}pub fn teachers_list_ui(ui: &mut egui::Ui) {ScrollArea::vertical().show(ui, |ui| {ui.add_space(30.);ui.separator();ui.vertical_centered(|ui| {if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *teacher_name().write()).hint_text("Filtrele"),).changed(){set_teachers_filter();};let mut teachers = filtered_teachers().write();for c in &mut *teachers {let fill_color = if selected_teacher().read().is_some_and(|i| i == c.id) {Color32::BLUE} else {Color32::default()};let stroke_color = if selected_teacher().read().is_some_and(|i| i == c.id) {Color32::LIGHT_BLUE} else {Color32::LIGHT_GRAY};let button = egui::Frame::none().fill(fill_color).inner_margin(10.).outer_margin(2.).rounding(5.0).stroke(Stroke::new(1., stroke_color)).show(ui, |ui| {ui.label(&c.name);}).response;let button = button.interact(egui::Sense::click()).on_hover_cursor(egui::CursorIcon::PointingHand);if button.clicked() {set_selected_teacher(c.clone());}}});});}pub fn teachers_ui(ui: &mut eframe::egui::Ui) {update_teacher(ui);Flex::horizontal().gap(vec2(20., 20.)).wrap(true).show(ui, |flex| {let del_states = del_teachers_state().read().clone();let del_states = del_states.iter().enumerate();for (del_state, teacher) in zip(del_states, filtered_teachers().read().iter()) {let frame = egui::Frame::default().stroke(Stroke::new(0.3, Color32::GRAY)).rounding(5.).inner_margin(5.);flex.add_flex(item().grow(1.).frame(frame), Flex::vertical(), |flex| {flex.add(item(), Label::new(&teacher.name));if *del_state.1 {flex.add_flex(item().grow(1.),Flex::horizontal().align_items(egui_flex::FlexAlign::Center).wrap(false),|flex| {if flex.add(item(),Link::new(RichText::new("Sil").color(Color32::RED)),)// .inner.clicked(){del_teacher(teacher.id, del_state.0);// del_teacher(teacher.id);};if flex.add(item().grow(1.), Link::new("Vazgeç"))// .inner.clicked(){std::thread::spawn(move || {if let Some(state) =del_teachers_state().write().get_mut(del_state.0){*state = false;}});};},);} else {flex.ui().layout().horizontal_justify();flex.add_flex(item().grow(0.0),Flex::horizontal().align_items(egui_flex::FlexAlign::Center).wrap(false),|flex| {if flex.add(item(),Link::new(RichText::new("Sil").color(Color32::RED)),)// .inner.clicked(){std::thread::spawn(move || {if let Some(state) =del_teachers_state().write().get_mut(del_state.0){*state = true;}});};if flex.add(item().grow(1.), Link::new("Düzenle"))// .inner.clicked(){let t = teacher.clone();set_selected_teacher(t.clone());std::thread::spawn(move || {*teacher_name().write() = t.name.clone();*teacher_short_name().write() = t.short_name.clone();*update_teacher_form().write() = true;});};},);}});}});}fn save_teachers() {std::thread::spawn(move || {let teachers = get_teachers().read();let js = serde_json::to_string(&*teachers);match js {Ok(j) => {let mut f = File::create("./db/teachers.json").unwrap();f.write_all(j.as_bytes()).unwrap();}Err(_) => {}}});}fn add_teacher() {let id = find_new_id();let teacher = Teacher {id,name: teacher_name().read().clone(),short_name: teacher_short_name().read().clone(),};get_teachers().write().insert(id, teacher);*teacher_name().write() = "".to_string();*teacher_short_name().write() = "".to_string();set_teachers_filter();let t_lims = TeacherLimitation::new(id);teachers_limitations().write().insert(id, t_lims);save_teachers();save_teachers_limitations();del_teachers_state().write().push(false);}fn read_teachers() -> BTreeMap<i32, Teacher> {let f = File::open("./db/teachers.json");if let Ok(mut f) = f {let mut content: String = String::new();f.read_to_string(&mut content).unwrap();let cls: BTreeMap<i32, Teacher> = serde_json::from_str(content.as_str()).unwrap();return cls;}BTreeMap::new()}fn del_teacher(id: i32, state: usize) {// let cls = Arc::clone(&teachers);std::thread::spawn(move || {get_teachers().write().remove(&id);save_teachers();del_teacher_acts(id);teachers_limitations().write().remove(&id);save_teachers_limitations();*teachers_scheds().write() = create_teachers_sched();teachers_acts().write().remove(&id);set_teachers_filter();del_teachers_state().write().remove(state);}).join().unwrap();}fn del_teacher_acts(id: i32) {// let acts = &mut *activities().write();if let Some(c_acts) = teachers_acts().read().get(&id) {for a in c_acts {if a.teachers.iter().any(|t| t == &id) {activities().write().remove(&a.id);}}}teachers_acts().write().remove(&id);save_activities();}fn find_new_id() -> i32 {let len = get_teachers().read().len() as i32;for i in 1..len + 1 {if !get_teachers().read().contains_key(&i) {return i;}}len + 1}pub fn set_selected_teacher(t: Teacher) {let teacher = Arc::clone(selected_teacher());std::thread::spawn(move || {*teacher.write() = Some(t.id);});// let lims = teachers_limitations().read();// let lims = lims.get(&t.id);// match lims {// Some(lims) => {// *teacher_limitation().write() = lims.clone();// }// None => {// *teacher_limitation().write() = TeacherLimitation::new(t.id);// }// }*act_teachers().write() = vec![t.clone()];}
// pub mod all_classes;// pub mod all_teachers;pub mod classes;pub mod teachers;
use std::iter::zip;use genpdf::*;use crate::{tabs::{get_school, limitations::limitations_ui::teachers_scheds, school_name,teachers::get_teachers,},DAYS,};pub fn teachers_prints() {let fon_family = crate::fonts::font_family();// let font_family = genpdf::fonts::from_files("./fonts", "LiberationSans", None)// .expect("Failed to load font family");let mut doc = genpdf::Document::new(fon_family);// Change the default settingsdoc.set_title(format!("{}", &*school_name().read()));// Customize the pageslet mut decorator = genpdf::SimplePageDecorator::new();decorator.set_margins(10);doc.set_page_decorator(decorator);// let mut buf: Vec<u8> = Vec::new();print_teachers(&mut doc);// doc.render(&mut buf).expect("Render edilemedi");doc.render_to_file("ogretmenler.pdf").expect("Failed to write PDF file");opener::open(std::path::Path::new("ogretmenler.pdf"));// let png_jsarray: zoon::JsValue = js_sys::Uint8Array::from(&buf[..]).into();// // the buffer has to be an array of arrays// let png_buffer: js_sys::Array = std::iter::IntoIterator::into_iter([png_jsarray]).collect();// let mut properties = web_sys::BlobPropertyBag::new();// properties.type_("application/pdf");// let png_blob =// web_sys::Blob::new_with_buffer_source_sequence_and_options(&png_buffer, &properties)// .unwrap();// let url = web_sys::Url::create_object_url_with_blob(&png_blob).unwrap();// let window = web_sys::window().unwrap();// window.open_with_url(&url).expect("Pdf açılamadı");}fn print_teachers(doc: &mut genpdf::Document) {let school_name = &*school_name().read();doc.set_minimal_conformance();doc.set_line_spacing(1.25);let mut decorator = genpdf::SimplePageDecorator::new();decorator.set_margins(10 as i32);doc.set_page_decorator(decorator);doc.set_line_spacing(1.25);let teachers = &*get_teachers().read();for teacher in teachers {let mut title = elements::LinearLayout::vertical();let mut title_style = style::Style::new();title_style.set_bold();title_style.set_font_size(20);let title_paragraph = elements::Paragraph::default();title.push(title_paragraph.styled_string(school_name, title_style).aligned(Alignment::Center),);let t_name = format!("{}", teacher.1.name);let mut teacher_style = style::Style::new();teacher_style.set_italic();teacher_style.set_font_size(18);title.push(elements::Paragraph::new(&t_name).aligned(Alignment::Center));doc.push(title);//doc.push(elements::Break::new(1));add_row(doc, teacher.1.id);doc.push(elements::PageBreak::new());}}fn add_row(doc: &mut genpdf::Document, c: i32) {let len = get_school().read().hour as usize;let mut table = elements::TableLayout::new(vec![8; len + 1]);table.set_cell_decorator(elements::FrameCellDecorator::new(true, true, false));let mut row = table.row();row.push_element(create_row_title(format!("{} ve {}", "Günler", "Saatler")).aligned(Alignment::Center),);for hour in vec![1; len].iter().enumerate() {row.push_element(create_row_title(format!("{}. saat", hour.0 + 1)).aligned(Alignment::Center),);}row.push().expect("Invalid table row");let sched = teachers_scheds().read();let scheds = sched.get(&c).unwrap();for (day, sched) in zip(DAYS, scheds) {let mut row = table.row();let mut day_row = elements::LinearLayout::vertical();day_row.push(create_row_title(day.to_string()).aligned(Alignment::Center));let mut line_style = style::Style::new();line_style.bold();line_style.set_font_size(8);// let par = elements::Paragraph::default()// .styled_string("00:00-00:00", line_style)// .aligned(Alignment::Center);// day_row.push(par);row.push_element(day_row);// println!("{:?}", sched);for s in sched {if let Some(s) = s {row.push_element(create_row_title(format!("{:?}", s)))} else {row.push_element(create_row_title("".to_string()))}}row.push().unwrap();}doc.push(table);}fn create_row_title(title: String) -> elements::Paragraph {let paragraph = elements::Paragraph::default();let mut title_style = style::Style::new();title_style.bold();title_style.set_font_size(10);paragraph.styled_string(title, title_style)}
use std::iter::zip;use genpdf::*;use crate::{tabs::{classes::get_classes, get_school, limitations::limitations_ui::classes_sched, school_name,},DAYS,};pub fn classes_prints() {let fon_family = crate::fonts::font_family();let mut doc = genpdf::Document::new(fon_family);// Change the default settingsdoc.set_title(format!("{}", &*school_name().read()));// Customize the pageslet mut decorator = genpdf::SimplePageDecorator::new();decorator.set_margins(10);doc.set_page_decorator(decorator);// let mut buf: Vec<u8> = Vec::new();print_classes(&mut doc);// doc.render(&mut buf).expect("Render edilemedi");doc.render_to_file("output.pdf").expect("Failed to write PDF file");// let png_jsarray: zoon::JsValue = js_sys::Uint8Array::from(&buf[..]).into();// // the buffer has to be an array of arrays// let png_buffer: js_sys::Array = std::iter::IntoIterator::into_iter([png_jsarray]).collect();// let mut properties = web_sys::BlobPropertyBag::new();// properties.type_("application/pdf");// let png_blob =// web_sys::Blob::new_with_buffer_source_sequence_and_options(&png_buffer, &properties)// .unwrap();// let url = web_sys::Url::create_object_url_with_blob(&png_blob).unwrap();// let window = web_sys::window().unwrap();// window.open_with_url(&url).expect("Pdf açılamadı");}fn print_classes(doc: &mut genpdf::Document) {let school_name = &*school_name().read();doc.set_minimal_conformance();doc.set_line_spacing(1.25);let mut decorator = genpdf::SimplePageDecorator::new();decorator.set_margins(10 as i32);doc.set_page_decorator(decorator);doc.set_line_spacing(1.25);let clss = &*get_classes().read();for class in clss {let mut title = elements::LinearLayout::vertical();let mut title_style = style::Style::new();title_style.set_bold();title_style.set_font_size(20);let title_paragraph = elements::Paragraph::default();title.push(title_paragraph.styled_string(school_name, title_style).aligned(Alignment::Center),);let cls_name = format!("{}", class.1.name);let mut teacher_style = style::Style::new();teacher_style.set_italic();teacher_style.set_font_size(18);title.push(elements::Paragraph::new(&cls_name).aligned(Alignment::Center));doc.push(title);//doc.push(elements::Break::new(1));add_row(doc, class.1.id);doc.push(elements::PageBreak::new());}}fn add_row(doc: &mut genpdf::Document, c: i32) {let len = get_school().read().hour as usize;let mut table = elements::TableLayout::new(vec![8; len + 1]);table.set_cell_decorator(elements::FrameCellDecorator::new(true, true, false));let mut row = table.row();row.push_element(create_row_title(format!("{} ve {}", "Günler", "Saatler")).aligned(Alignment::Center),);for hour in vec![0; len].iter().enumerate() {row.push_element(create_row_title(format!("{}. saat", hour.0)).aligned(Alignment::Center));}row.push().expect("Invalid table row");let sched = classes_sched().read();let scheds = sched.get(&c).unwrap();for (day, sched) in zip(DAYS, scheds) {let mut row = table.row();let mut day_row = elements::LinearLayout::vertical();day_row.push(create_row_title(day.to_string()).aligned(Alignment::Center));let mut line_style = style::Style::new();line_style.bold();line_style.set_font_size(8);// let par = elements::Paragraph::default()// .styled_string("00:00-00:00", line_style)// .aligned(Alignment::Center);// day_row.push(par);row.push_element(day_row);for s in sched {if let Some(s) = s {row.push_element(create_row_title(format!("{:?}", s)))} else {row.push_element(create_row_title("".to_string()))}}row.push().unwrap();}doc.push(table);}fn create_row_title(title: String) -> elements::Paragraph {let paragraph = elements::Paragraph::default();let mut title_style = style::Style::new();title_style.bold();title_style.set_font_size(10);paragraph.styled_string(title, title_style)}
use genpdf::elements::TableLayout;use genpdf::{elements, style, Alignment, Document, Size};use shared::msgs::activities::FullActivity;use shared::msgs::teachers::Teacher;use shared::msgs::timetables::Schedule;use crate::app::timetables::{selected_timetable_hour, schedules, activities, teachers, classes};use crate::app::timetables::school;pub fn print_teacher_all(){let fon_family = crate::fonts::font_family();let mut doc = genpdf::Document::new(fon_family);let mut buf: Vec<u8> = Vec::new();//print_classes(&mut doc);print_teachers(&mut doc);doc.render(&mut buf).expect("Render edilemedi");let png_jsarray: zoon::JsValue = js_sys::Uint8Array::from(&buf[..]).into();// the buffer has to be an array of arrayslet png_buffer: js_sys::Array = std::iter::IntoIterator::into_iter([png_jsarray]).collect();let mut properties = web_sys::BlobPropertyBag::new();properties.type_("application/pdf");let png_blob =web_sys::Blob::new_with_buffer_source_sequence_and_options(&png_buffer, &properties).unwrap();let url = web_sys::Url::create_object_url_with_blob(&png_blob).unwrap();let window = web_sys::window().unwrap();window.open_with_url(&url).expect("Pdf açılamadı");}fn print_teachers(doc: &mut genpdf::Document){doc.set_paper_size(Size::new(297,210));doc.set_title(format!("{}", school().get_cloned().unwrap().name));// Customize the pageslet mut decorator = genpdf::SimplePageDecorator::new();decorator.set_margins(10);doc.set_page_decorator(decorator);let school_name = school().get_cloned().unwrap().name;doc.set_minimal_conformance();doc.set_line_spacing(1.25);let mut title = elements::LinearLayout::vertical();let mut title_style = style::Style::new();title_style.set_bold();title_style.set_font_size(20);let title_paragraph = elements::Paragraph::default();title.push(title_paragraph.styled_string(&school_name, title_style).aligned(Alignment::Center));doc.push(title);day_row(doc);}use crate::i18n::t_s;fn day_row(doc: &mut Document){let mut table = elements::TableLayout::new(vec![8, 8, 8, 8, 8, 8]);table.set_cell_decorator(elements::FrameCellDecorator::new(true, true, false));let mut row = table.row();row.push_element(create_row_title(format!("{}", t_s!("days"))).aligned(Alignment::Center));for day in &["Pzt","Salı","Çarş","Per","Cuma"]{row.push_element(create_row_title(format!("{}",day)).aligned(Alignment::Center));}row.push().expect("Invalid table row");let mut row = table.row();row.push_element(create_row_title(format!("{}", t_s!("hours"))).aligned(Alignment::Center));for _day in &["Pzt","Salı","Çarş","Per","Cuma"]{let mut table2 = elements::TableLayout::new(vec![1, 1, 1, 1, 1, 1, 1]);table2.set_cell_decorator(elements::FrameCellDecorator::new(true, false, false));let mut row2 = table2.row();for i in [1,2,3,4,5,6,7]{row2.push_element(create_row_title(i.to_string()));}row2.push().expect("");row.push_element(table2);}row.push().expect("");create_teacher_row(&mut table);doc.push(table);}fn create_teacher_row(table: &mut TableLayout){let tchrs = teachers().lock_mut().to_vec();for t in tchrs{let mut row = table.row();row.push_element(create_row_title(format!("{} {}",t.first_name, t.last_name)));for d in 0..5{let t = create_table_for_row(&t, d+1);row.push_element(t);}row.push().expect("msg");}}fn create_table_for_row(t: &Teacher, d: i32)-> TableLayout{let acts = activities().lock_mut().to_vec();let t_acts: Vec<&FullActivity> = acts.iter().filter(|a| a.teachers.iter().any(|c2| c2 == &t.id)).collect();let sch = schedules().lock_mut().to_vec();let sch: Vec<&Schedule> = sch.iter().filter(|s| t_acts.iter().any(|a| a.id == s.activity)).collect();let l = selected_timetable_hour().lock_mut().to_vec();let mut table = genpdf::elements::TableLayout::new(vec![1; l.len()]);table.set_cell_decorator(elements::FrameCellDecorator::new(true, false, false));let mut row = table.row();for i in 0..l.len(){let s = sch.iter().find(|s| s.day_id == d && s.hour as usize == i);match s{Some(s) => {let a = t_acts.iter().find(|a| a.id == s.activity).unwrap();let cls = classes().lock_mut().to_vec();let cls = cls.iter().find(|c| a.classes.iter().any(|c2| c2 == &c.id )).unwrap();let cls = format!("{}{}", cls.kademe, cls.sube);let cls = cls.chars().take(2).collect::<String>();row.push_element(create_row_title(cls));}None => row.push_element(create_row_title2("".to_string()))}}row.push().expect("msg");table}fn create_row_title(title: String) -> elements::Paragraph{let mut paragraph = elements::Paragraph::default();let mut title_style = style::Style::new();title_style.bold();title_style.set_font_size(10);paragraph = paragraph.styled_string(title, title_style);paragraph = paragraph.aligned(Alignment::Center);paragraph}fn create_row_title2(title: String) -> elements::Paragraph{let paragraph = elements::Paragraph::default();let mut title_style = style::Style::new();//title_style.bold();title_style.set_font_size(10);paragraph.styled_string(title, title_style)}
use genpdf::elements::TableLayout;use genpdf::{elements, style, Alignment, Document, Size};pub fn print_class_all() {let fon_family = crate::fonts::font_family();let mut doc = genpdf::Document::new(fon_family);let mut buf: Vec<u8> = Vec::new();//print_classes(&mut doc);print_classes(&mut doc);// doc.render(&mut buf).expect("Render edilemedi");// let png_jsarray: zoon::JsValue = js_sys::Uint8Array::from(&buf[..]).into();// // the buffer has to be an array of arrays// let png_buffer: js_sys::Array = std::iter::IntoIterator::into_iter([png_jsarray]).collect();// let mut properties = web_sys::BlobPropertyBag::new();// properties.type_("application/pdf");// let png_blob =// web_sys::Blob::new_with_buffer_source_sequence_and_options(&png_buffer, &properties)// .unwrap();// let url = web_sys::Url::create_object_url_with_blob(&png_blob).unwrap();// let window = web_sys::window().unwrap();// window.open_with_url(&url).expect("Pdf açılamadı");}fn print_classes(doc: &mut genpdf::Document) {doc.set_paper_size(Size::new(297, 210));doc.set_title(format!("{}", school_name().read()));// Customize the pageslet mut decorator = genpdf::SimplePageDecorator::new();decorator.set_margins(10);doc.set_page_decorator(decorator);let school_name = &*school_name().read();doc.set_minimal_conformance();doc.set_line_spacing(1.25);let mut title = elements::LinearLayout::vertical();let mut title_style = style::Style::new();title_style.set_bold();title_style.set_font_size(20);let title_paragraph = elements::Paragraph::default();title.push(title_paragraph.styled_string(school_name, title_style).aligned(Alignment::Center),);doc.push(title);day_row(doc);}use crate::tabs::activities::{activities, Activity};use crate::tabs::classes::{get_classes, Class};use crate::tabs::generating::Schedule;use crate::tabs::limitations::limitations_ui::{classes_sched, schedules};use crate::tabs::{school_hour, school_name};fn day_row(doc: &mut Document) {let mut table = elements::TableLayout::new(vec![8, 8, 8, 8, 8, 8]);table.set_cell_decorator(elements::FrameCellDecorator::new(true, true, false));let mut row = table.row();row.push_element(create_row_title(format!("{}", "Günler")).aligned(Alignment::Center));for day in &["Pzt", "Salı", "Çarş", "Per", "Cuma"] {row.push_element(create_row_title(format!("{}", day)).aligned(Alignment::Center));}row.push().expect("Invalid table row");let mut row = table.row();row.push_element(create_row_title(format!("{}", "Saatler")).aligned(Alignment::Center));for _day in &["Pzt", "Salı", "Çarş", "Per", "Cuma"] {let mut table2 = elements::TableLayout::new(vec![1, 1, 1, 1, 1, 1, 1]);table2.set_cell_decorator(elements::FrameCellDecorator::new(true, false, false));let mut row2 = table2.row();for i in [1, 2, 3, 4, 5, 6, 7] {row2.push_element(create_row_title(i.to_string()));}row2.push().expect("");row.push_element(table2);}row.push().expect("");create_class_row(&mut table);doc.push(table);}fn create_class_row(table: &mut TableLayout) {let clss = &*get_classes().read();for c in clss {let mut row = table.row();row.push_element(create_row_title(format!("{}", &c.1.name)));for d in 0..5 {let t = create_table_for_row(&c.1, d + 1);row.push_element(t);}row.push().expect("msg");}}fn create_table_for_row(c: &Class, d: i32) -> TableLayout {let acts = activities().read();let c_acts: Vec<&Activity> = acts.values().filter(|a| a.classes.iter().any(|c2| c2 == &c.id)).collect();let sch = &*classes_sched().read();let sch = sch.get(&c.id).unwrap();let l = &*school_hour().read();let l = l.parse::<usize>().unwrap();let mut table = genpdf::elements::TableLayout::new(vec![1; l]);table.set_cell_decorator(elements::FrameCellDecorator::new(true, false, false));let mut row = table.row();for s in sch {// match s {// Some(s) => {// row.push_element(create_row_title(format!("{s:?}")));// }// None => row.push_element(create_row_title2("".to_string())),// }}row.push().expect("msg");table}fn create_row_title(title: String) -> elements::Paragraph {let mut paragraph = elements::Paragraph::default();let mut title_style = style::Style::new();title_style.bold();title_style.set_font_size(10);paragraph = paragraph.styled_string(title, title_style);paragraph = paragraph.aligned(Alignment::Center);paragraph}fn create_row_title2(title: String) -> elements::Paragraph {let paragraph = elements::Paragraph::default();let mut title_style = style::Style::new();//title_style.bold();title_style.set_font_size(10);paragraph.styled_string(title, title_style)}
use eframe::egui::{self, ScrollArea};use limitations_ui::limitations_ui;use super::{classes::classes_lists_ui, get_page, panel_buttons, teachers::teachers_list_ui, SubPage,};pub mod limitations_ui;pub fn limitations(ui: &mut egui::Ui) {egui::TopBottomPanel::top("top_panel").resizable(true).default_height(60.).height_range(50.0..=350.0).show_inside(ui, |ui| {panel_buttons(ui);});egui::SidePanel::left("right_panel").resizable(true).default_width(250.0).width_range(150.0..=300.0).show_inside(ui, |ui| {if let SubPage::Teachers = *get_page().read() {teachers_list_ui(ui);} else {classes_lists_ui(ui);}// limitations_ui(ui);});egui::CentralPanel::default()// .resizable(true)// .default_width(1024.0)// .width_range(800.0..=1280.0).show_inside(ui, |ui| {ScrollArea::vertical()// .scroll_bar_visibility(true).max_width(f32::INFINITY).show_viewport(ui, |ui, _viewport| {// ui.add_sized(Vec2::new(1500., 5000.), Label::new("A"));// Flex::vertical().wrap(false).show(ui, |flex| {limitations_ui(ui);// list_activities_ui(ui);// });});});}
use std::{collections::HashMap,fs::File,io::{Read, Write},sync::{Arc, OnceLock},thread::spawn,};use eframe::egui::{self, mutex::RwLock, vec2, Button, Color32, Frame, Label, RichText, Stroke, Vec2,};use egui_flex::{item, Flex, FlexInstance};use serde::{Deserialize, Serialize};use crate::{tabs::{activities::{activities, acts_frames, get_classes_name, get_teachers_name, partnered_act,teachers_acts_hours, Activity,},classes::{classes_acts, get_classes, selected_class},generating::{available_days, create_available_days, data, Schedule, TimetableData},get_school, school_hour,teachers::{get_teachers, selected_teacher, teachers_acts},SubPage,},DAYS,};use super::get_page;#[derive(Debug, Clone, Default, Serialize, Deserialize)]pub struct ClassLimitation {pub class_id: i32,pub limitations: Vec<Vec<bool>>,}impl ClassLimitation {pub fn new(id: i32) -> Self {let hour = school_hour().read().parse::<usize>().unwrap_or(8);Self {class_id: id,limitations: vec![vec![true; hour]; 7],}}fn validation(&mut self) {let hour = &*school_hour().read();let hour = hour.parse::<usize>().unwrap_or(8);while self.limitations.len() > 7 {self.limitations.pop();}while self.limitations.len() < 7 {self.limitations.push(vec![true; hour]);}self.limitations.iter_mut().for_each(|l| {while l.len() > hour {l.pop();}while l.len() < hour {l.push(true);}})}}pub fn classes_volumes() -> &'static Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>> {static PAGE: OnceLock<Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(create_classes_volumes())))}fn create_classes_volumes() -> HashMap<i32, Vec<Vec<i32>>> {let clss = get_classes().read();let s_hour = get_school().read().hour;let acts = classes_acts().read().clone();let mut map = HashMap::new();for c in &*clss {let c_acts = acts.get(c.0).unwrap();let mut days = vec![];for day in DAYS.iter().enumerate() {let mut hours = vec![0; s_hour as usize];for act in c_acts {let h_lim = s_hour - act.hour + 1;for h in 0..h_lim as usize {if act.hour + h <= s_hour&& act.classes_available(h, day.0)&& act.teachers_available(h, day.0){(0..act.hour).for_each(|hh| hours[h + hh as usize] += 1);}}}days.push(hours);}map.insert(*c.0 as i32, days);}map}pub fn teachers_volumes() -> &'static Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>> {static PAGE: OnceLock<Arc<RwLock<HashMap<i32, Vec<Vec<i32>>>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(create_teachers_volumes())))}fn create_teachers_volumes() -> HashMap<i32, Vec<Vec<i32>>> {let teachers = get_teachers().read();let s_hour = get_school().read().hour;let acts = teachers_acts().read().clone();let mut map = HashMap::new();for t in &*teachers {let t_acts = acts.get(t.0).unwrap();let mut days = vec![];for day in DAYS.iter().enumerate() {let mut hours = vec![0; s_hour as usize];for h in 0..s_hour as usize {for act in t_acts {if act.hour + h <= s_hour&& act.classes_available(h, day.0)&& act.teachers_available(h, day.0){hours[h] += 1;}}}days.push(hours);}map.insert(*t.0 as i32, days);}map}pub fn schedules() -> &'static Arc<RwLock<Vec<Schedule>>> {static PAGE: OnceLock<Arc<RwLock<Vec<Schedule>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(vec![])))}pub fn classes_limitations() -> &'static Arc<RwLock<HashMap<i32, ClassLimitation>>> {static PAGE: OnceLock<Arc<RwLock<HashMap<i32, ClassLimitation>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(get_class_limitations())))}pub fn get_class_limitations() -> HashMap<i32, ClassLimitation> {let lims = File::open("./db/classes_limitations.json");if let Ok(mut lims) = lims {let mut content: String = String::new();lims.read_to_string(&mut content).unwrap();let mut cls: Vec<ClassLimitation> = serde_json::from_str(content.as_str()).unwrap();cls.iter_mut().for_each(|l| l.validation());let mut lims: HashMap<i32, ClassLimitation> = HashMap::new();for c in cls {lims.insert(c.class_id, c);}return lims;} else {let mut lims: HashMap<i32, ClassLimitation> = HashMap::new();for c in &*get_classes().read() {lims.insert(c.1.id, ClassLimitation::new(c.1.id));}return lims;}}type ClassSched = Arc<RwLock<HashMap<i32, Vec<Vec<Option<Activity>>>>>>;pub fn classes_sched() -> &'static ClassSched {static ACT: OnceLock<ClassSched> = OnceLock::new();ACT.get_or_init(|| Arc::new(RwLock::new(create_classes_sched())))}fn get_class_scheds(id: i32) -> Vec<Vec<Option<Activity>>> {let scheds = &*classes_sched().read();let scheds = scheds.get(&id);if let Some(scheds) = scheds {return scheds.clone();} else {create_classes_sched();return get_class_scheds(id);}}fn get_class_lims(id: i32) -> Vec<Vec<bool>> {let lims = classes_limitations().read();let lims = lims.get(&id);if let Some(lims) = lims {return lims.limitations.clone();} else {std::thread::spawn(move || {classes_limitations().write().insert(id, ClassLimitation::new(id));});return get_class_lims(id);}}#[derive(Debug, Clone, Default, Serialize, Deserialize)]pub struct TeacherLimitation {pub teacher_id: i32,pub limitations: Vec<Vec<bool>>,}impl TeacherLimitation {pub fn new(id: i32) -> Self {let hour = school_hour().read().parse::<usize>().unwrap_or(8);Self {teacher_id: id,limitations: vec![vec![true; hour]; 7],}}fn validation(&mut self) {let hour = &*school_hour().read();let hour = hour.parse::<usize>().unwrap_or(8);while self.limitations.len() > 7 {self.limitations.pop();}while self.limitations.len() < 7 {self.limitations.push(vec![true; hour]);}self.limitations.iter_mut().for_each(|l| {while l.len() > hour {l.pop();}while l.len() < hour {l.push(true);}})}}fn get_teacher_lims(id: i32) -> Vec<Vec<bool>> {let lims = teachers_limitations().read();let lims = lims.get(&id);if let Some(lims) = lims {return lims.limitations.clone();} else {let lims = TeacherLimitation::new(id);let lims2 = lims.clone();std::thread::spawn(move || {teachers_limitations().write().insert(id, lims2);});return lims.limitations;}}pub fn teachers_limitations() -> &'static Arc<RwLock<HashMap<i32, TeacherLimitation>>> {static PAGE: OnceLock<Arc<RwLock<HashMap<i32, TeacherLimitation>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(get_teacher_limitations())))}pub fn get_teacher_limitations() -> HashMap<i32, TeacherLimitation> {let lims = File::open("./db/teachers_limitations.json");if let Ok(mut lims) = lims {let mut content: String = String::new();lims.read_to_string(&mut content).unwrap();let mut cls: Vec<TeacherLimitation> = serde_json::from_str(content.as_str()).unwrap();cls.iter_mut().for_each(|l| l.validation());let mut lims: HashMap<i32, TeacherLimitation> = HashMap::new();for c in cls {lims.insert(c.teacher_id, c);}return lims;} else {let tchrs = get_teachers().read();let mut lims: HashMap<i32, TeacherLimitation> = HashMap::new();for t in &*tchrs {lims.insert(t.1.id, TeacherLimitation::new(t.1.id));}return lims;}}type TeacherSched = Arc<RwLock<HashMap<i32, Vec<Vec<Option<Activity>>>>>>;pub fn teachers_scheds() -> &'static TeacherSched {// create_sched();static ACT: OnceLock<TeacherSched> = OnceLock::new();ACT.get_or_init(|| Arc::new(RwLock::new(create_teachers_sched())))}fn get_teacher_scheds(id: i32) -> Vec<Vec<Option<Activity>>> {let scheds = teachers_scheds().read();let scheds = scheds.get(&id);if let Some(scheds) = scheds {return scheds.clone();} else {create_teachers_sched();return get_teacher_scheds(id);}}fn _update_teacher_limitation() {// let teacher_lims = &*teacher_limitation().read();// let mut lims = teachers_limitations().write();// let id = selected_teacher().read().unwrap();// lims.insert(id, teacher_lims.clone());}pub fn limitations_ui(ui: &mut egui::Ui) {let page = &*get_page().read();let acts = if let SubPage::Teachers = page {let id = selected_teacher().read().unwrap_or(1);let activities = teachers_acts().read().clone();let act = activities.get(&id).unwrap();act.clone()} else {let id = selected_class().read().unwrap_or(1);let activities = classes_acts().read().clone();let act = activities.get(&id).unwrap();act.clone()};match page {super::SubPage::Teachers => {if let Some(teacher_id) = *selected_teacher().read() {ui.set_width(1024.);Flex::vertical()// .grow_items(0.5).gap(Vec2::new(0., 0.)).show(ui, |flex| {flex.add(item(),Label::new(RichText::new(format!("{}: {} saat",get_teachers_name(&[teacher_id]),teachers_acts_hours().read().clone().get(&teacher_id).unwrap())).size(24.),),);flex.add_ui(item(), |ui| ui.add_space(10.));hours_frame(flex);days_frame(flex,get_teacher_lims(teacher_id),get_teacher_scheds(teacher_id),teachers_volumes().read().get(&teacher_id).unwrap(),);flex.add_ui(item(), |ui| ui.add_space(10.));flex.add_ui(item(), |ui| {ui.horizontal(|ui| {if ui.add_sized(Vec2::new(150., 50.), Button::new("Kaydet")).clicked(){save_teachers_limitations();}if ui.add_sized(Vec2::new(150., 50.), Button::new("Tümüne Uygula")).clicked(){change_all();}});});});} else {ui.label("Sol listeden seçim yapın");}}super::SubPage::Classes => {if let Some(class_id) = *selected_class().read() {ui.set_width(1024.);Flex::vertical()// .grow_items(0.5).gap(Vec2::new(0., 0.)).show(ui, |flex| {flex.add(item().grow(1.),Label::new(RichText::new(get_classes_name(&[class_id])).size(24.)),);flex.add_ui(item(), |ui| ui.add_space(10.));hours_frame(flex);days_frame(flex,get_class_lims(class_id),get_class_scheds(class_id),classes_volumes().read().get(&class_id).unwrap(),);flex.add_ui(item(), |ui| ui.add_space(10.));flex.add_ui(item(), |ui| {ui.horizontal(|ui| {if ui.add_sized(Vec2::new(150., 50.), Button::new("Kaydet")).clicked(){save_classes_limitations();}if ui.add_sized(Vec2::new(150., 50.), Button::new("Tümüne Uygula")).clicked(){change_all();}});});});} else {ui.label("Sol listeden seçim yapın");}}}acts_frames(ui, &acts);}fn hours_frame(flex: &mut FlexInstance) {let hour = school_hour().read().parse::<usize>().unwrap_or(8);let frame = Frame::none().stroke(Stroke::new(1., Color32::LIGHT_GRAY));flex.add_flex(item().grow(1.),Flex::horizontal().gap(vec2(0., 0.)),|flex| {flex.add_flex(item().frame(frame), Flex::new(), |flex| {flex.add_ui(item(), |ui| {ui.add_sized(Vec2::new(100., 50.), Label::new("Günler ve Saatler"));});});for i in 0..hour {flex.add_flex(item().frame(frame), Flex::new(), |flex| {flex.add_ui(item(), |ui| {if ui.add_sized(Vec2::new(100., 50.), Label::new((i + 1).to_string())).clicked(){change_all_hours(i);};})});}},);}// static LIMS: &[&[bool]] = &'static [&'static [true; 10]; 7];fn days_frame(flex: &mut FlexInstance,_lims: Vec<Vec<bool>>,_scheds: Vec<Vec<Option<Activity>>>,vol: &Vec<Vec<i32>>,) {let hour = school_hour().read().parse::<usize>().unwrap_or(8);let frame = Frame::none().stroke(Stroke::new(1., Color32::LIGHT_GRAY));for (index, day) in DAYS.iter().enumerate() {flex.add_flex(item(), Flex::horizontal().gap(Vec2::splat(0.)), |flex| {flex.add_flex(item().frame(frame), Flex::new(), |flex| {flex.add_ui(item(), |ui| {if ui.add_sized(Vec2::new(100., 50.), Label::new(*day)).clicked(){change_all_day(index);};});});for i in 0..hour {let v: u8 = if vol[index][i] > 100 {100} else {vol[index][i] as u8};let f_color = if _lims[index][i] {Color32::from_rgb(50 + v * 2, 0, 0)} else {Color32::default()};let frame = Frame::none().stroke(Stroke::new(1., Color32::LIGHT_GRAY)).fill(f_color);flex.add_flex(item().grow(1.).frame(frame), Flex::vertical(), |ui| {ui.add_ui(item(), |ui| {ui.visuals_mut().widgets.inactive.bg_fill = egui::Color32::TRANSPARENT;let (_, payl) = ui.dnd_drop_zone::<Activity, ()>(Frame::none(), |ui| {sched_act(ui, &_scheds[index][i], index, i)});if let Some(p) = payl {if p.teachers_available(i, index) && p.classes_available(i, index) {std::thread::spawn(move || {if let Some(p_id) = partnered_act().read().get(&p.id) {let a = activities().read();let a = a.get(p_id).unwrap();data().write().put_act(index, i, &a.clone(), false);} else {data().write().put_act(index, i, &p.clone(), false);}data().write().replace_act(index, i, p.id, p.hour);// update_tt();});}// println!("{p:?}");}});});}});}}pub fn create_teachers_sched() -> HashMap<i32, Vec<Vec<Option<Activity>>>> {let mut t_scheds = HashMap::new();let acts = activities().read().clone();let p_acts = partnered_act().read().clone();for teacher in &*get_teachers().read() {let mut teacher_acts = activities().read().iter().filter(|a| a.1.teachers.iter().any(|c| c == &teacher.1.id)).map(|a| a.1.clone()).collect::<Vec<Activity>>();let p_ids = p_acts.iter().filter(|pa| teacher_acts.iter().any(|ta| pa.0 == &ta.id)).map(|pa| pa.1.clone()).collect::<Vec<i32>>();for p_id in p_ids {if let Some(act) = acts.get(&p_id) {teacher_acts.push(act.clone());}}// let mut scheds = vec![];let scs = (*schedules().read()).clone();let sched = scs.iter().filter(|s| teacher_acts.iter().any(|a| a.id == s.activity)).map(|s| s.clone()).collect::<Vec<Schedule>>();let mut scheduls: Vec<Vec<Option<Activity>>> =vec![vec![None; get_school().read().hour as usize]; 7];sched.iter().for_each(|s| {scheduls[s.day_id][s.hour as usize] = teacher_acts.clone().into_iter().find(|ca| ca.id == s.activity);});let t = teacher.1.clone();// let t_sched = Arc::clone(teacher_scheds());// std::thread::spawn(move || {t_scheds.insert(t.id, scheduls);// });}t_scheds}pub fn create_classes_sched() -> HashMap<i32, Vec<Vec<Option<Activity>>>> {let mut t_scheds = HashMap::new();for class in &*get_classes().read() {let class_acts = activities().read().iter().filter(|a| a.1.classes.iter().any(|c| c == &class.1.id)).map(|a| a.1.clone()).collect::<Vec<Activity>>();// let mut scheds = vec![];let scs = (*schedules().read()).clone();let sched = scs.iter().filter(|s| class_acts.iter().any(|a| a.id == s.activity)).map(|s| s.clone()).collect::<Vec<Schedule>>();let mut scheduls: Vec<Vec<Option<Activity>>> =vec![vec![None; get_school().read().hour as usize]; 7];sched.iter().for_each(|s| {scheduls[s.day_id][s.hour as usize] = class_acts.clone().into_iter().find(|ca| ca.id == s.activity);});let t = class.1.clone();// let t_sched = Arc::clone(class_scheds());// std::thread::spawn(move || {t_scheds.insert(t.id, scheduls);// });}t_scheds}fn sched_act(ui: &mut egui::Ui, a: &Option<Activity>, index: usize, i: usize) {let Some(a) = a else {if ui.add_sized(Vec2::new(100., 50.), Label::new("")).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){change_row(index, i);};return ();};let rtext = RichText::new(&a.lectures_name()).size(12.).strong();if ui.add_sized(Vec2::new(100., 15.), Label::new(rtext)).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){change_row(index, i);};match *get_page().read() {SubPage::Teachers => {let rtext = RichText::new(&a.classes_name()).size(16.).strong();if ui.add_sized(vec2(100., 20.), Label::new(rtext)).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){change_row(index, i);};}SubPage::Classes => {let rtext = RichText::new(&a.teachers_short_name()).size(10.).strong();if ui.add_sized(vec2(100., 15.), Label::new(rtext)).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){change_row(index, i);};}}ui.horizontal(|ui| {let rtext = RichText::new("🗑").size(16.).strong();if ui.add_sized(Vec2::new(45., 15.), Label::new(rtext)).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){del_tt(a.id);};let color = if is_lock_tt(a.id) {Color32::BLUE} else {Color32::GRAY};let ltext = RichText::new("🔒").size(16.).color(color).strong();if ui.add_sized(Vec2::new(45., 15.), Label::new(ltext)).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){lock_tt(a.id);};});// ui.add(Label::new());// format!("{}\n{}", a.lectures_name(), a.teachers_short_name())}fn lock_tt(act_id: i32) {std::thread::spawn(move || {let dt: &mut TimetableData = &mut *data().write();let scheds = &mut dt.timetables;let sched = scheds.get_mut(&act_id);if let Some(tt) = sched {tt.iter_mut().for_each(|t| t.locked = !t.locked);}update_tt();});}fn del_tt(act_id: i32) {std::thread::spawn(move || {let dt: &mut TimetableData = &mut *data().write();let scheds = &mut dt.timetables;let sched = scheds.remove(&act_id);update_tt();});}pub fn update_tt() {std::thread::spawn(move || {let dt: &mut TimetableData = &mut *data().write();let scheds = &mut dt.timetables;let mut sch = vec![];scheds.values().for_each(|tt| sch.append(&mut tt.clone()));*schedules().write() = sch.clone();*classes_sched().write() = create_classes_sched();*teachers_scheds().write() = create_teachers_sched();*classes_volumes().write() = create_classes_volumes();*teachers_volumes().write() = create_teachers_volumes();});}fn is_lock_tt(act_id: i32) -> bool {let scheds: &Vec<Schedule> = &*schedules().write();let sched = scheds.iter().find(|a| a.activity == act_id);if let Some(tt) = sched {return tt.locked;}return false;}fn change_all_day(day: usize) {std::thread::spawn(move || {let page = &*get_page().read();match page {super::SubPage::Teachers => {let lims = &*teachers_limitations();let lim = Arc::clone(lims);std::thread::spawn(move || {let lims = &mut lim.write();let day = &mut lims.get_mut(&selected_teacher().read().unwrap()).unwrap().limitations[day];if day.iter().any(|h| !*h) {*day = vec![true; 10];} else {*day = vec![false; 10];}});}super::SubPage::Classes => {let lims = &*classes_limitations();let lim = Arc::clone(lims);std::thread::spawn(move || {let lims = &mut lim.write();let day = &mut lims.get_mut(&selected_class().read().unwrap()).unwrap().limitations[day];if day.iter().any(|h| !*h) {*day = vec![true; 10];} else {*day = vec![false; 10];}});}}});}fn change_all_hours(hour: usize) {std::thread::spawn(move || {let page = &*get_page().read();match page {super::SubPage::Teachers => {let lims = &*teachers_limitations();let lim = Arc::clone(lims);std::thread::spawn(move || {let lims = &mut lim.write();let lims = &mut lims.get_mut(&selected_teacher().read().unwrap()).unwrap().limitations;if lims.iter().any(|h| !h[hour]) {lims.iter_mut().for_each(|d| d[hour] = true);} else {lims.iter_mut().for_each(|d| d[hour] = false);// *day = vec![false; 10];}// lim.write().limitations[day][hour] = !row;});}super::SubPage::Classes => {let lims = &*classes_limitations();let lim = Arc::clone(lims);std::thread::spawn(move || {let lims = &mut lim.write();let lims = &mut lims.get_mut(&selected_class().read().unwrap()).unwrap().limitations;if lims.iter().any(|h| !h[hour]) {lims.iter_mut().for_each(|d| d[hour] = true);} else {lims.iter_mut().for_each(|d| d[hour] = false);}});}}});}pub fn save_teachers_limitations() {spawn(move || {let lims = &*teachers_limitations().read();let lims = lims.values().collect::<Vec<&TeacherLimitation>>();let mut f = File::create("./db/teachers_limitations.json").unwrap();f.write_all(serde_json::to_string(&lims).unwrap().as_bytes()).unwrap();*available_days().write() = create_available_days();});}pub fn save_classes_limitations() {let lims = &*classes_limitations().read();let lims = lims.values().collect::<Vec<&ClassLimitation>>();let mut f = File::create("./db/classes_limitations.json").unwrap();f.write_all(serde_json::to_string(&lims).unwrap().as_bytes()).expect("Sınıf Kısıtları Yazılamadı");}fn change_row(day: usize, hour: usize) {std::thread::spawn(move || {let page = &*get_page().read();match page {SubPage::Teachers => {let c_id = selected_teacher().read().unwrap();let mut lims = teachers_limitations().write();let row = lims.get_mut(&c_id);if let Some(r) = row {r.limitations[day][hour] = !r.limitations[day][hour];}}SubPage::Classes => {let c_id = selected_class().read().unwrap();let mut lims = classes_limitations().write();let row = lims.get_mut(&c_id);if let Some(r) = row {r.limitations[day][hour] = !r.limitations[day][hour];}}}});}fn change_all() {let page = get_page();match &*page.read() {SubPage::Teachers => {change_all_teachers();}SubPage::Classes => {change_all_classes();}}}fn change_all_teachers() {let t_id = selected_teacher().read().unwrap();let teachers_lims = teachers_limitations().read().clone();let t_lims = teachers_lims.get(&t_id).unwrap().clone();std::thread::spawn(move || {let t_lims = t_lims.clone();let teachers = &*get_teachers().read();for t in teachers {let lims = &mut *teachers_limitations().write();if let Some(lims) = lims.get_mut(&t.1.id) {lims.limitations = t_lims.limitations.clone();}}});}fn change_all_classes() {let c_id = selected_class().read().unwrap();let classes_lims = classes_limitations().read().clone();let c_lims = classes_lims.get(&c_id).unwrap().clone();std::thread::spawn(move || {let c_lims = c_lims.clone();let classes = &*get_classes().read();for c in classes {let lims = &mut *classes_limitations().write();if let Some(lims) = lims.get_mut(&c.1.id) {lims.limitations = c_lims.limitations.clone();}}});}
use std::{collections::HashMap,fs::File,io::{Read, Write},sync::{Arc, OnceLock},};use eframe::egui::{self, mutex::RwLock, Color32, Label, RichText, Sense, Stroke, Vec2};use serde::{Deserialize, Serialize};use crate::{tabs::{activities::{activities, get_lec_short_name, get_teachers_short_name, Activity},classes::{get_classes, selected_class, set_selected_class},generating::Schedule,},DAYS,};use super::save_classes_limitations;#[derive(Debug, Clone, Default, Serialize, Deserialize)]pub struct ClassLimitation {pub class_id: i32,pub limitations: Vec<Vec<bool>>,}impl ClassLimitation {pub fn new(id: i32) -> Self {Self {class_id: id,limitations: vec![vec![true; 10]; 7],}}}pub fn classes_limitations() -> &'static Arc<RwLock<HashMap<i32, ClassLimitation>>> {static PAGE: OnceLock<Arc<RwLock<HashMap<i32, ClassLimitation>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(get_class_limitations())))}pub fn schedules() -> &'static Arc<RwLock<Vec<Schedule>>> {static PAGE: OnceLock<Arc<RwLock<Vec<Schedule>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(vec![])))}pub fn get_class_limitations() -> HashMap<i32, ClassLimitation> {let lims = File::open("./db/classes_limitations.json");if let Ok(mut lims) = lims {let mut content: String = String::new();lims.read_to_string(&mut content).unwrap();let cls: Vec<ClassLimitation> = serde_json::from_str(content.as_str()).unwrap();let mut lims: HashMap<i32, ClassLimitation> = HashMap::new();for c in cls {lims.insert(c.class_id, c);}return lims;}HashMap::new()}type ClassSched = Arc<RwLock<HashMap<i32, Vec<Vec<Option<Activity>>>>>>;pub fn class_sched() -> &'static ClassSched {static ACT: OnceLock<ClassSched> = OnceLock::new();ACT.get_or_init(|| Arc::new(RwLock::new(HashMap::new())))}pub fn class_limitation() -> &'static Arc<RwLock<ClassLimitation>> {static LIM: OnceLock<Arc<RwLock<ClassLimitation>>> = OnceLock::new();LIM.get_or_init(|| Arc::new(RwLock::new(ClassLimitation::default())))}pub fn create_sched(id: i32) {// let id = selected_class().read().unwrap();let class_acts = activities().read().iter().filter(|a| a.1.classes.iter().any(|c| c == &id)).map(|a| a.1.clone()).collect::<Vec<Activity>>();// let mut scheds = vec![];let scs = (*schedules().read()).clone();let sched = scs.iter().filter(|s| class_acts.iter().any(|a| a.id == s.activity)).map(|s| s.clone()).collect::<Vec<Schedule>>();let mut scheduls: Vec<Vec<Option<Activity>>> = vec![vec![None; 10]; 7];sched.iter().for_each(|s| {scheduls[s.day_id as usize - 1][s.hour as usize] = class_acts.clone().into_iter().find(|ca| ca.id == s.activity);});std::thread::spawn(move || {let c_sched = Arc::clone(class_sched());c_sched.write().insert(id, scheduls);});}pub fn save_class_limitations() {let lims = &*classes_limitations().read();let lims = lims.values().collect::<Vec<&ClassLimitation>>();let mut f = File::create("./db/classes_limitations.json").unwrap();f.write_all(serde_json::to_string(&lims).unwrap().as_bytes()).expect("Kısıtlamalar Yazılamadı");}pub fn update_class_limitation() {let class_lims = &*class_limitation().read();let mut lims = classes_limitations().write();let id = selected_class().read().unwrap();lims.insert(id, class_lims.clone());}pub fn class_lim_ui(ui: &mut egui::Ui) {for c in &*get_classes().read() {create_sched(c.1.id);}egui::SidePanel::left("right_panel").resizable(true).default_width(250.0).width_range(150.0..=300.0).show_inside(ui, |ui| {ui.vertical_centered(|ui| {let class_id = selected_class().read();let mut classes = get_classes().write();for c in &mut *classes {let fill_color = if class_id.is_some_and(|c2| c2 == c.1.id) {Color32::LIGHT_BLUE} else {Color32::default()};let stroke_color = if class_id.is_some_and(|c2| c2 == c.1.id) {Color32::DARK_BLUE} else {Color32::default()};let button = egui::Frame::none().fill(fill_color).stroke(Stroke::new(1., stroke_color)).show(ui, |ui| {ui.label(&c.1.name);}).response;let button = button.interact(egui::Sense::click()).on_hover_cursor(egui::CursorIcon::PointingHand);if button.clicked() {set_selected_class(c.1.id);}}});});egui::CentralPanel::default()// .resizable(true)// .default_width(1024.0)// .width_range(800.0..=1280.0).show_inside(ui, |ui| {class_limitation_ui(ui);});}fn class_limitation_ui(ui: &mut egui::Ui) {if let None = *selected_class().read() {return ();}// ui.set_width(1024.)let class_id = selected_class().read().unwrap();let c_sched = class_sched().read();let c_sched = c_sched.get(&class_id);if let Some(c_sched) = c_sched {ui.add_space(50.);ui.horizontal(|ui| {ui.add_space(100.);egui::Grid::new("some_unique_id").min_col_width(100.).max_col_width(100.).min_row_height(100.)// .with_row_color(100.).spacing((1.0, 1.0)).show(ui, |ui| {hours_row(ui);ui.end_row();days_row(ui, c_sched);});ui.end_row();});ui.vertical_centered(|ui| {ui.add_space(20.);if ui.button("Kaydet").clicked() {update_class_limitation();};if ui.button("Tümünü dosyaya Kaydet").clicked() {save_classes_limitations();};});}}fn days_row(ui: &mut egui::Ui, c_sched: &Vec<Vec<Option<Activity>>>) {for day in DAYS.iter().enumerate() {ui.painter().rect(ui.available_rect_before_wrap(),0.0,Color32::default(),Stroke::new(1.0, Color32::LIGHT_GRAY),);if ui.add_sized(Vec2::new(100., 50.), Label::new(*day.1)).interact(Sense::click()).clicked(){change_all_day(day.0);};for i in 1..=10 {row_paint(ui, day.0, i - 1);let r = ui.add_sized(Vec2::new(100., 50.),Label::new(sched_act(&c_sched[day.0][i - 1])),);let r = r.interact(Sense::click()).on_hover_cursor(egui::CursorIcon::PointingHand);if r.clicked() {change_row(day.0, i - 1);}}ui.end_row();}}fn hours_row(ui: &mut egui::Ui) {ui.painter().rect(ui.available_rect_before_wrap(),0.0,Color32::default(),Stroke::new(1.0, Color32::LIGHT_GRAY),);ui.label("Günler ve Saatler");for i in 1..=10 {ui.painter().rect(ui.available_rect_before_wrap(),0.0,Color32::default(),Stroke::new(1.0, Color32::LIGHT_GRAY),);if ui.add_sized(Vec2::new(100., 50.),Label::new(RichText::new(format!("{i}. Saat")).color(Color32::WHITE)),).interact(Sense::click()).clicked(){change_all_hours(i - 1);};}}fn row_paint(ui: &mut egui::Ui, day: usize, hour: usize) {let lims = &*class_limitation().read().limitations;if lims[day][hour] {ui.painter().rect_filled(ui.available_rect_before_wrap(), 0.0, Color32::BROWN);}ui.painter().rect(ui.available_rect_before_wrap(),0.0,Color32::default(),Stroke::new(1., Color32::WHITE),);}fn change_row(day: usize, hour: usize) {let lims = &*class_limitation();std::thread::spawn(move || {let lim = Arc::clone(lims);let row = lim.read().limitations[day][hour];lim.write().limitations[day][hour] = !row;});}fn sched_act(a: &Option<Activity>) -> String {let Some(a) = a else {return "".to_string();};let mut activity = a.id.to_string();activity.push_str("-");activity.push_str(&get_lec_short_name(a.lecture));activity.push_str("\n");// activity.push_str(&get_classes_name(&a.classes));activity.push_str(&get_teachers_short_name(&a.teachers));activity}fn change_all_day(day: usize) {let lims = &*class_limitation();std::thread::spawn(move || {let lim = Arc::clone(lims);let day = &mut lim.write().limitations[day];if day.iter().any(|h| !*h) {*day = vec![true; 10];} else {*day = vec![false; 10];}// lim.write().limitations[day][hour] = !row;});}fn change_all_hours(hour: usize) {let lims = &*class_limitation();std::thread::spawn(move || {let lim = Arc::clone(lims);let day = &mut lim.write().limitations;if day.iter().any(|h| !h[hour]) {day.iter_mut().for_each(|d| d[hour] = true);} else {day.iter_mut().for_each(|d| d[hour] = false);// *day = vec![false; 10];}// lim.write().limitations[day][hour] = !row;});}
use eframe::egui;use eframe::egui::mutex::RwLock;use eframe::egui::vec2;use eframe::egui::Align2;use eframe::egui::Button;use eframe::egui::Color32;use eframe::egui::Label;use eframe::egui::Link;use eframe::egui::RichText;use eframe::egui::Stroke;use eframe::egui::TextEdit;use egui::TextBuffer;// use eframe::Frame;use egui_flex::item;use egui_flex::Flex;use serde::Deserialize;use serde::Serialize;use std::collections::BTreeMap;use std::fmt::Display;use std::fs::File;use std::io::Read;use std::io::Write;use std::iter::zip;use std::sync::Arc;use std::sync::OnceLock;use super::activities::activities;use super::activities::activity_form::filtered_lectures;use super::activities::activity_form::filtering_lectures;use super::activities::activity_form::lectures_ui::set_lecture_filter;use super::activities::save_activities;use super::activities::Activity;use super::classes::get_classes;#[derive(Clone, Serialize, Deserialize, Debug, Default)]pub struct Lecture {pub id: i32,pub name: String,pub short_name: String,}impl Display for Lecture {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {write!(f, "{}", self.name)}}pub fn lec_del_states() -> &'static Arc<RwLock<Vec<bool>>> {static LECTURES: OnceLock<Arc<RwLock<Vec<bool>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(vec![false; filtered_lectures().read().len()])))}pub fn create_states() -> Vec<bool> {vec![false; filtered_lectures().read().len()]}pub fn class_lectures() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>> {static LECTURES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(create_class_lectures())))}pub fn not_class_lectures() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>> {static LECTURES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Lecture>>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(not_create_class_lectures())))}pub fn get_lectures() -> &'static Arc<RwLock<BTreeMap<i32, Lecture>>> {static LECTURES: OnceLock<Arc<RwLock<BTreeMap<i32, Lecture>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(read_lectures())))}pub fn lec_name() -> &'static Arc<RwLock<String>> {static NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}pub fn selected_lec() -> &'static Arc<RwLock<i32>> {static NAME: OnceLock<Arc<RwLock<i32>>> = OnceLock::new();NAME.get_or_init(|| Arc::new(RwLock::new(-1)))}pub fn lec_short_name() -> &'static Arc<RwLock<String>> {static SHORT_NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}fn update_lec_form() -> &'static Arc<RwLock<bool>> {static SHORT_NAME: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new(false)))}fn update_lec(ui: &mut eframe::egui::Ui) {egui::Window::new("Update Lecture").open(&mut *update_lec_form().write()).resizable([true, true]).show(ui.ctx(), |ui| {ui.add(TextEdit::singleline(&mut *lec_name().write()));ui.add(TextEdit::singleline(&mut *lec_short_name().write()));if ui.add(Button::new("Güncelle")).clicked() {if let Some(t) = get_lectures().write().get_mut(&selected_lec().read()) {t.name = lec_name().read().clone();t.short_name = lec_short_name().read().clone();save_lectures();lec_name().write().clear();lec_short_name().write().clear();set_lecture_filter();*update_lec_form().write() = false;}}});}pub fn lectures_page(ui: &mut eframe::egui::Ui) {// let mut name = get_name().lock().unwrap();ui.vertical_centered(|ui| {if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *lec_name().write()).hint_text("Ders Adını Gir"),).changed(){set_lecture_filter();};ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *lec_short_name().write()).hint_text("Kısa Adı"),);if ui.add_sized(vec2(250., 30.), Button::new("Ekle")).clicked() {add_lec();}});ui.separator();lectures_ui(ui);}fn add_lec() {let new_id = find_new_id();let new_lec = Lecture {id: new_id,name: lec_name().write().clone(),short_name: lec_short_name().write().clone(),};std::thread::spawn(move || {let lecs = get_lectures();lecs.write().insert(new_id, new_lec);*lec_name().write() = "".to_string();*lec_short_name().write() = "".to_string();set_lecture_filter();*filtered_lectures().write() = filtering_lectures();save_lectures();lec_del_states().write().push(false);});}fn lectures_ui(ui: &mut eframe::egui::Ui) {update_lec(ui);Flex::horizontal()// .grow_items(1.).wrap(true).gap(vec2(20., 20.)).show(ui, |flex| {let del_states = lec_del_states().read().clone();let del_states = del_states.iter().enumerate();for (del_state, lecture) in zip(del_states, filtered_lectures().read().iter()) {let frame = egui::Frame::default().stroke(Stroke::new(0.3, Color32::GRAY)).rounding(5.).inner_margin(10.);flex.add_flex(item().grow(1.).frame(frame),Flex::vertical().align_items_content(Align2::CENTER_TOP),|flex| {flex.add(item(), Label::new(&lecture.name));if *del_state.1 {flex.add_flex(item().grow(1.),Flex::horizontal().align_items(egui_flex::FlexAlign::Center),|flex| {if flex.add(item().grow(1.),Link::new(RichText::new("Sil").color(Color32::LIGHT_RED),),)// .inner.clicked(){del_lecture(lecture.id);};if flex.add(item().grow(1.), Link::new("Vazgeç"))// .inner.clicked(){change_state(del_state.0);};},);} else {if flex.add(item(),Link::new(RichText::new("Sil").color(Color32::DARK_RED)),)// .inner.clicked(){change_state(del_state.0);}if flex.add(item(), Link::new("Düzenle")).clicked() {let c = lecture.clone();*selected_lec().write() = c.id;std::thread::spawn(move || {*lec_name().write() = c.name.clone();*lec_short_name().write() = c.short_name.clone();*update_lec_form().write() = true;});}}},);}});}fn change_state(state: usize) {std::thread::spawn(move || {if let Some(st) = lec_del_states().write().get_mut(state) {*st = !*st;}});}fn save_lectures() {std::thread::spawn(move || {let lectures = get_lectures().read();let js = serde_json::to_string(&*lectures);match js {Ok(j) => {let mut f = File::create("./db/lectures.json").unwrap();f.write_all(j.as_bytes()).unwrap();}Err(_) => {}}});}fn read_lectures() -> BTreeMap<i32, Lecture> {let f = File::open("./db/lectures.json");if let Ok(mut f) = f {let mut content: String = String::new();f.read_to_string(&mut content).unwrap();let cls: BTreeMap<i32, Lecture> = serde_json::from_str(content.as_str()).unwrap();return cls;}BTreeMap::new()}fn create_class_lectures() -> BTreeMap<i32, Vec<Lecture>> {let mut map = BTreeMap::new();let cls = get_classes().read();let acts = &*activities().read();let lecs = get_lectures().read().values().map(|l| l.clone()).collect::<Vec<Lecture>>();for c in &*cls {let c_acts = acts.values().filter(|a| a.classes.iter().any(|ac| ac == &c.1.id)).map(|a| a.clone()).collect::<Vec<Activity>>();let lec = &lecs.iter().filter(|l| c_acts.iter().any(|a| a.lecture == l.id)).map(|l| l.clone()).collect::<Vec<Lecture>>();map.insert(c.1.id, lec.clone());}map}fn not_create_class_lectures() -> BTreeMap<i32, Vec<Lecture>> {let mut map = BTreeMap::new();let cls = get_classes().read();// let acts = &*activities().read();let lecs = get_lectures().read().values().map(|l| l.clone()).collect::<Vec<Lecture>>();let c_lecs = class_lectures().read().clone();for c in &*cls {let c_lecs = c_lecs.get(&c.1.id);if let Some(cl) = c_lecs {let mut l = lecs.clone();l.retain(|l| !cl.iter().any(|cl| cl.id == l.id));map.insert(c.1.id, l.clone());} else {map.insert(c.1.id, lecs.clone());}// let lec = &lecs.retain(|l| class_lectures().read().values().any(|cl| cl. =))// map.insert(c.1.id, lec.clone());}map}fn del_lecture(id: i32) {let lectures = get_lectures().clone();let cls = Arc::clone(&lectures);std::thread::spawn(move || {cls.write().remove(&id);save_lectures();*filtered_lectures().write() = filtering_lectures();*lec_del_states().write() = create_states();let acts = &mut *activities().write();acts.retain(|_a, b| b.lecture != id);save_activities();});}fn find_new_id() -> i32 {let len = get_lectures().read().len() as i32;for i in 1..len + 1 {if !get_lectures().read().contains_key(&i) {return i;}}len + 1}
use floem::{reactive::{create_rw_signal, create_signal},text,views::{container, text_input, v_stack},IntoView,};pub fn homepage() -> impl IntoView {let name = create_rw_signal("".to_string());container(v_stack((text_input(name),)))}
use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet},sync::{Arc, OnceLock},thread::sleep,time::Duration,};use activities::activities;use eframe::{egui::mutex::RwLock, glow::MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS};use rand::{seq::SliceRandom, thread_rng};use serde::{Deserialize, Serialize};use super::{activities::{self, partnered_act, selected_act, Activity},classes::{get_classes, validates_c_lims, validates_t_lims, Class},generate::{continued, create_total_hours, generating, multi_thread, recalc_sched, total_hours,},get_school,limitations::limitations_ui::{classes_sched, create_classes_sched, create_teachers_sched, get_class_limitations,get_teacher_limitations, schedules, teachers_limitations, teachers_scheds, update_tt,ClassLimitation, TeacherLimitation,},school_hour,teachers::{get_teachers, Teacher},};pub fn act_total_teachers() -> &'static Arc<RwLock<HashMap<i32, Vec<i32>>>> {static STOP: OnceLock<Arc<RwLock<HashMap<i32, Vec<i32>>>>> = OnceLock::new();STOP.get_or_init(|| Arc::new(RwLock::new(create_act_total_teachers())))}fn create_act_total_teachers() -> HashMap<i32, Vec<i32>> {let acts = activities().read().clone();let mut map = HashMap::new();for act in &acts {let mut v = act.1.teachers.clone();for a in &act.1.partners {if let Some(a) = acts.get(&a) {v.append(&mut a.teachers.clone())};}map.insert(act.1.id, v);}map}pub fn act_total_classes() -> &'static Arc<RwLock<HashMap<i32, Vec<i32>>>> {static STOP: OnceLock<Arc<RwLock<HashMap<i32, Vec<i32>>>>> = OnceLock::new();STOP.get_or_init(|| Arc::new(RwLock::new(create_act_total_classes())))}pub fn available_days() -> &'static Arc<RwLock<HashMap<i32, Vec<(usize, Vec<usize>)>>>> {static STOP: OnceLock<Arc<RwLock<HashMap<i32, Vec<(usize, Vec<usize>)>>>>> = OnceLock::new();STOP.get_or_init(|| Arc::new(RwLock::new(create_available_days())))}pub fn conflict_acts() -> &'static Arc<RwLock<HashSet<i32>>> {static STOP: OnceLock<Arc<RwLock<HashSet<i32>>>> = OnceLock::new();STOP.get_or_init(|| Arc::new(RwLock::new(HashSet::new())))}pub fn create_available_days() -> HashMap<i32, Vec<(usize, Vec<usize>)>> {let acts = activities().read();let mut map = HashMap::new();let hour = get_school().read().hour;for a in &*acts {let mut days = vec![];for i in 0..7 {let mut hours = vec![];for h in (0..hour).rev() {if a.1.teachers_available(h, i) && a.1.classes_available(h, i) {hours.push(h);}}if !hours.is_empty() {days.push((i, hours));}}map.insert(*a.0, days);}map}// fn started() -> &'static Arc<RwLock<bool>> {// static STOP: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();// STOP.get_or_init(|| Arc::new(RwLock::new(false)))// }fn create_act_total_classes() -> HashMap<i32, Vec<i32>> {let acts = activities().read().clone();let mut map = HashMap::new();for act in &acts {let mut v = act.1.classes.clone();for a in &act.1.partners {if let Some(a) = acts.get(&a) {v.append(&mut a.classes.clone())};}map.insert(act.1.id, v);}map}#[derive(Debug, Serialize, Deserialize, Clone)]#[serde(crate = "serde")]pub struct Schedule {pub day_id: usize,pub hour: usize,pub activity: i32,pub locked: bool,}#[derive(Debug, Serialize, Deserialize, Default, Clone)]#[serde(crate = "serde")]pub struct Params {pub hour: usize,pub depth: usize,pub depth2: usize,}#[derive(Clone, Serialize, Deserialize)]#[serde(crate = "serde")]pub struct TimetableData {pub tat: HashMap<i32, TeacherLimitation>,pub cat: HashMap<i32, ClassLimitation>,pub clean_tat: HashMap<i32, TeacherLimitation>,pub clean_cat: HashMap<i32, ClassLimitation>,pub acts: Vec<Activity>,pub teachers_acts: HashMap<i32, Vec<Activity>>,pub neighbour_acts: HashMap<i32, HashSet<i32>>,pub classes: BTreeMap<i32, Class>,pub teachers: BTreeMap<i32, Teacher>,pub timetables: HashMap<i32, Vec<Schedule>>,pub school_hour: usize,pub not_placed_acts: HashSet<i32>,}// fn cpu_nums() -> &'static Arc<RwLock<u8>> {// static STOP: OnceLock<Arc<RwLock<u8>>> = OnceLock::new();// STOP.get_or_init(|| Arc::new(RwLock::new(0)))// }impl TimetableData {// fn generate_multi(&mut self, params: &Params, act: &Activity) -> bool {// let cpus = 3;// *started().write() = false;// drop(started().write());// let ac_dt = Arc::new(RwLock::new(self.clone()));// // drop(start);// for _ in 0..cpus {// let a = act.clone();// let p = params.clone();// let ac_clone = Arc::clone(&ac_dt);// // if *cond_rec.read() {// // break;// // }// std::thread::spawn(move || {// let s = ac_clone// .write()// .recursive_put(&a.clone(), 0, &a.clone(), &p.clone());// if s {// // *started().write() = true;// // drop(started().write());// // let l = data().read().timetables.len();// // if ac_clone.read().timetables.len() > l {// *data().write() = ac_clone.read().clone();// // }// }// });// }// if self.timetables.len() < data().read().timetables.len() {// *self = data().read().clone();// return true;// }// return false;// }pub fn generate(&mut self, params: &mut Params) -> bool {// println!("{}", self.not_placed_acts.len());let mut act = self.not_placed_acts.iter();let Some(act) = act.next() else {return true;};let acts = activities().read();let Some(act) = acts.get(&act) else {return false;};*selected_act().write() = act.id;let available = self.find_timeslot(act, params);match available {Some(slots) => {self.put_act(slots.0, slots.1, act, false);return true;}None => {let mut s_c = self.clone();// if *multi_thread().read() {// if s_c.generate_multi(params, act) {// *self = s_c;// return true;// };conflict_acts().write().clear();if s_c.recursive_put(act, 0, &act, params) {*self = s_c;return true;}// let mut days = create_available_days();// days.iter_mut().for_each(|d| d.1.shuffle(&mut thread_rng()));// *available_days().write() = days;self.not_placed_acts = HashSet::from_iter(self.acts.clone().into_iter().filter(|a| !a.teachers.is_empty() && self.timetables.get(&a.id).is_none()).map(|a| a.id),);let conflict_acts = self.find_conflict_activity(act, &act, params);if conflict_acts.is_empty() {return false;}for a in &conflict_acts[0] {self.delete_activity(a);}if let Some(slots) = self.find_timeslot(act, params) {self.put_act(slots.0, slots.1, act, false);}// for a in &conflict_acts[0] {// if let Some(slots) = self.find_timeslot(a, params) {// self.put_act(slots.0, slots.1, a);// }// }return true;}}}pub fn replace_act(&mut self, day: usize, hour: usize, act_id: i32, act_hour: usize) {let tt = &mut self.timetables;let scheds = &*schedules().write().clone();let ng = self.neighbour_acts.get(&act_id);if let Some(ng) = ng {let acts = scheds.iter().filter(|s| s.day_id == day && ng.iter().any(|a| a == &s.activity)).collect::<Vec<&Schedule>>();println!("{acts:?}");for h in hour..hour + act_hour {if let Some(s) = acts.iter().find(|a| a.hour == h) {tt.remove(&s.activity);};}update_tt();}}pub fn find_timeslot(&self, act: &Activity, params: &Params) -> Option<(usize, usize)> {let days = available_days().read().clone();let days = days.get(&act.id).unwrap();if self.tat.len() == 0 {validates_c_lims();validates_t_lims();return None;}// days.shuffle(&mut thread_rng());// let hour_lim = self.school_hour - act.hour as usize + 1;for day in days {for hour in &day.1 {if self.teachers_available(act, *hour, day.0)&& self.classes_available(act, *hour, day.0)&& (//act.teachers.is_empty()act.no_limit || self.same_day_available(act, *hour, day.0, params)){// println!("{:?} {}", day, hour);return Some((day.0, *hour));}}}None}fn same_day_available(&self, act: &Activity, hour: usize, day: usize, params: &Params) -> bool {if let Some(teacher_acts) = self.teachers_acts.get(&act.id) {let mut same_day_acts = vec![];for a in teacher_acts {if !a.no_limit {if let Some(s) = self.timetables.get(&a.id) {same_day_acts.append(&mut s.clone());// return false;}}}let same_day_acts: Vec<&Schedule> =same_day_acts.iter().filter(|t| t.day_id == day).collect();if same_day_acts.len() == 0 {return true;} else if (act.hour + same_day_acts.len()) > params.hour {return false;} else {let hours = same_day_acts.iter().cloned().find(|t| hour > 0 && t.hour == (hour - 1) || t.hour == (hour + act.hour));if hours.is_some() {return true;}return false;}}true}fn classes_available(&self, act: &Activity, hour: usize, day: usize) -> bool {let mut classes_availables = vec![];let act_classes = act_total_classes().read();let Some(classes) = act_classes.get(&act.id) else {return false;};for class in classes {let class = self.cat.get(class);if let Some(c) = class {classes_availables.push(c.limitations[day].clone());}}(hour..hour + act.hour as usize).all(|h| classes_availables.iter().all(|ca| ca[h]))}fn teachers_available(&self, act: &Activity, hour: usize, day: usize) -> bool {let mut teachers_availables = vec![];let act_teachers = act_total_teachers().read();let Some(teachers) = act_teachers.get(&act.id) else {return false;};for teacher in teachers {let teacher = self.tat.get(teacher);if let Some(t) = teacher {teachers_availables.push(t.limitations[day].clone());}}(hour..hour + act.hour as usize).all(|h| teachers_availables.iter().all(|ta| ta[h]))}pub fn put_act(&mut self, day: usize, hour: usize, act: &Activity, lock: bool) {for timetable in hour..hour + act.hour as usize {let tt = Schedule {day_id: day,hour: timetable,activity: act.id,locked: lock,};let act_teachers = act_total_teachers().read();if let Some(teachers) = act_teachers.get(&act.id) {for teacher in teachers {if let Some(tat) = self.tat.get_mut(teacher) {if let Some(tat_index) = tat.limitations.get_mut(tt.day_id) {tat_index[tt.hour as usize] = false;}}}}let act_classes = act_total_classes().read();if let Some(classes) = act_classes.get(&act.id) {for class in classes {if let Some(cat) = self.cat.get_mut(class) {if let Some(cat_index) = cat.limitations.get_mut(tt.day_id) {cat_index[tt.hour] = false;}}}}if let Some(timetables) = self.timetables.get_mut(&act.id) {timetables.push(tt);} else {self.timetables.insert(act.id, vec![tt.clone()]);}}self.not_placed_acts.remove(&act.id);}pub fn delete_activity(&mut self, act: &Activity) {let tt = self.timetables.get(&act.id).unwrap();for t in tt {let act_teachers = act_total_teachers().read();if let Some(teachers) = act_teachers.get(&act.id) {for teacher in teachers {if let Some(tat) = self.tat.get_mut(teacher) {if let Some(tat_index) = tat.limitations.get_mut(t.day_id) {tat_index[t.hour as usize] = true;}}}}let act_classes = act_total_classes().read();if let Some(classes) = act_classes.get(&act.id) {for class in classes {if let Some(cat) = self.cat.get_mut(class) {if let Some(cat_index) = cat.limitations.get_mut(t.day_id) {cat_index[t.hour as usize] = true;}}}}}self.not_placed_acts.insert(act.id);self.timetables.remove(&act.id);//self.timetables.retain(|t| t.activity != act.id);}fn find_conflict_activity(&self,act: &Activity,ignores: &Activity,params: &Params,) -> Vec<Vec<Activity>> {//let now = instant::Instant::now();let mut total_act: Vec<Vec<Activity>> = Vec::new();let acts = self.neighbour_acts.get(&act.id).unwrap();let days = &*available_days().read();let days = days.get(&act.id).unwrap();for day in days {for h in &day.1 {let mut less_conflict: HashSet<Activity> = HashSet::new();for i in *h..*h + act.hour as usize {for a in acts {if let Some(s) = self.timetables.get(&a) {let sa = s.iter().find(|t| {t.day_id == day.0 && t.hour as usize == i && !t.locked// && ignores.id != t.activity});if let Some(s) = sa {if let Some(a) = activities().read().get(&s.activity) {less_conflict.insert(a.clone());};};}}}if !less_conflict.is_empty() {total_act.push(Vec::from_iter(less_conflict));}}}total_act.shuffle(&mut thread_rng());if total_act.len() >= params.depth {return total_act[..params.depth].to_vec();}total_act}pub(crate) fn recursive_put(&mut self,act: &Activity,depth: usize,ignores: &Activity,params: &Params,) -> bool {let mut conflict_acts = self.find_conflict_activity(act, ignores, params);let mut okey2 = false;let tat2 = self.tat.clone();let not_placed_acts = self.not_placed_acts.clone();let cat2 = self.cat.clone();let timetables2 = self.timetables.clone();for c_act in &mut conflict_acts {for a in &*c_act {self.delete_activity(a);}c_act.sort_by(|a, b| a.hour.cmp(&b.hour));c_act.push(act.clone());//ignore_list.append(&mut c_act.clone());let mut okey = true;for a in c_act.iter().rev() {let available = self.find_timeslot(a, params);match available {Some(slots) => {self.put_act(slots.0, slots.1, a, false);}None => {if depth < params.depth2 {let rec_result = self.recursive_put(a, depth + 1, ignores, params);if !rec_result {okey = false;break;}} else {okey = false;break;}}}}if okey {okey2 = true;//ignore_list.retain(|a3| a3.id != act.id);break;} else {self.tat = tat2.to_owned();self.cat = cat2.to_owned();self.timetables = timetables2.to_owned();self.not_placed_acts = not_placed_acts.to_owned();}}okey2}fn validate_tt(&mut self) {self.clean_cat = get_class_limitations();self.clean_tat = get_teacher_limitations();self.tat = self.clean_tat.clone();self.cat = self.clean_cat.clone();let tt_c = self.timetables.clone();self.timetables.clear();schedules().write().clear();teachers_scheds().write().clear();classes_sched().write().clear();self.not_placed_acts = self.acts.iter().map(|a| a.id.clone()).collect();for tt in &tt_c {let act = self.acts.clone().into_iter().find(|a| a.id == *tt.0).unwrap();if self.teachers_available(&act, tt.1[0].hour as usize, tt.1[0].day_id)&& self.classes_available(&act, tt.1[0].hour as usize, tt.1[0].day_id)&& (act.no_limit|| self.same_day_available(&act,tt.1[0].hour as usize,tt.1[0].day_id,&Params {hour: 2,depth: 0,depth2: 0,},)){self.put_act(tt.1[0].day_id, tt.1[0].hour as usize, &act, tt.1[0].locked);} else {// self.delete_activity(&act);}}let mut sch = vec![];self.timetables.values().for_each(|tt| sch.append(&mut tt.clone()));*schedules().write() = sch.clone();*teachers_scheds().write() = create_teachers_sched();*classes_sched().write() = create_classes_sched();*data().write() = self.clone();}}pub fn create_data() -> TimetableData {// create_acts_data();let clean_tat = get_teacher_limitations();let tat = get_teacher_limitations();let clean_cat = get_class_limitations();let cat = get_class_limitations();let mut acts = (*activities().read()).clone().values().filter(|a| partnered_act().read().get(&a.id).is_none()).map(|a| a.clone()).collect::<Vec<Activity>>();acts.shuffle(&mut thread_rng());acts.sort_by(|a, b| a.hour.cmp(&b.hour));let not_placed_acts = acts.iter().map(|a| a.id).collect();let hour = &*school_hour().read();let h = hour.parse::<usize>().unwrap_or(8);let timetables = HashMap::new();let dt = TimetableData {tat,cat,clean_cat,clean_tat,acts,teachers_acts: create_teachers_acts(),neighbour_acts: create_ng(),classes: get_classes().read().clone(),teachers: (*get_teachers().read()).clone(),timetables, //(*schedules().read()).clone(),school_hour: h,not_placed_acts,};dt}fn create_teachers_acts() -> HashMap<i32, Vec<Activity>> {let activities = (*activities().read()).clone();let acts: Vec<Activity> = activities.clone().values().map(|a| a.clone()).collect();let mut ts_acts = HashMap::new();for act in &activities {let acts: Vec<Activity> = acts.iter().cloned().filter(|a| {act.1.teachers.iter().all(|t| a.teachers.iter().any(|t2| t2 == t))&& act.1.classes.iter().all(|c| a.classes.iter().any(|c2| c2 == c))}, //&& act.lecture == a.lecture)// .map(|a| a.1).collect();ts_acts.insert(act.1.id, acts);// teachers_acts().set(ts_acts);}ts_acts}pub fn data() -> &'static Arc<RwLock<TimetableData>> {static DATA: OnceLock<Arc<RwLock<TimetableData>>> = OnceLock::new();DATA.get_or_init(|| Arc::new(RwLock::new(create_data())))}pub fn generate() {// create_data();let mut params = Params {hour: 2,depth: 6,depth2: 6,};std::thread::spawn(move || {let mut t_data = data().read().clone();t_data.validate_tt();t_data.timetables = recalc_sched();*total_hours().write() = create_total_hours();let mut sch = vec![];t_data.timetables.values().for_each(|tt| sch.append(&mut tt.clone()));*schedules().write() = sch.clone();*teachers_scheds().write() = create_teachers_sched();*classes_sched().write() = create_classes_sched();// println!("not:{:?}", t_data.not_placed_acts);loop {if !*generating().read() {break;}// let len = t_data.timetables.len();if t_data.not_placed_acts.is_empty() {// // t_data.timetables = recalc_sched();// // is_generate().set(true);let mut sch = vec![];t_data.timetables.values().for_each(|tt| sch.append(&mut tt.clone()));*schedules().write() = sch.clone();*teachers_scheds().write() = create_teachers_sched();*classes_sched().write() = create_classes_sched();*generating().write() = false;*continued().write() = false;break;}if t_data.generate(&mut params) {if t_data.timetables.len() >= data().read().timetables.len() {*data().write() = t_data.clone();} else {t_data = data().read().clone();}let mut sch = vec![];t_data.timetables.values().for_each(|tt| sch.append(&mut tt.clone()));*schedules().write() = sch.clone();*teachers_scheds().write() = create_teachers_sched();*classes_sched().write() = create_classes_sched();} else {*generating().write() = false;*continued().write() = false;break;}}});// println!("{:?}", t_data.timetables);}fn create_ng() -> HashMap<i32, HashSet<i32>> {let acts = &*activities().read().values().map(|a| a.clone()).collect::<Vec<Activity>>();let mut neighbours: HashMap<i32, HashSet<i32>> = HashMap::new();for a in &*acts {let ns = &*acts// .clone().into_iter().filter(|a2| {a2.id != a.id&& (a2.classes.iter().any(|c| a.classes.iter().any(|c2| c2 == c))|| a2.teachers.iter().any(|t| a.teachers.iter().any(|t2| t2 == t)))}).collect::<Vec<&Activity>>();let neigh_map: HashSet<i32> = HashSet::from_iter(ns.iter().map(|n| n.id));neighbours.insert(a.id, neigh_map);}neighbours}
use std::{collections::HashMap,fs::File,io::{Read, Write},path::{Path, PathBuf},sync::{Arc, OnceLock},time::Instant,};use chrono::Local;use eframe::egui::{mutex::RwLock, vec2, Button, ProgressBar, TextEdit};use egui::Context;use egui_flex::{item, Flex};use rfd::FileDialog;use super::{activities::{activities, partnered_act, selected_act},generating::{data, generate, Schedule},limitations::limitations_ui::{classes_sched, create_classes_sched, create_teachers_sched, schedules, teachers_scheds,},print_pdf::{classes::classes_prints, teachers::teachers_prints},};pub fn params_hour() -> &'static RwLock<String> {static PARAM: OnceLock<RwLock<String>> = OnceLock::new();PARAM.get_or_init(|| RwLock::new("".to_string()))}pub fn total_hours() -> &'static RwLock<f32> {static PARAM: OnceLock<RwLock<f32>> = OnceLock::new();PARAM.get_or_init(|| RwLock::new(create_total_hours()))}pub fn create_total_hours() -> f32 {activities().read().clone().values().filter(|a| partnered_act().read().get(&a.id).is_none()).fold(0., |acc, x| acc + x.hour as f32)}pub fn continued() -> &'static RwLock<bool> {static PARAM: OnceLock<RwLock<bool>> = OnceLock::new();PARAM.get_or_init(|| RwLock::new(false))}pub fn generating() -> &'static Arc<RwLock<bool>> {static GENERATING: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();GENERATING.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn multi_thread() -> &'static Arc<RwLock<bool>> {static GENERATING: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();GENERATING.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn recalc_sched() -> HashMap<i32, Vec<Schedule>> {let schdls = &*schedules().read();let mut map: HashMap<i32, Vec<Schedule>> = HashMap::new();for s in schdls {let acts = activities().read();if let Some(a) = acts.get(&s.activity) {if let Some(tt) = map.get_mut(&a.id) {tt.push(s.clone());} else {map.insert(a.id, vec![s.clone()]);};};}map}pub fn generate_ui(ui: &mut eframe::egui::Ui) {ui.vertical_centered(|ui| {ui.add_sized(vec2(400., 30.),TextEdit::singleline(&mut *params_hour().write()).hint_text("Bir öğretmenin aynı sınıfa verebileceği ders saati sayısı"),);ui.add_space(10.);ui.add(ProgressBar::new(schedules().read().len() as f32 / *total_hours().read()).desired_width(400.).desired_height(50.).text(format!(" {}/{}",schedules().read().len(),total_hours().read())).animate(*continued().read()).corner_radius(5),);ui.add_space(10.);if *generating().read() {if ui.add_sized(vec2(400., 30.), Button::new("Durdur")).clicked(){*generating().write() = false;}} else {if *continued().read() {if ui.add_sized(vec2(400., 30.), Button::new("Devam Et")).clicked(){*generating().write() = true;// *continued().write() = true;generate();}} else {if ui.add_sized(vec2(400., 30.), Button::new("Çalıştır")).clicked(){*generating().write() = true;*continued().write() = true;generate();};}}if ui.add_sized(vec2(400., 30.), Button::new("Sıfırla")).clicked(){let mut sch = vec![];data().write().timetables.retain(|_id, tt| tt.iter().any(|t| t.locked));data().read().timetables.values().for_each(|tt| sch.append(&mut tt.clone()));*schedules().write() = sch.clone();*teachers_scheds().write() = create_teachers_sched();*classes_sched().write() = create_classes_sched();*total_hours().write() = create_total_hours();}// ui.allocate_space(ui.available_size());// ui.checkbox(&mut *multi_thread().write(), "Çoklu Thread Kullan");ui.layout().horizontal_justify();Flex::horizontal().wrap(true).width_percent(1.).grow_items(1.).show(ui, |flex| {flex.add_ui(item(), |ui| {if ui.add_sized(vec2(197., 30.), Button::new("Sınıf Programını Yazdır")).clicked(){classes_prints();}if ui.add_sized(vec2(197., 30.), Button::new("Öğretmen Programını Yazdır")).clicked(){teachers_prints();}});});ui.label(format!("{:?}", *selected_act().read()));if ui.add_sized(vec2(197., 30.), Button::new("Programı Kaydet")).clicked(){save_scheds();}if ui.add_sized(vec2(197., 30.), Button::new("Programı Aç")).clicked(){open_scheds();}});}pub fn save_scheds() {std::thread::spawn(move || {let scheds = &*schedules().read();let js = serde_json::to_string(&*scheds.clone());match js {Ok(j) => {let date = Local::now();let file_name = format!("./db/scheds/{}.json", date.format("%Y-%m-%d %H:%M"));let mut f = File::create(file_name).unwrap();f.write_all(j.as_bytes()).unwrap();}Err(_) => {}}});}pub fn read_scheds(path: PathBuf) {std::thread::spawn(move || {let f = File::open(path);if let Ok(mut f) = f {let mut content: String = String::new();f.read_to_string(&mut content).unwrap();let cls: Vec<Schedule> = serde_json::from_str(content.as_str()).unwrap();let data = &mut *data().write();let tt = &mut data.timetables;for sch in &cls {tt.entry(sch.activity).and_modify(|a| a.push(sch.clone())).or_insert(vec![sch.clone()]);}*schedules().write() = cls;}});}pub fn open_scheds() {let file = FileDialog::new().set_title("Dosya Seç").set_directory("./db/scheds").pick_file();read_scheds(file.unwrap());}
use eframe::egui;use eframe::egui::mutex::RwLock;use eframe::egui::vec2;use eframe::egui::Align2;use eframe::egui::Button;use eframe::egui::Color32;use eframe::egui::Label;use eframe::egui::Link;use eframe::egui::RichText;use eframe::egui::ScrollArea;use eframe::egui::Stroke;use eframe::egui::TextEdit;// use eframe::Frame;use egui_flex::item;use egui_flex::Flex;use serde::Deserialize;use serde::Serialize;use std::collections::BTreeMap;use std::fs::File;use std::io::Read;use std::io::Write;use std::iter::zip;use std::sync::Arc;use std::sync::OnceLock;use crate::tabs::activities::activity_form::filtered_classrooms;use crate::tabs::activities::Activity;use super::activities::activities;use super::activities::activity_form::classrooms_ui::set_classrooms_filter;// use super::activities::activity_form::filtered_classes;// use super::activities::activity_form::filtering_classes;use super::activities::activity_form::filtering_classrooms;use super::activities::save_activities;// use super::limitations::limitations_ui::create_classes_sched;// use super::classrooms::get_classrooms;// use super::limitations::limitations_ui::ClassLimitation;// use super::limitations::limitations_ui::{classes_limitations, save_classes_limitations};#[derive(Clone, Serialize, Deserialize)]pub struct ClassRoom {pub id: i32,pub name: String,short_name: String,}pub fn selected_classroom() -> &'static Arc<RwLock<Option<i32>>> {static SELECTED: OnceLock<Arc<RwLock<Option<i32>>>> = OnceLock::new();SELECTED.get_or_init(|| Arc::new(RwLock::new(None)))}pub fn get_classrooms() -> &'static Arc<RwLock<BTreeMap<i32, ClassRoom>>> {static CLASSES: OnceLock<Arc<RwLock<BTreeMap<i32, ClassRoom>>>> = OnceLock::new();CLASSES.get_or_init(|| Arc::new(RwLock::new(read_classrooms())))}pub fn del_classrooms_state() -> &'static Arc<RwLock<Vec<bool>>> {static TEACHERS: OnceLock<Arc<RwLock<Vec<bool>>>> = OnceLock::new();TEACHERS.get_or_init(|| Arc::new(RwLock::new(vec![false; filtered_classrooms().read().len()])))}pub fn classrooms_acts() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Activity>>>> {static CLASSES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Activity>>>>> = OnceLock::new();CLASSES.get_or_init(|| Arc::new(RwLock::new(create_classrooms_acts())))}pub fn create_classrooms_acts() -> BTreeMap<i32, Vec<Activity>> {let acts = &*activities().read();let mut map = BTreeMap::new();for c in &*get_classrooms().read() {let mut c_acts = acts// .clone().values().filter(|a| a.classes.iter().any(|ac| ac == &c.1.id)).map(|a| a.clone()).collect::<Vec<Activity>>();c_acts.sort_by(|a, b| a.lecture.cmp(&b.lecture));map.insert(c.1.id, c_acts);}map}pub fn classroom_name() -> &'static Arc<RwLock<String>> {static NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}fn classroom_short_name() -> &'static Arc<RwLock<String>> {static SHORT_NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}pub fn set_selected_classroom(id: i32) {let class = Arc::clone(selected_classroom());std::thread::spawn(move || {*class.write() = Some(id);});}pub fn classrooms_page(ui: &mut eframe::egui::Ui) {// let mut name = get_name().lock().unwrap();ui.vertical_centered(|ui| {ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *classroom_name().write()).hint_text("Derslik Adını Gir"),);ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *classroom_short_name().write()).hint_text("Kısa Adı"),);if ui.add_sized(vec2(250., 30.), Button::new("Ekle")).clicked() {add_classroom();}});ui.separator();flex_classes_ui(ui);}fn flex_classes_ui(ui: &mut eframe::egui::Ui) {Flex::horizontal().gap(vec2(20., 20.)).wrap(true).show(ui, |flex| {let del_states = del_classrooms_state().read().clone();let del_states = del_states.iter().enumerate();for (del_state, cl) in zip(del_states, filtered_classrooms().read().iter()) {let frame = egui::Frame::default().stroke(Stroke::new(0.3, Color32::GRAY)).rounding(5.).inner_margin(5.);flex.add_flex(item().grow(1.).frame(frame),Flex::vertical().align_items_content(Align2::CENTER_TOP),|flex| {flex.add(item(), Label::new(&cl.name));if *del_state.1 {flex.add_flex(item().grow(1.),Flex::horizontal().align_items(egui_flex::FlexAlign::Center).wrap(false),|flex| {if flex.add(item(),Link::new(RichText::new("Sil").color(Color32::RED)),)// .inner.clicked(){del_classroom(cl.id, del_state.0);// del_teacher(teacher.id);};if flex.add(item().grow(1.), Link::new("Vazgeç"))// .inner.clicked(){std::thread::spawn(move || {if let Some(state) =del_classrooms_state().write().get_mut(del_state.0){*state = false;}});};},);} else if flex.add(item().grow(1.),Link::new(RichText::new("Sil").color(Color32::DARK_RED)),)// .inner.clicked(){std::thread::spawn(move || {if let Some(state) =del_classrooms_state().write().get_mut(del_state.0){*state = true;}});// del_teacher(teacher.id);}},);}});}pub fn classrooms_lists_ui(ui: &mut eframe::egui::Ui) {ScrollArea::vertical().show(ui, |ui| {ui.add_space(30.);ui.separator();ui.vertical_centered(|ui| {if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *classroom_name().write()).hint_text("Filtrele"),).changed(){set_classrooms_filter();};let mut classes = filtered_classrooms().write();for c in &mut *classes {let fill_color = if selected_classroom().read().is_some_and(|i| i == c.id) {Color32::BLUE} else {Color32::default()};let stroke_color = if selected_classroom().read().is_some_and(|i| i == c.id) {Color32::LIGHT_BLUE} else {Color32::LIGHT_GRAY};let button = egui::Frame::none().fill(fill_color).inner_margin(10.).outer_margin(2.).rounding(5.0).stroke(Stroke::new(1., stroke_color)).show(ui, |ui| {ui.label(&c.name);}).response;let button = button.interact(egui::Sense::click()).on_hover_cursor(egui::CursorIcon::PointingHand);if button.clicked() {set_selected_classroom(c.id);}}});});}fn save_classrooms() {let classes = get_classrooms().read();let js = serde_json::to_string(&*classes);match js {Ok(j) => {let mut f = File::create("./db/classrooms.json").unwrap();f.write_all(j.as_bytes()).unwrap();}Err(_) => {}}}fn read_classrooms() -> BTreeMap<i32, ClassRoom> {let f = File::open("./db/classrooms.json");if let Ok(mut f) = f {let mut content: String = String::new();f.read_to_string(&mut content).unwrap();let cls: BTreeMap<i32, ClassRoom> = serde_json::from_str(content.as_str()).unwrap();return cls;// return BTreeMap::from_iter(cls.iter().map(|c| (c.id, c.clone())));}// validates_c_lims();BTreeMap::new()}fn add_classroom() {std::thread::spawn(move || {let len = find_new_id();let class = ClassRoom {id: len,name: classroom_name().write().clone(),short_name: classroom_short_name().write().clone(),};let mut cls = get_classrooms().write();cls.insert(len, class);drop(cls);*filtered_classrooms().write() = filtering_classrooms();// let c_lims = ClassLimitation::new(len);// classes_limitations().write().insert(len, c_lims);// save_classes_limitations();save_classrooms();});}fn del_classroom(index: i32, state: usize) {let classes = get_classrooms().clone();std::thread::spawn(move || {let cls = Arc::clone(&classes);cls.write().remove(&index);*filtered_classrooms().write() = filtering_classrooms();// classes_limitations().write().remove(&index);// save_classes_limitations();let acts = &mut *activities().write();acts.iter_mut().for_each(|a| a.1.classes.retain(|c| c != &index));acts.retain(|_, a| !a.classes.is_empty());save_activities();std::thread::spawn(move || {// *classes_sched().write() = create_classes_sched();// *classes_acts().write() = create_classes_acts();// *().write() = create_teacher_acts();});del_classrooms_state().write().remove(state);});del_classrooms_acts(index);save_classrooms();}fn del_classrooms_acts(index: i32) {let acts = &mut *activities().write();if let Some(c_acts) = classrooms_acts().read().get(&index) {for a in c_acts {acts.remove(&a.id);}}classrooms_acts().write().remove(&index);save_activities();}fn find_new_id() -> i32 {let len = get_classrooms().read().len() as i32;for i in 1..len + 1 {if !get_classrooms().read().contains_key(&i) {return i;}}len + 1}// pub fn validates_c_lims() {// std::thread::spawn(move || {// let classes = &*get_classrooms().read();// // let lims = &mut *classes_limitations().write();// // lims.retain(|id, _lim| classes.contains_key(id));// // save_classes_limitations();// // validates_t_lims();// });// }// pub fn validates_t_lims() {// std::thread::spawn(move || {// let teachers = &*get_teachers().read();// let lims = &mut *teachers_limitations().write();// lims.retain(|id, _lim| teachers.contains_key(id));// save_teachers_limitations();// validates_c_acts();// });// }// fn validates_trlims() {// let teachers = &*get_classrooms().read();// let lims = &mut *classr_limitations().write();// lims.retain(|id, _lim| teachers.contains_key(id));// save_teachers_limitations();// }// pub fn validates_c_acts() {// std::thread::spawn(move || {// let classes = &*get_classes().read();// let acts = &mut *activities().write();// acts.retain(|_id, act| act.classes.iter().all(|ac| classes.contains_key(ac)));// save_activities();// validates_t_acts();// });// }// pub fn validates_t_acts() {// std::thread::spawn(move || {// let teachers = &*get_teachers().read();// let acts = &mut *activities().write();// acts.retain(|_id, act| act.teachers.iter().all(|ac| teachers.contains_key(ac)));// save_activities();// validates_l_acts();// });// }// pub fn validates_l_acts() {// std::thread::spawn(move || {// let lectures = &*get_lectures().read();// let acts = &mut *activities().write();// acts.retain(|_id, act| lectures.contains_key(&act.lecture));// save_activities();// });// }
use eframe::egui;use eframe::egui::mutex::RwLock;use eframe::egui::vec2;use eframe::egui::Align2;use eframe::egui::Button;use eframe::egui::Color32;use eframe::egui::Label;use eframe::egui::Link;use eframe::egui::RichText;use eframe::egui::ScrollArea;use eframe::egui::Stroke;use eframe::egui::TextEdit;// use eframe::Frame;use egui_flex::item;use egui_flex::Flex;use serde::Deserialize;use serde::Serialize;use std::collections::BTreeMap;use std::fs::File;use std::io::Read;use std::io::Write;use std::iter::zip;use std::sync::Arc;use std::sync::OnceLock;use crate::tabs::activities::Activity;use super::activities::activities;use super::activities::activity_form::classes_ui::set_classes_filter;use super::activities::activity_form::filtered_classes;use super::activities::activity_form::filtering_classes;use super::activities::save_activities;// use super::classrooms::get_classrooms;use super::lectures::get_lectures;use super::limitations::limitations_ui::classes_sched;// use super::limitations::limitations_ui::create_classes_sched;use super::limitations::limitations_ui::ClassLimitation;use super::limitations::limitations_ui::{classes_limitations, save_classes_limitations, save_teachers_limitations, teachers_limitations,};use super::teachers::get_teachers;#[derive(Clone, Serialize, Deserialize)]pub struct Class {pub id: i32,pub name: String,short_name: String,}pub fn selected_class() -> &'static Arc<RwLock<Option<i32>>> {static SELECTED: OnceLock<Arc<RwLock<Option<i32>>>> = OnceLock::new();SELECTED.get_or_init(|| Arc::new(RwLock::new(None)))}pub fn get_classes() -> &'static Arc<RwLock<BTreeMap<i32, Class>>> {static CLASSES: OnceLock<Arc<RwLock<BTreeMap<i32, Class>>>> = OnceLock::new();CLASSES.get_or_init(|| Arc::new(RwLock::new(read_classes())))}pub fn del_classes_state() -> &'static Arc<RwLock<Vec<bool>>> {static TEACHERS: OnceLock<Arc<RwLock<Vec<bool>>>> = OnceLock::new();TEACHERS.get_or_init(|| Arc::new(RwLock::new(vec![false; filtered_classes().read().len()])))}pub fn classes_acts() -> &'static Arc<RwLock<BTreeMap<i32, Vec<Activity>>>> {static CLASSES: OnceLock<Arc<RwLock<BTreeMap<i32, Vec<Activity>>>>> = OnceLock::new();CLASSES.get_or_init(|| Arc::new(RwLock::new(create_classes_acts())))}pub fn create_classes_acts() -> BTreeMap<i32, Vec<Activity>> {let acts = &*activities().read();let mut map = BTreeMap::new();for c in &*get_classes().read() {let mut c_acts = acts// .clone().values().filter(|a| a.classes.iter().any(|ac| ac == &c.1.id) || a.classes.is_empty()).map(|a| a.clone()).collect::<Vec<Activity>>();c_acts.sort_by(|a, b| a.lecture.cmp(&b.lecture));map.insert(c.1.id, c_acts);}map}pub fn class_name() -> &'static Arc<RwLock<String>> {static NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}fn class_short_name() -> &'static Arc<RwLock<String>> {static SHORT_NAME: OnceLock<Arc<RwLock<String>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new("".to_string())))}pub fn set_selected_class(id: i32) {let class = Arc::clone(selected_class());std::thread::spawn(move || {*class.write() = Some(id);});}fn update_class_form() -> &'static Arc<RwLock<bool>> {static SHORT_NAME: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();SHORT_NAME.get_or_init(|| Arc::new(RwLock::new(false)))}fn update_class(ui: &mut eframe::egui::Ui) {egui::Window::new("Select Class").open(&mut *update_class_form().write()).resizable([true, true]).show(ui.ctx(), |ui| {ui.add(TextEdit::singleline(&mut *class_name().write()));ui.add(TextEdit::singleline(&mut *class_short_name().write()));if ui.add(Button::new("Güncelle")).clicked() {if let Some(t) = get_classes().write().get_mut(&selected_class().read().unwrap()){t.name = class_name().read().clone();t.short_name = class_short_name().read().clone();save_classes();}}});}pub fn classes_page(ui: &mut eframe::egui::Ui) {// let mut name = get_name().lock().unwrap();ui.vertical_centered(|ui| {if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *class_name().write()).hint_text("Sınıf Adını Gir"),).changed(){set_classes_filter();};ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *class_short_name().write()).hint_text("Kısa Adı"),);if ui.add_sized(vec2(250., 30.), Button::new("Ekle")).clicked() {add_class();}});ui.separator();flex_classes_ui(ui);}fn flex_classes_ui(ui: &mut eframe::egui::Ui) {update_class(ui);Flex::horizontal().gap(vec2(20., 20.)).wrap(true).show(ui, |flex| {let del_states = del_classes_state().read().clone();let del_states = del_states.iter().enumerate();for (del_state, class) in zip(del_states, filtered_classes().read().iter()) {let frame = egui::Frame::default().stroke(Stroke::new(0.3, Color32::GRAY)).rounding(5.).inner_margin(5.);flex.add_flex(item().grow(1.).frame(frame),Flex::vertical().align_items_content(Align2::CENTER_TOP),|flex| {flex.add(item(), Label::new(&class.name));if *del_state.1 {flex.add_flex(item().grow(1.),Flex::horizontal().align_items(egui_flex::FlexAlign::Center).wrap(false),|flex| {if flex.add(item(),Link::new(RichText::new("Sil").color(Color32::RED)),)// .inner.clicked(){del_class(class.id, del_state.0);// del_teacher(teacher.id);};if flex.add(item().grow(1.), Link::new("Vazgeç"))// .inner.clicked(){std::thread::spawn(move || {if let Some(state) =del_classes_state().write().get_mut(del_state.0){*state = false;}});};},);} else {if flex.add(item().grow(1.),Link::new(RichText::new("Sil").color(Color32::DARK_RED)),)// .inner.clicked(){std::thread::spawn(move || {if let Some(state) =del_classes_state().write().get_mut(del_state.0){*state = true;}});// del_teacher(teacher.id);}if flex.add(item(), Link::new("Düzenle")).clicked() {let c = class.clone();set_selected_class(c.id);std::thread::spawn(move || {*class_name().write() = c.name.clone();*class_short_name().write() = c.short_name.clone();*update_class_form().write() = true;});}}},);}});}pub fn classes_lists_ui(ui: &mut eframe::egui::Ui) {ScrollArea::vertical().show(ui, |ui| {ui.add_space(30.);ui.separator();ui.vertical_centered(|ui| {if ui.add_sized(vec2(250., 30.),TextEdit::singleline(&mut *class_name().write()).hint_text("Filtrele"),).changed(){set_classes_filter();};let classes = &*filtered_classes().read();for c in classes {let fill_color = if selected_class().read().is_some_and(|i| i == c.id) {Color32::BLUE} else {Color32::default()};let stroke_color = if selected_class().read().is_some_and(|i| i == c.id) {Color32::LIGHT_BLUE} else {Color32::LIGHT_GRAY};let button = egui::Frame::none().fill(fill_color).inner_margin(10.).outer_margin(2.).rounding(5.0).stroke(Stroke::new(1., stroke_color)).show(ui, |ui| {ui.label(&c.name);}).response;let button = button.interact(egui::Sense::click()).on_hover_cursor(egui::CursorIcon::PointingHand);if button.clicked() {set_selected_class(c.id);}}});});}fn save_classes() {std::thread::spawn(move || {let classes = get_classes().read();let js = serde_json::to_string(&*classes);match js {Ok(j) => {let mut f = File::create("./db/classes.json").unwrap();f.write_all(j.as_bytes()).unwrap();}Err(_) => {}}});}fn read_classes() -> BTreeMap<i32, Class> {let f = File::open("./db/classes.json");if let Ok(mut f) = f {let mut content: String = String::new();f.read_to_string(&mut content).unwrap();let cls: BTreeMap<i32, Class> = serde_json::from_str(content.as_str()).unwrap();return cls;// return BTreeMap::from_iter(cls.iter().map(|c| (c.id, c.clone())));}// validates_c_lims();BTreeMap::new()}fn add_class() {let len = find_new_id();let class = Class {id: len,name: class_name().write().clone(),short_name: class_short_name().write().clone(),};std::thread::spawn(move || {get_classes().write().insert(len, class);*class_name().write() = "".to_string();*class_short_name().write() = "".to_string();set_classes_filter();let c_lims = ClassLimitation::new(len);classes_limitations().write().insert(len, c_lims);save_classes_limitations();save_classes();del_classes_state().write().push(false);});}fn del_class(index: i32, state: usize) {std::thread::spawn(move || {let classes = get_classes();classes.write().remove(&index);save_classes();// drop(cls);classes_limitations().write().remove(&index);save_classes_limitations();del_class_acts(index);*filtered_classes().write() = filtering_classes();classes_sched().write().remove(&index);classes_acts().write().remove(&index);// *().write() = create_teacher_acts();del_classes_state().write().remove(state);});}fn del_class_acts(index: i32) {// let acts = &mut *activities().write();if let Some(c_acts) = classes_acts().read().get(&index) {for a in c_acts {activities().write().remove(&a.id);}}classes_acts().write().remove(&index);save_activities();}fn find_new_id() -> i32 {let len = get_classes().read().len() as i32;for i in 1..len + 1 {if !get_classes().read().contains_key(&i) {return i;}}len + 1}pub fn validates_c_lims() {std::thread::spawn(move || {let classes = &*get_classes().read();let lims = &mut *classes_limitations().write();lims.retain(|id, _lim| classes.contains_key(id));save_classes_limitations();// validates_t_lims();});}pub fn validates_t_lims() {std::thread::spawn(move || {let teachers = &*get_teachers().read();let lims = &mut *teachers_limitations().write();lims.retain(|id, _lim| teachers.contains_key(id));save_teachers_limitations();validates_c_acts();});}// fn validates_trlims() {// let teachers = &*get_classrooms().read();// let lims = &mut *classr_limitations().write();// lims.retain(|id, _lim| teachers.contains_key(id));// save_teachers_limitations();// }pub fn validates_c_acts() {std::thread::spawn(move || {let classes = &*get_classes().read();let acts = &mut *activities().write();acts.retain(|_id, act| act.classes.iter().all(|ac| classes.contains_key(ac)));save_activities();validates_t_acts();});}pub fn validates_t_acts() {std::thread::spawn(move || {let teachers = &*get_teachers().read();let acts = &mut *activities().write();acts.retain(|_id, act| act.teachers.iter().all(|ac| teachers.contains_key(ac)));save_activities();validates_l_acts();});}pub fn validates_l_acts() {std::thread::spawn(move || {let lectures = &*get_lectures().read();let acts = &mut *activities().write();acts.retain(|_id, act| lectures.contains_key(&act.lecture));save_activities();});}
use activity_form::{act_form, add_activity, filtered_teachers, find_new_act_id, lectures_ui,teachers_ui::filter_teacher_text, update_activity_data,};use eframe::egui::{self, mutex::RwLock, vec2, Align2, Button, Color32, ComboBox, Frame, Label, RichText, Rounding,Stroke, TextEdit,};use egui::{CornerRadius, Id};use egui_extras::{Column, TableBody, TableBuilder};use egui_flex::{item, Flex};use serde::{Deserialize, Serialize};use std::{collections::{BTreeMap, HashMap},fmt::Debug,fs::File,io::{Read, Write},iter::zip,sync::{Arc, OnceLock},};use super::{classes::{classes_acts, classes_lists_ui, create_classes_acts, get_classes, selected_class},classrooms::get_classrooms,generating::{act_total_classes, act_total_teachers, data},get_page, get_school,lectures::get_lectures,limitations::limitations_ui::{classes_limitations, teachers_limitations},panel_buttons,teachers::{create_teacher_acts, get_teachers, selected_teacher, teachers_acts, teachers_list_ui,},SubPage,};pub mod activity_form;#[derive(Hash, Clone, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize)]pub struct Activity {pub id: i32,pub lecture: i32,pub classes: Vec<i32>,pub teachers: Vec<i32>,pub hour: usize,pub classroom: Vec<i32>,pub no_limit: bool,pub partners: Vec<i32>,}impl Activity {pub fn lectures_name(&self) -> String {let mut activity = "".to_string();activity.push_str(&get_lec_short_name(self.lecture));activity.push_str(" ");for p_id in &self.partners {let p_act = activities().read().clone();let p_act = p_act.get(&p_id).unwrap();activity.push_str(&get_lec_short_name(p_act.lecture));}activity.trim().to_string()}pub fn classes_name(&self) -> String {let mut activity = "".to_string();for c in &self.classes {activity.push_str(&get_class_name(*c));}activity.push_str(" ");for p_id in &self.partners {let p_act = activities().read().clone();let p_act = p_act.get(&p_id).unwrap();for c in &p_act.classes {activity.push_str(&get_class_name(*c));}}activity.trim().to_string()}pub fn teachers_short_name(&self) -> String {let mut activity = "".to_string();for t in &self.teachers {activity.push_str(&get_teacher_name(*t));}activity.push_str(" ");for p_id in &self.partners {let p_act = activities().read().clone();let p_act = p_act.get(&p_id).unwrap();for t in &p_act.teachers {activity.push_str(&get_teacher_name(*t));}}activity.trim().to_string()}pub fn teachers_name(&self) -> String {let mut activity = "".to_string();for t in &self.teachers {activity.push_str(&get_teacher_name(*t));}activity.push_str(" ");for p_id in &self.partners {let p_act = activities().read().clone();let p_act = p_act.get(&p_id).unwrap();for t in &p_act.teachers {activity.push_str(&get_teacher_name(*t));}}activity.trim().to_string()}fn classes_lims(&self) -> Option<Vec<Vec<Vec<bool>>>> {let mut c_availables = vec![];let act_classes = act_total_classes().read();let Some(classes) = act_classes.get(&self.id) else {return None;};for class in classes {let c = &*classes_limitations().read();if let Some(c) = c.get(class) {c_availables.push(c.limitations.clone());}}Some(c_availables)}pub fn classes_available(&self, hour: usize, day: usize) -> bool {let Some(lims) = self.classes_lims() else {return false;};hour + self.hour <= get_school().read().hour&& (hour..hour + self.hour as usize).all(|h| lims.iter().all(|ta| ta[day][h]))}fn teachers_lims(&self) -> Option<Vec<Vec<Vec<bool>>>> {let mut t_availables = vec![];let act_teachers = act_total_teachers().read();let Some(teachers) = act_teachers.get(&self.id) else {return None;};for teacher in teachers {let t = &*teachers_limitations().read();if let Some(t) = t.get(teacher) {t_availables.push(t.limitations.clone());}}Some(t_availables)}pub fn teachers_available(&self, hour: usize, day: usize) -> bool {let Some(lims) = self.teachers_lims() else {return false;};hour + self.hour <= get_school().read().hour&& (hour..hour + self.hour as usize).all(|h| lims.iter().all(|ta| ta[day][h]))}}impl Debug for Activity {fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {let name = format!("{}, {} {} {} - {}",self.id,self.lectures_name(),self.teachers_short_name(),self.classes_name(),self.hour);write!(f, "{}", name)}}pub fn save_activities() {std::thread::spawn(move || {let acts = &*activities().read();// let acts = acts.iter().map(|a| a.1.clone()).collect::<Vec<Activity>>();// let mut map = BTreeMap::new();// for a in acts {// map.insert(a.id, a.clone());// }let mut f = File::create("./db/activities.json").unwrap();f.write_all(serde_json::to_string(&acts).unwrap().as_bytes()).expect("Aktiviteler yazılamadı");});}fn read_activities() -> BTreeMap<i32, Activity> {let f = File::open("./db/activities.json");if let Ok(mut f) = f {let mut content: String = String::new();f.read_to_string(&mut content).unwrap();let cls: BTreeMap<i32, Activity> = serde_json::from_str(content.as_str()).unwrap();// cls.sort_by(|a, b| b.id.cmp(&a.id));return cls;}BTreeMap::new()}pub fn activities() -> &'static Arc<RwLock<BTreeMap<i32, Activity>>> {static PAGE: OnceLock<Arc<RwLock<BTreeMap<i32, Activity>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(read_activities())))}pub fn classes_acts_hours() -> &'static Arc<RwLock<BTreeMap<i32, usize>>> {static PAGE: OnceLock<Arc<RwLock<BTreeMap<i32, usize>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(create_classes_hours())))}pub fn teachers_acts_hours() -> &'static Arc<RwLock<BTreeMap<i32, usize>>> {static PAGE: OnceLock<Arc<RwLock<BTreeMap<i32, usize>>>> = OnceLock::new();PAGE.get_or_init(|| Arc::new(RwLock::new(create_teachers_hours())))}pub fn selected_act() -> &'static Arc<RwLock<i32>> {static LECTURES: OnceLock<Arc<RwLock<i32>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(-1)))}pub fn partnered_act() -> &'static Arc<RwLock<HashMap<i32, i32>>> {static LECTURES: OnceLock<Arc<RwLock<HashMap<i32, i32>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(create_partnered_act())))}pub fn create_partnered_act() -> HashMap<i32, i32> {let acts = &*activities().read();let mut map = HashMap::new();for a in acts {for id in &a.1.partners {map.insert(id.clone(), a.1.id);}}map}pub fn show_add_class_form() -> &'static Arc<RwLock<bool>> {static LECTURES: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn set_show_class_form() {let stat = *show_add_class_form().read();std::thread::spawn(move || {*show_add_class_form().write() = !stat;});}pub fn show_add_classroom_form() -> &'static Arc<RwLock<bool>> {static LECTURES: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn set_show_classroom_form() {let stat = *show_add_classroom_form().read();std::thread::spawn(move || {*show_add_classroom_form().write() = !stat;});}pub fn show_add_teacher_form() -> &'static Arc<RwLock<bool>> {static LECTURES: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn select_class_for_move() -> &'static Arc<RwLock<Option<i32>>> {static LECTURES: OnceLock<Arc<RwLock<Option<i32>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(None)))}pub fn class_name_for_move() -> &'static Arc<RwLock<String>> {static LECTURES: OnceLock<Arc<RwLock<String>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new("".to_string())))}pub fn set_show_teacher_form() {let stat = show_add_teacher_form().read().clone();std::thread::spawn(move || {*show_add_teacher_form().write() = !stat;});}pub fn show_add_partner_form() -> &'static Arc<RwLock<bool>> {static LECTURES: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn set_partner_form() {let stat = show_add_partner_form().read().clone();std::thread::spawn(move || {*show_add_partner_form().write() = !stat;});}fn create_classes_hours() -> BTreeMap<i32, usize> {let acts = &*activities().read();let mut cah = BTreeMap::new();for c in &*get_classes().read() {let c_acts = acts.iter().filter(|a| a.1.classes.iter().any(|ca| ca == &c.1.id)).fold(0, |acc, a| acc + a.1.hour);cah.insert(c.1.id, c_acts);}cah}fn create_teachers_hours() -> BTreeMap<i32, usize> {let acts = &*activities().read();let mut cah = BTreeMap::new();for c in &*get_teachers().read() {let c_acts = acts.iter().filter(|a| a.1.teachers.iter().any(|ca| ca == &c.1.id)).fold(0, |acc, a| acc + a.1.hour);cah.insert(c.1.id, c_acts);}cah}pub fn del_states() -> &'static Arc<RwLock<Vec<bool>>> {static SELECTED: OnceLock<Arc<RwLock<Vec<bool>>>> = OnceLock::new();let len = activities().read().len();SELECTED.get_or_init(|| Arc::new(RwLock::new(vec![false; len])))}pub fn get_lec_name(id: i32) -> String {let lec = get_lectures().read().clone().into_iter().find(|l| l.1.id == id);if let Some(lec) = lec {return lec.1.name;}"".to_string()}pub fn get_lec_short_name(id: i32) -> String {let lec = get_lectures().read().clone().into_iter().find(|l| l.1.id == id);if let Some(lec) = lec {return lec.1.short_name;}"".to_string()}pub fn get_classes_name(ids: &[i32]) -> String {let mut name = "".to_string();for i in ids {if let Some(c) = get_classes().read().get(i) {name.push_str(&c.name);name.push_str(" ");}}name.trim().to_string()}pub fn get_class_name(id: i32) -> String {let mut name = "".to_string();if let Some(c) = get_classes().read().get(&id) {name.push_str(&c.name);}name.trim().to_string()}pub fn get_act_classrooms_name(id: i32) -> String {let mut name = "".to_string();if let Some(c) = get_classrooms().read().get(&id) {name.push_str(&c.name);}name.trim().to_string()}pub fn get_teachers_name(ids: &[i32]) -> String {let mut name = "".to_string();for i in ids {if let Some(c) = get_teachers().read().get(i) {name.push_str(&c.short_name);name.push_str("\n");}}name.trim().to_string()}pub fn get_teacher_name(id: i32) -> String {let mut name = "".to_string();if let Some(c) = get_teachers().read().get(&id) {name.push_str(&c.short_name);}name.trim().to_string()}pub fn get_teachers_short_name(ids: &[i32]) -> String {let mut name = "".to_string();for i in ids {if let Some(c) = get_teachers().read().get(i) {name.push_str(&c.short_name);name.push_str(" ");}}name.trim().to_string()}fn del_act(id: i32) {std::thread::spawn(move || {activities().write().remove(&id);let len = activities().read().len();*del_states().write() = vec![false; len];*classes_acts().write() = create_classes_acts();*classes_acts_hours().write() = create_classes_hours();*teachers_acts().write() = create_teacher_acts();*teachers_acts_hours().write() = create_teachers_hours();save_activities();});}pub fn activities_ui(ui: &mut egui::Ui) {egui::TopBottomPanel::top("top_panel").resizable(true).default_height(60.).height_range(50.0..=350.0).show_inside(ui, |ui| {panel_buttons(ui);});home_ui(ui);}pub fn home_ui(ui: &mut egui::Ui) {egui::SidePanel::left("left_panel").resizable(true).default_width(250.0).width_range(200.0..=500.0).show_inside(ui, |ui| {if let SubPage::Teachers = *get_page().read() {teachers_list_ui(ui);} else {classes_lists_ui(ui);}});egui::CentralPanel::default().show_inside(ui, |ui| {act_form(ui);ui.horizontal(|ui| {// ui.vertical(|ui| {// ui.add_sized(vec2(250., 50.), Label::new("Atanmamış dersler"));// not_put_acts(ui);// });ui.separator();ui.vertical(|ui| {list_activities_ui(ui);});});});}pub fn list_activities_ui(ui: &mut egui::Ui) {add_more_teachers_list(ui);add_more_classes_list(ui);add_more_classroom_list(ui);add_partner_form(ui);lectures_ui::select_lecture_ui(ui);let w = ui.available_width();if ui.add_sized(vec2(w, 50.), Button::new("Ders Ata")).clicked(){*lectures_ui::show_lectures().write() = true;};match *get_page().read() {SubPage::Teachers => {if let Some(t) = *selected_teacher().read() {let text = get_teachers_name(&[t]);let hour = *teachers_acts_hours().read().get(&t).unwrap_or(&0);if let Some(acts) = teachers_acts().write().get_mut(&t) {list_acts_table(ui, acts);}ui.separator();ui.add(Label::new(RichText::new(format!("{} adlı öğretmene atanan toplam ders yükü: {} saat",text, hour)).size(18.),));}}SubPage::Classes => {if let Some(c) = *selected_class().read() {let text = get_classes_name(&[c]);let hour = *classes_acts_hours().read().get(&c).unwrap_or(&0);if let Some(acts) = classes_acts().write().get(&c) {list_acts_table(ui, acts);}ui.separator();ui.horizontal_centered(|ui| {ui.add(Label::new(RichText::new(format!("{} sınıfına atanan toplam ders yükü: {} saat",text, hour)).size(18.),));ui.add_space(50.);ComboBox::new("move_classes", "").width(50.).selected_text(&*class_name_for_move().read()).show_ui(ui, |ui| {for c in &*get_classes().read() {let cl = c.1.clone();if ui.button(&c.1.name).clicked() {std::thread::spawn(move || {*class_name_for_move().write() = cl.name.clone();*select_class_for_move().write() = Some(cl.id);});};}});if ui.add_sized(vec2(100., 30.), Button::new("Seçili Sınıfa Aktar")).clicked(){std::thread::spawn(move || {if let Some(id) = *select_class_for_move().read() {if let Some(acts) = classes_acts().read().get(&c) {for a in acts {let mut a = a.clone();a.classes.iter_mut().for_each(|c2| {if c == *c2 {*c2 = id;}});a.id = find_new_act_id();add_activity(a);}}}});}});}}};ui.separator();}pub fn list_acts_table(ui: &mut egui::Ui, acts: &Vec<Activity>) {TableBuilder::new(ui).column(Column::initial(50.).resizable(true)).column(Column::initial(250.).resizable(true)).column(Column::initial(230.).resizable(true)).column(Column::initial(100.).resizable(true)).column(Column::initial(50.).resizable(true)).column(Column::initial(50.).resizable(true)).column(Column::initial(120.).resizable(true)).column(Column::initial(120.).resizable(true)).column(Column::initial(50.).resizable(true)).striped(true).min_scrolled_height(800.).auto_shrink(false)// .column(Column::remainder()).header(50., |mut header| {header.col(|ui| {ui.heading("İd");});header.col(|ui| {ui.heading("Ders");});header.col(|ui| {ui.heading("Öğretmenler");});header.col(|ui| {ui.heading("Sınıflar");});header.col(|ui| {ui.heading("Saat");});header.col(|ui| {ui.heading("Limit");});header.col(|ui| {ui.heading("Derslik");});header.col(|ui| {ui.heading("Ortak Dersler");});}).body(|body| table_body(body, acts));}fn table_body(mut body: TableBody, acts: &Vec<Activity>) {let stats = &*del_states().read();for (index, (act, stat)) in zip(acts, stats).enumerate() {body.row(40., |mut row| {row.col(|ui| {ui.horizontal_centered(|ui| {if !*stat {if ui.button("Sil").clicked() {std::thread::spawn(move || {del_states().write()[index] = true;});};if ui.button("Çoğalt").clicked() {let mut a = act.clone();a.id = find_new_act_id();add_activity(a);};if ui.button("Böl").clicked() {let id = act.id;let hour = act.hour;std::thread::spawn(move || {let a = &mut *activities().write();let a = a.get_mut(&id);if let Some(a) = a {a.hour = hour - a.hour / 2;}}).join().unwrap();let mut a = act.clone();a.id = find_new_act_id();a.hour = a.hour / 2;add_activity(a);save_activities();// println!("a");};if index > 0 && acts[index - 1].lecture == act.lecture {if ui.button("↑").clicked() {let id = act.id;let id2 = acts[index - 1].clone();let hour = id2.hour;let id2 = id2.id;std::thread::spawn(move || {let a = &mut *activities().write();a.remove(&id2);let a = a.get_mut(&id);if let Some(a) = a {a.hour = a.hour + hour;}save_activities();update_activity_data();});// let mut a = act.clone();// a.id = find_new_act_id();// add_activity(a);};}} else {ui.horizontal_centered(|ui| {if ui.button(RichText::new("Sil").color(Color32::DARK_RED)).clicked(){del_act(act.id);};if ui.button(RichText::new("Vazgeç").color(Color32::DARK_RED)).clicked(){std::thread::spawn(move || {del_states().write()[index] = false;});};});}});});row.col(|ui| {ui.horizontal_centered(|ui| {ui.label(RichText::new(get_lec_name(act.lecture)).size(if act.id == *selected_act().read() {24.} else {16.},));});});row.col(|ui| {act_teachers_row(ui, &act);});row.col(|ui| {act_classes_row(ui, &act);});row.col(|ui| {ui.horizontal_centered(|ui| {ui.label(act.hour.to_string());});});row.col(|ui| {if ui.checkbox(&mut act.no_limit.clone(), "").changed() {change_no_limit(act.id);};});row.col(|ui| {act_classrooms_row(ui, &act);});row.col(|ui| {ui.horizontal_wrapped(|ui| {act_partners_row(ui, &act);});});});}}fn act_partners_row(ui: &mut egui::Ui, act: &Activity) {let ids = &act.partners;ui.horizontal_centered(|ui| {for id in ids {let a = activities().read().clone();let a = a.get(&id).unwrap();let fmt = format!("{}-{}",get_lec_name(a.lecture),get_teachers_name(&a.teachers));Frame::new().corner_radius(CornerRadius::same(5)).stroke(Stroke::new(0.5, Color32::GRAY)).inner_margin(2.).show(ui, |ui| {ui.label(fmt);let b = Button::new(" ✖").stroke(Stroke::NONE).fill(Color32::default());if ui.add(b).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){del_partner(act.id, a.id);};});}});if partnered_act().read().get(&act.id).is_none()&& ui.button(RichText::new(" ➕").color(Color32::LIGHT_BLUE)).clicked(){*selected_act().write() = act.id;set_partner_form();}}fn act_teachers_row(ui: &mut egui::Ui, act: &Activity) {ui.horizontal_centered(|ui| {ui.horizontal(|ui| {for t in &act.teachers {Frame::new().corner_radius(CornerRadius::same(5)).stroke(Stroke::new(0.5, Color32::GRAY)).show(ui, |ui| {ui.label(get_teacher_name(*t));let b = Button::new("✖").stroke(Stroke::NONE).fill(Color32::default());if ui.add(b).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){remove_teacher(*t, act.id);};});}});if ui.button(RichText::new(" ➕").color(Color32::LIGHT_BLUE)).clicked(){*selected_act().write() = act.id;set_show_teacher_form();}});}fn act_classes_row(ui: &mut egui::Ui, act: &Activity) {ui.horizontal_centered(|ui| {ui.horizontal(|ui| {for c in &act.classes {Frame::new().corner_radius(CornerRadius::same(5)).stroke(Stroke::new(0.5, Color32::GRAY)).show(ui, |ui| {ui.label(get_class_name(*c));let b = Button::new("✖").stroke(Stroke::NONE).fill(Color32::default());if ui.add(b).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){remove_class(*c, act.id);};});}});if ui.button(RichText::new(" ➕").color(Color32::LIGHT_BLUE)).clicked(){*selected_act().write() = act.id;*show_add_class_form().write() = true;}});}fn act_classrooms_row(ui: &mut egui::Ui, act: &Activity) {ui.horizontal_centered(|ui| {ui.horizontal(|ui| {for c in &act.classroom {Frame::new().corner_radius(CornerRadius::same(5)).stroke(Stroke::new(0.5, Color32::GRAY)).show(ui, |ui| {ui.label(get_act_classrooms_name(*c));let b = Button::new("✖").stroke(Stroke::NONE).fill(Color32::default());if ui.add(b).on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){remove_classroom(*c, act.id);};});}});if ui.button(RichText::new(" ➕").color(Color32::LIGHT_BLUE)).clicked(){*selected_act().write() = act.id;set_show_classroom_form();}});}fn add_more_classes_list(ui: &mut egui::Ui) {let id = *selected_act().read();egui::Window::new("Select Class").open(&mut *show_add_class_form().write()).show(ui.ctx(), |ui| {// classes_ui(ui);Flex::horizontal().align_items(egui_flex::FlexAlign::Stretch).align_items_content(Align2::CENTER_CENTER).gap(vec2(1., 1.0)).show(ui, |flex| {for c in &*get_classes().read() {flex.add_ui(item().grow(5.), |ui| {// let b = Button::new(&c.1.name);if ui.add_sized(vec2(50., 30.), Button::new(&c.1.name)).clicked(){add_more_class(c.1.id, id);}});}});});}fn add_more_classroom_list(ui: &mut egui::Ui) {let id = *selected_act().read();egui::Window::new("Select Classroom").open(&mut *show_add_classroom_form().write()).show(ui.ctx(), |ui| {// classes_ui(ui);Flex::horizontal().align_items(egui_flex::FlexAlign::Stretch).align_items_content(Align2::CENTER_CENTER).gap(vec2(1., 1.0)).show(ui, |flex| {for c in &*get_classrooms().read() {flex.add_ui(item().grow(5.), |ui| {// let b = Button::new(&c.1.name);if ui.add_sized(vec2(50., 30.), Button::new(&c.1.name)).clicked(){add_more_classroom(c.1.id, id);}});}});});}fn add_more_teachers_list(ui: &mut egui::Ui) {let id = *selected_act().read();egui::Window::new("Select Teacher").open(&mut *show_add_teacher_form().write()).show(ui.ctx(), |ui| {filter_teacher_text(ui);Flex::vertical()// .justify(egui_flex::FlexJustify::SpaceAround).wrap(true).gap(vec2(1., 1.0)).show(ui, |flex| {for t in &*filtered_teachers().read() {flex.add_ui(item().grow(1.), |ui| {// let b = Button::new(&c.1.name);if ui.add_sized(vec2(250., 30.), Button::new(&t.name)).clicked(){add_more_teacher(t.id, id);}});}});});}fn add_partner_form(ui: &mut egui::Ui) {let act_id = *selected_act().read();egui::Window::new("Ortak Ders Ekle").open(&mut *show_add_partner_form().write()).show(ui.ctx(), |ui| {Flex::vertical()// .justify(egui_flex::FlexJustify::SpaceAround)// .wrap(false).gap(vec2(1., 1.0)).show(ui, |flex| {flex.add_ui(item(), |ui| {if ui.add(TextEdit::singleline(&mut *filter_acts_string().write()).hint_text("Ders adı Öğretmen Sınıf sıralamasıyla filtrele"),).changed(){filtering_acts();};});for a in &*filtered_acts().read() {if a.id != act_id&& a.partners.is_empty()&& partnered_act().read().get(&a.id).is_none(){flex.add_ui(item().grow(1.), |ui| {// let b = Button::new(&c.1.name);if ui.add_sized(vec2(250., 30.), Button::new(format!("{:?}", a))).clicked(){change_partner(act_id, a.id);}});}}});});}pub fn acts_frames(ui: &mut egui::Ui, acts: &Vec<Activity>) {let tt = data().read().timetables.clone();let frame = Frame::none().stroke(Stroke::new(0.5, Color32::LIGHT_GRAY)).inner_margin(vec2(10., 10.)).rounding(5.);Flex::horizontal().gap(vec2(10., 10.)).wrap(true).show(ui, |flex| {for a in acts {if !tt.contains_key(&a.id) {flex.add_ui(item().grow(1.).frame(frame), |ui| {ui.dnd_drag_source(Id::new(a.id), a.clone(), |ui| {ui.add(Label::new(format!("{:?}", a)));});});}}});}pub fn filtered_acts() -> &'static Arc<RwLock<Vec<Activity>>> {static TEACHERS: OnceLock<Arc<RwLock<Vec<Activity>>>> = OnceLock::new();TEACHERS.get_or_init(|| Arc::new(RwLock::new(vec![])))}pub fn filter_acts_string() -> &'static Arc<RwLock<String>> {static TEACHERS: OnceLock<Arc<RwLock<String>>> = OnceLock::new();TEACHERS.get_or_init(|| Arc::new(RwLock::new("".to_string())))}pub fn filtering_acts() {let flt = &*filter_acts_string().read().clone().to_uppercase();*filtered_acts().write() = activities().read().iter().filter(|a| format!("{:?}", a.1).to_uppercase().contains(flt)).map(|a| a.1.clone()).collect();}fn change_no_limit(id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {a.no_limit = !a.no_limit;std::thread::spawn(move || {*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();save_activities();// set_show_teacher_form();});}}fn change_partner(act_id: i32, p_id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&act_id);if let Some(a) = act {a.partners.push(p_id);std::thread::spawn(move || {*partnered_act().write() = create_partnered_act();*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();save_activities();});}}fn add_more_teacher(teacher: i32, id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {if !a.teachers.iter().any(|i| i == &teacher) {a.teachers.push(teacher);}std::thread::spawn(move || {*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();save_activities();set_show_teacher_form();});}}fn del_partner(id: i32, p_id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {a.partners.retain(|a| a != &p_id);std::thread::spawn(move || {*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();*partnered_act().write() = create_partnered_act();save_activities();});}}fn remove_teacher(teacher: i32, id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {a.teachers.retain(|t| t != &teacher);std::thread::spawn(move || {*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();save_activities();});}}fn add_more_class(class: i32, id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {if !a.classes.iter().any(|i| i == &class) {a.classes.push(class);}std::thread::spawn(move || {*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();save_activities();// set_show_teacher_form();});}}fn remove_class(class: i32, id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {a.classes.retain(|c| c != &class);std::thread::spawn(move || {*classes_acts().write() = create_classes_acts();*teachers_acts().write() = create_teacher_acts();save_activities();});}}fn add_more_classroom(class: i32, id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {if !a.classroom.iter().any(|i| i == &class) {a.classroom.push(class);}std::thread::spawn(move || {// *classes_acts().write() = create_classes_acts();// *teachers_acts().write() = create_teacher_acts();save_activities();// set_show_teacher_form();});}}fn remove_classroom(cr: i32, id: i32) {let acts = &mut *activities().write();let act = acts.get_mut(&id);if let Some(a) = act {a.classroom.retain(|c| c != &cr);std::thread::spawn(move || {// *classes_acts().write() = create_classes_acts();// *teachers_acts().write() = create_teacher_acts();save_activities();});}}// fn addd(a: Activity, teacher: i32) {// // std::thread::spawn(move || {// if let Some(c_acts) = teachers_acts().write().get_mut(&teacher) {// c_acts.push(a.clone());// }// // });// }
// use std::sync::{Arc, OnceLock, RwLock};use std::sync::{Arc, OnceLock};use eframe::egui::{self, mutex::RwLock, Align2, Button, Vec2};use egui_flex::item;use crate::tabs::{classes::{classes_acts, create_classes_acts, get_classes, selected_class, Class},classrooms::{get_classrooms, ClassRoom},get_page,lectures::{get_lectures, Lecture},teachers::{create_teacher_acts, get_teachers, selected_teacher, teachers_acts, Teacher},SubPage,};use super::{activities, classes_acts_hours, create_classes_hours, create_teachers_hours, del_states,save_activities, teachers_acts_hours, Activity,};pub mod classes_ui;pub mod classrooms_ui;pub mod lectures_ui;pub mod teachers_ui;pub fn filtered_classes() -> &'static Arc<RwLock<Vec<Class>>> {static LECTURES: OnceLock<Arc<RwLock<Vec<Class>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(filtering_classes())))}pub fn show_form() -> &'static Arc<RwLock<bool>> {static LECTURES: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(false)))}pub fn filtering_classes() -> Vec<Class> {let lecs = get_classes().read().clone();let mut lecs = lecs.values().map(|v| v.clone()).collect::<Vec<Class>>();lecs.sort_by(|a, b| a.name.cmp(&b.name));lecs}pub fn filtered_lectures() -> &'static Arc<RwLock<Vec<Lecture>>> {static LECTURES: OnceLock<Arc<RwLock<Vec<Lecture>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(filtering_lectures())))}pub fn filtering_lectures() -> Vec<Lecture> {let lecs = get_lectures().read().clone();let mut lecs = lecs.values().map(|v| v.clone()).collect::<Vec<Lecture>>();lecs.sort_by(|a, b| a.name.to_uppercase().cmp(&b.name.to_uppercase()));lecs}pub fn filtered_teachers() -> &'static Arc<RwLock<Vec<Teacher>>> {static LECTURES: OnceLock<Arc<RwLock<Vec<Teacher>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(filtering_teachers().clone())))}pub fn filtering_teachers() -> Vec<Teacher> {let teachers = get_teachers().read().clone();let mut teachers = teachers.values().map(|v| v.clone()).collect::<Vec<Teacher>>();teachers.sort_by(|a, b| a.name.to_uppercase().cmp(&b.name.to_uppercase()));teachers}pub fn filtered_classrooms() -> &'static Arc<RwLock<Vec<ClassRoom>>> {static LECTURES: OnceLock<Arc<RwLock<Vec<ClassRoom>>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new(filtering_classrooms().clone())))}pub fn filtering_classrooms() -> Vec<ClassRoom> {let classrooms = get_classrooms().read().clone();let mut classrooms = classrooms.values().map(|v| v.clone()).collect::<Vec<ClassRoom>>();classrooms.sort_by(|a, b| a.name.to_uppercase().cmp(&b.name.to_uppercase()));classrooms}pub fn act_lec() -> &'static Arc<RwLock<Option<Lecture>>> {static ACT_LEC: OnceLock<Arc<RwLock<Option<Lecture>>>> = OnceLock::new();ACT_LEC.get_or_init(|| Arc::new(RwLock::new(None)))}pub fn act_classes() -> &'static Arc<RwLock<Vec<Class>>> {static ACT_CLASSES: OnceLock<Arc<RwLock<Vec<Class>>>> = OnceLock::new();ACT_CLASSES.get_or_init(|| Arc::new(RwLock::new(vec![])))}pub fn act_hours() -> &'static Arc<RwLock<String>> {static ACT_HOURS: OnceLock<Arc<RwLock<String>>> = OnceLock::new();ACT_HOURS.get_or_init(|| Arc::new(RwLock::new("".to_string())))}pub fn act_teachers() -> &'static Arc<RwLock<Vec<Teacher>>> {static ACT_TEACHER: OnceLock<Arc<RwLock<Vec<Teacher>>>> = OnceLock::new();ACT_TEACHER.get_or_init(|| Arc::new(RwLock::new(vec![])))}pub fn act_classrooms() -> &'static Arc<RwLock<Vec<ClassRoom>>> {static ACT_TEACHER: OnceLock<Arc<RwLock<Vec<ClassRoom>>>> = OnceLock::new();ACT_TEACHER.get_or_init(|| Arc::new(RwLock::new(vec![])))}pub fn add_act() {let lec = &*act_lec().read();if let Some(lec) = lec {let hours = act_hours().read().clone();let tchr = if let SubPage::Teachers = *get_page().read() {if let Some(t) = *selected_teacher().read() {vec![t]} else {vec![]}} else {vec![]};let cls = if let SubPage::Classes = *get_page().read() {if let Some(c) = *selected_class().read() {vec![c]} else {vec![]}} else {vec![]};hours.split(" ").for_each(|h| {let Ok(h) = h.parse::<usize>() else {return ();};let lec = lec.clone();let act = Activity {id: find_new_act_id(),lecture: lec.id,classes: cls.clone(),teachers: tchr.clone(),hour: h,classroom: vec![],no_limit: false,partners: vec![],};add_activity(act);// update_activity_data();});}}pub fn add_activity(act: Activity) {std::thread::spawn(move || {let acts = activities();acts.write().insert(act.id, act.clone());update_activity_data();save_activities();}).join().unwrap();}pub fn update_activity_data() {std::thread::spawn(move || {*teachers_acts().write() = create_teacher_acts();*classes_acts().write() = create_classes_acts();*teachers_acts_hours().write() = create_teachers_hours();*classes_acts_hours().write() = create_classes_hours();let len = activities().read().len();*del_states().write() = vec![false; len];});}pub fn find_new_act_id() -> i32 {let len = activities().read().len() as i32;for i in 1..len + 1 {if !activities().read().contains_key(&i) {return i;}}len + 1}pub fn act_form(ui: &mut egui::Ui) {egui::Window::new("My Window").open(&mut *show_form().write())// .default_size(vec2(500., 500.)).show(ui.ctx(), |ui| {ui.vertical_centered(|ui| {egui_flex::Flex::horizontal()// .gap(Vec2::new(5., 5.)).grow_items(1.0).align_content(egui_flex::FlexAlignContent::SpaceBetween).align_items_content(Align2::CENTER_TOP)// .wrap(true).gap(Vec2::new(1., 1.)).show(ui, |flex| {flex.add_ui(item().basis(500.), |ui| {lectures_ui::select_lecture_ui(ui);});flex.add_ui(item().basis(500.), |ui| {classes_ui::select_classes_ui(ui);});flex.add_ui(item().basis(500.), |_ui| {// teachers_ui::select_teachers_ui(ui);});});if ui.add_sized(Vec2::new(500., 30.), Button::new("Dosyaya Kaydet")).clicked(){save_activities();};});});}
use eframe::egui::{self, TextEdit};use crate::tabs::teachers::{get_teachers, teacher_name};use super::filtered_teachers;pub fn set_teachers_filter() {std::thread::spawn(move || {let f = teacher_name().read();let f = &*f.to_uppercase();let tchrs = get_teachers().read().clone().into_iter().filter(|l| l.1.name.to_uppercase().contains(&f));*filtered_teachers().write() = tchrs.map(|t| t.1.clone()).collect();filtered_teachers().write().sort_by(|a, b| a.name.cmp(&b.name));});}pub fn filter_teacher_text(ui: &mut egui::Ui) {ui.label("Öğretmen(ler)i Seçin ");let text = ui.add(TextEdit::singleline(&mut *teacher_name().write()).hint_text("Öğretmenleri Filtrele"));text.request_focus();if text.changed() {set_teachers_filter()};}// pub fn select_teachers_ui(ui: &mut egui::Ui) {// ui.vertical(|ui| {// Frame::none()// .stroke(Stroke::new(1., Color32::BLACK))// .rounding(1.)// .inner_margin(10.0)// .outer_margin(10.0)// .show(ui, |ui| {// ui.label("Öğretmen(ler)i Seçin ");// if ui// .add(// TextEdit::singleline(&mut *teacher_name().write())// .hint_text("Öğretmenleri Filtrele"),// )// .changed()// {// set_teachers_filter()// };// ui.add_space(5.);// Flex::horizontal()// .wrap(true)// // .justify(egui_flex::FlexJustify::Center)// .align_items(egui_flex::FlexAlign::Center)// .show(ui, |flex| {// let teachers = filtered_teachers().read();// for teacher in &*teachers {// let is_selected =// act_teachers().read().iter().any(|i| teacher.id == i.id);// let _stroke = Stroke::new(// if is_selected { 1.0 } else { 0.5 },// if is_selected {// Color32::BLUE// } else {// Color32::GRAY// },// );// // let frame = egui::Frame::default()// // .stroke(stroke)// // .rounding(5.)// // .inner_margin(5.);// flex.add_flex(// item(),// Flex::horizontal().align_items_content(Align2::CENTER_TOP),// |flex| {// // let sel_lec = act_lec();// if flex// .add_ui(item(), |ui| {// ui.add_sized(// Vec2::new(30., 15.),// Label::new(&teacher.name),// )// })// .inner// .on_hover_cursor(egui::CursorIcon::PointingHand)// .clicked()// {// select_teacher(teacher.clone(), is_selected);// };// },// );// }// });// });// });// }// fn select_teacher(teacher: Teacher, del: bool) {// let teachers = act_teachers();// // let selected_class = selected_class().read().unwrap();// std::thread::spawn(move || {// // let class = class.clone();// let teachers: Arc<RwLock<Vec<Teacher>>> = Arc::clone(teachers);// if del {// teachers.write().retain(|t| &t.id != &teacher.id);// } else {// teachers.write().push(teacher.clone());// }// });// }
use std::sync::{Arc, OnceLock};use eframe::egui::{self, mutex::RwLock, vec2, Button, Color32, Label, Sense, Stroke, TextEdit};use egui_flex::{item, Flex};use crate::tabs::lectures::{get_lectures, lec_name};use super::{act_hours, act_lec, add_act, filtered_lectures};pub fn show_lectures() -> &'static Arc<RwLock<bool>> {static ACT_LEC: OnceLock<Arc<RwLock<bool>>> = OnceLock::new();ACT_LEC.get_or_init(|| Arc::new(RwLock::new(false)))}// fn filter_lectures() -> &'static Arc<RwLock<String>> {// static LECTURES: OnceLock<Arc<RwLock<String>>> = OnceLock::new();// LECTURES.get_or_init(|| Arc::new(RwLock::new("".to_string())))// }pub fn set_lecture_filter() {std::thread::spawn(move || {let f = &*lec_name().read();let f = &*f.replace('i', "İ")// .replace('ı', "I")// .replace('I', "ı")// .replace('İ', "i").to_uppercase();let lecs = get_lectures().read().clone().into_iter().filter(|l| l.1.name.replace('i', "İ").to_uppercase().contains(&f));*filtered_lectures().write() = lecs.map(|l| l.1).collect();});}pub fn select_lecture_ui(ui: &mut egui::Ui) {egui::Window::new("Lectures Ui").open(&mut *show_lectures().write()).show(ui.ctx(), |ui| {ui.label("Ders Seçin");if ui.add(TextEdit::singleline(&mut *lec_name().write()).hint_text("Dersleri Filtrele")).changed(){set_lecture_filter();};ui.add_space(5.);ui.layout().with_main_wrap(true);Flex::horizontal().wrap(true).align_items(egui_flex::FlexAlign::Start)// .justify(egui_flex::FlexJustify::Center)// .align_items(egui_flex::FlexAlign::Center).width_percent(0.3).show(ui, |flex| {for lec in &filtered_lectures().read()[..] {let sel_lec = act_lec();let mut color = Color32::GRAY;let mut stroke = 0.3;if let Some(l) = &*sel_lec.read() {if &l.id == &lec.id {color = Color32::BLUE;stroke = 1.0;}}let frame = egui::Frame::default().stroke(Stroke::new(stroke, color)).rounding(5.).inner_margin(5.);if flex.add_widget(item().frame(frame),Label::new(&lec.name).sense(Sense::click()),).inner.on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){let lec = lec.clone();std::thread::spawn(move || {let lec_clone = Arc::clone(sel_lec);*lec_clone.write() = Some(lec.clone());});}}});ui.add_sized(vec2(500., 30.),TextEdit::singleline(&mut *act_hours().write()).hint_text("Ders bloklarını gir"),);if ui.add_sized(vec2(500., 30.), Button::new("Ekle")).clicked() {add_act();};});}
use std::sync::Arc;use eframe::egui::{self, mutex::RwLock, Align2, Color32, Frame, Label, Stroke, TextEdit, Vec2};use egui_flex::{item, Flex};use crate::tabs::classrooms::{classroom_name, get_classrooms, ClassRoom};use super::{act_classrooms, filtered_classrooms};pub fn set_classrooms_filter() {let f = classroom_name().read();let f = &*f.to_uppercase();let tchrs = get_classrooms().read().clone().into_iter().filter(|l| l.1.name.to_uppercase().contains(&f));*filtered_classrooms().write() = tchrs.map(|t| t.1.clone()).collect();filtered_classrooms().write().sort_by(|a, b| a.name.cmp(&b.name));}pub fn select_classroom_ui(ui: &mut egui::Ui) {ui.vertical(|ui| {Frame::none().stroke(Stroke::new(1., Color32::BLACK)).rounding(1.).inner_margin(10.0).outer_margin(10.0).show(ui, |ui| {ui.label("Derslik(ler)i Seçin ");if ui.add(TextEdit::singleline(&mut *classroom_name().write()).hint_text("Derslikleri Filtrele"),).changed(){set_classrooms_filter()};ui.add_space(5.);Flex::horizontal().wrap(true)// .justify(egui_flex::FlexJustify::Center).align_items(egui_flex::FlexAlign::Center).show(ui, |flex| {let teachers = filtered_classrooms().read();for teacher in &*teachers {let is_selected =act_classrooms().read().iter().any(|i| teacher.id == i.id);let stroke = Stroke::new(if is_selected { 1.0 } else { 0.5 },if is_selected {Color32::BLUE} else {Color32::GRAY},);let _frame = egui::Frame::default().stroke(stroke).rounding(5.).inner_margin(5.);flex.add_flex(item(),Flex::horizontal().align_items_content(Align2::CENTER_TOP),// frame,|flex| {// let sel_lec = act_lec();if flex.add_ui(item(), |ui| {ui.add_sized(Vec2::new(30., 15.),Label::new(&teacher.name),)}).inner.on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){select_classroom(teacher.clone(), is_selected);};},);}});});});}fn select_classroom(cl: ClassRoom, del: bool) {let teachers = act_classrooms();// let selected_class = selected_class().read().unwrap();std::thread::spawn(move || {// let class = class.clone();let classrooms: Arc<RwLock<Vec<ClassRoom>>> = Arc::clone(teachers);if del {classrooms.write().retain(|t| &t.id != &cl.id);} else {classrooms.write().push(cl.clone());}});}
use std::sync::{Arc, OnceLock};use eframe::egui::{self, mutex::RwLock, Align2, Color32, Frame, Label, Stroke, TextEdit, Vec2};use egui_flex::{item, Flex};use crate::tabs::classes::{class_name, get_classes, Class};use super::{act_classes, filtered_classes};fn filter_classes() -> &'static Arc<RwLock<String>> {static LECTURES: OnceLock<Arc<RwLock<String>>> = OnceLock::new();LECTURES.get_or_init(|| Arc::new(RwLock::new("".to_string())))}// fn filter_range() -> &'static Arc<RwLock<usize>> {// let lec_len = filtered_classes().read().len();// let range = if lec_len >= 10 { lec_len } else { 5 };// static RANGE: OnceLock<Arc<RwLock<usize>>> = OnceLock::new();// RANGE.get_or_init(|| Arc::new(RwLock::new(range)))// }pub fn set_classes_filter() {let f = class_name().read();let f = &*f.to_uppercase();let lecs = get_classes().read().clone().into_iter().filter(|l| l.1.name.to_uppercase().contains(&f));*filtered_classes().write() = lecs.map(|c| c.1.clone()).collect();}pub fn select_classes_ui(ui: &mut egui::Ui) {ui.vertical(|ui| {Frame::none().stroke(Stroke::new(1., Color32::BLACK)).rounding(1.).inner_margin(10.0).outer_margin(10.0).show(ui, |ui| {ui.label("Sınıfları Seçin");if ui.add(TextEdit::singleline(&mut *filter_classes().write()).hint_text("Sınıfları Filtrele"),).changed(){set_classes_filter()};ui.add_space(5.);Flex::horizontal().wrap(true)// .justify(egui_flex::FlexJustify::Center).align_items(egui_flex::FlexAlign::Center).show(ui, |flex| {let classes = filtered_classes().read();// for class in &classes[..*filter_range().read()] {for class in &classes[..] {let is_selected = act_classes().read().iter().any(|i| class.id == i.id);let stroke = Stroke::new(if is_selected { 1.0 } else { 0.5 },if is_selected {Color32::BLUE} else {Color32::GRAY},);let _frame = egui::Frame::default().stroke(stroke).rounding(5.).inner_margin(5.);flex.add_flex(item(),Flex::horizontal().align_items_content(Align2::CENTER_TOP),// frame,|flex| {// let sel_lec = act_lec();if flex.add_ui(item(), |ui| {ui.add_sized([30., 15.], Label::new(&class.name))}).inner.on_hover_cursor(egui::CursorIcon::PointingHand).clicked(){select_class(class.clone(), is_selected);};},);}// if *filter_range().read() != filtered_classes().read().len() {// show_more(flex);// }});});});}// fn show_more(flex: &mut FlexInstance) {// let frame = egui::Frame::default()// .stroke(Stroke::new(0.5, Color32::GRAY))// .rounding(5.)// .inner_margin(5.);// flex.add_flex_frame(// item(),// Flex::horizontal().align_items_content(Align2::CENTER_TOP),// frame,// |flex| {// // let sel_lec = act_lec();// if flex// .add_simple(item(), |ui| {// ui.add_sized(Vec2::new(30., 15.), Label::new("...Tümünü Göster"))// })// .inner// .on_hover_cursor(egui::CursorIcon::PointingHand)// .clicked()// {// let l = filtered_classes().read().len();// // *filter_range().write() = l;// };// },// );// }fn select_class(class: Class, del: bool) {let clss = act_classes();// let selected_class = selected_teacher().read().unwrap();std::thread::spawn(move || {// let class = class.clone();let clss = Arc::clone(clss);if del {clss.write().retain(|c| &c.id != &class.id);} else {clss.write().push(class.clone());}});}