optirs_core/research/
mod.rs

1// Academic Research Collaboration Framework
2//
3// This module provides comprehensive tools for academic researchers to collaborate,
4// reproduce experiments, track results, and generate publications using SciRS2 optimizers.
5//
6// # Features
7//
8// - **Experiment Tracking**: Comprehensive tracking of experimental configurations and results
9// - **Reproducibility**: Tools to ensure experiments can be reproduced exactly
10// - **Publication Generation**: Automated LaTeX/Markdown report generation
11// - **Citation Management**: BibTeX integration and automated citations
12// - **Benchmark Suite**: Standardized academic benchmarks
13// - **Collaboration Tools**: Multi-researcher project management
14// - **Conference Integration**: Templates and tools for academic conferences
15// - **Peer Review Support**: Anonymous review and feedback systems
16//
17// # Examples
18//
19// ## Setting up a Research Project
20//
21// ```rust
22// use optirs_core::research::*;
23//
24// let project = ResearchProject::new("Neural Optimizer Comparison")
25//     .add_researcher("Dr. Alice Smith", "alice@university.edu")
26//     .add_researcher("Prof. Bob Johnson", "bob@institute.org")
27//     .set_research_area(ResearchArea::MachineLearning)
28//     .set_funding_source("NSF Grant #12345")
29//     .enable_reproducibility_tracking(true);
30//
31// // Setup experiment tracking
32// let experiment = Experiment::new("Adam vs SGD Comparison")
33//     .set_hypothesis("Adam converges faster than SGD on deep networks")
34//     .add_optimizer_config("adam", adam_config)
35//     .add_optimizer_config("sgd", sgd_config)
36//     .set_dataset("CIFAR-10")
37//     .set_metrics(vec!["accuracy", "convergence_rate", "training_time"]);
38// ```
39
40pub mod benchmarks;
41pub mod citations;
42pub mod collaboration;
43pub mod conferences;
44pub mod datasets;
45pub mod experiments;
46pub mod funding;
47pub mod peer_review;
48pub mod publications;
49pub mod reproducibility;
50
51// Re-exports for convenience - using selective exports to avoid conflicts
52pub use benchmarks::*;
53pub use collaboration::*;
54pub use datasets::*;
55pub use funding::*;
56
57// Selective re-exports for experiments to avoid conflicts
58pub use experiments::{
59    CpuInfo, DataType, DatasetInfo, DatasetStatistics, EarlyStoppingConfig, Experiment,
60    ExperimentConfig, ExperimentMetadata, ExperimentNote, ExperimentResult, ExperimentRunner,
61    ExperimentStatus, ExperimentTimeline, GpuInfo, HardwareConfig as ExperimentHardwareConfig,
62    MemoryAllocationStrategy, MemoryConfig, NoteType, OptimizationMode, ParallelConfig,
63    PreprocessingStep, ReproducibilityChecklist, ReproducibilityInfo, ResourceMonitor,
64    ResourceUsage, RunStatus, SystemInfo as ExperimentSystemInfo, TrainingHistory,
65};
66
67// Selective re-exports for reproducibility to avoid conflicts
68pub use reproducibility::{
69    CpuSpec, Dependency, Difference, DifferenceCategory, EnvironmentSnapshot, GpuSpec,
70    HardwareConfig as ReproducibilityHardwareConfig, IssueSeverity, IssueType, MemorySpec,
71    ReproducibilityChecklist as ReproducibilityChecklistType, ReproducibilityConfig,
72    ReproducibilityIssue, ReproducibilityManager, ReproducibilityReport, ReproducibilityStorage,
73    SimilarityMetrics, StorageSpec, SystemInfo as ReproducibilitySystemInfo, VerificationResult,
74    VerificationStatus,
75};
76
77// Selective re-exports to avoid conflicts
78// Citations module exports
79pub use citations::{
80    Author as CitationAuthor, BibliographyFormat, Citation, CitationManager,
81    CitationStyle as CitationStyleType, DateFormat, FormattingRules, InTextFormat, NameFormat,
82    PublicationType as CitationPublicationType, PunctuationRules, SortDirection, SortField,
83    SortingRules, TitleFormat,
84};
85
86// Publications module exports
87pub use publications::{
88    Affiliation, Author as PublicationAuthor, AuthorPosition, BibTeXEntry, Bibliography,
89    CitationStyle as PublicationCitationStyle, Decision, Figure, FigureType, ManuscriptSection,
90    Publication, PublicationStatus, PublicationType as PublicationTypeEnum,
91    Review as PublicationReview, ReviewRecommendation as PublicationReviewRecommendation,
92    ReviewerInfo, SectionType, SubmissionRecord, SubmissionStatus, Table, Venue, VenueType,
93};
94
95// Peer review module exports
96pub use peer_review::{
97    MetaReview, PeerReview, PeerReviewSystem, ReviewAssignment, ReviewCriterion, ReviewDiscussion,
98    ReviewQualityAssessment, ReviewQualityMetric, ReviewRecommendation as PeerReviewRecommendation,
99    ReviewSession, ReviewSessionStatus, ReviewStatus, ReviewType, Reviewer, ReviewerAvailability,
100    ReviewerHistory, ReviewerPreferences, ReviewerQualityMetrics, WrittenReview,
101};
102
103// Conferences module exports
104pub use conferences::{
105    Conference, ConferenceDates, ConferenceManager, DeadlineType, Review as ConferenceReview,
106    ReviewFormat, ReviewProcess, ReviewRecommendation as ConferenceReviewRecommendation,
107    Submission, SubmissionStatus as ConferenceSubmissionStatus,
108};
109
110use crate::error::{OptimError, Result};
111use chrono::{DateTime, Utc};
112use serde::{Deserialize, Serialize};
113use std::collections::HashMap;
114use std::path::PathBuf;
115
116/// Main research project coordinator
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct ResearchProject {
119    /// Project name
120    pub name: String,
121    /// Project description
122    pub description: String,
123    /// Research area classification
124    pub research_area: ResearchArea,
125    /// Project status
126    pub status: ProjectStatus,
127    /// List of researchers
128    pub researchers: Vec<Researcher>,
129    /// Funding information
130    pub funding: Option<FundingInfo>,
131    /// Project timeline
132    pub timeline: ProjectTimeline,
133    /// Experiments in this project
134    pub experiments: Vec<Experiment>,
135    /// Publications related to this project
136    pub publications: Vec<Publication>,
137    /// Project settings
138    pub settings: ProjectSettings,
139    /// Creation timestamp
140    pub created_at: DateTime<Utc>,
141    /// Last modified timestamp
142    pub modified_at: DateTime<Utc>,
143}
144
145/// Research area classifications
146#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
147pub enum ResearchArea {
148    /// Machine Learning
149    MachineLearning,
150    /// Deep Learning
151    DeepLearning,
152    /// Optimization Theory
153    OptimizationTheory,
154    /// Computer Vision
155    ComputerVision,
156    /// Natural Language Processing
157    NaturalLanguageProcessing,
158    /// Reinforcement Learning
159    ReinforcementLearning,
160    /// Scientific Computing
161    ScientificComputing,
162    /// High Performance Computing
163    HighPerformanceComputing,
164    /// Distributed Systems
165    DistributedSystems,
166    /// Quantum Computing
167    QuantumComputing,
168    /// Interdisciplinary
169    Interdisciplinary,
170    /// Other with description
171    Other(String),
172}
173
174/// Project status
175#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
176pub enum ProjectStatus {
177    /// Planning phase
178    Planning,
179    /// Active research
180    Active,
181    /// Data collection
182    DataCollection,
183    /// Analysis phase
184    Analysis,
185    /// Writing phase
186    Writing,
187    /// Under review
188    UnderReview,
189    /// Published
190    Published,
191    /// Completed
192    Completed,
193    /// On hold
194    OnHold,
195    /// Cancelled
196    Cancelled,
197}
198
199/// Researcher information
200#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct Researcher {
202    /// Full name
203    pub name: String,
204    /// Email address
205    pub email: String,
206    /// Institution/affiliation
207    pub affiliation: String,
208    /// ORCID identifier
209    pub orcid: Option<String>,
210    /// Role in the project
211    pub role: ResearcherRole,
212    /// Expertise areas
213    pub expertise: Vec<String>,
214    /// Contact information
215    pub contact_info: ContactInfo,
216}
217
218/// Researcher roles
219#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
220pub enum ResearcherRole {
221    /// Principal Investigator
222    PrincipalInvestigator,
223    /// Co-Principal Investigator
224    CoPrincipalInvestigator,
225    /// Senior Researcher
226    SeniorResearcher,
227    /// Postdoc
228    Postdoc,
229    /// PhD Student
230    PhDStudent,
231    /// Masters Student
232    MastersStudent,
233    /// Undergraduate Student
234    UndergraduateStudent,
235    /// Research Assistant
236    ResearchAssistant,
237    /// Collaborator
238    Collaborator,
239    /// Advisor
240    Advisor,
241}
242
243/// Contact information
244#[derive(Debug, Clone, Serialize, Deserialize, Default)]
245pub struct ContactInfo {
246    /// Phone number
247    pub phone: Option<String>,
248    /// Office address
249    pub office_address: Option<String>,
250    /// Mailing address
251    pub mailing_address: Option<String>,
252    /// Website/homepage
253    pub website: Option<String>,
254    /// Social media handles
255    pub social_media: HashMap<String, String>,
256}
257
258/// Funding information
259#[derive(Debug, Clone, Serialize, Deserialize)]
260pub struct FundingInfo {
261    /// Funding agency
262    pub agency: String,
263    /// Grant number
264    pub grant_number: String,
265    /// Grant title
266    pub grant_title: String,
267    /// Total amount
268    pub amount: Option<f64>,
269    /// Currency
270    pub currency: String,
271    /// Start date
272    pub start_date: DateTime<Utc>,
273    /// End date
274    pub end_date: DateTime<Utc>,
275    /// Award date
276    pub award_date: Option<DateTime<Utc>>,
277}
278
279/// Project timeline
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct ProjectTimeline {
282    /// Project start date
283    pub start_date: DateTime<Utc>,
284    /// Planned end date
285    pub planned_end_date: DateTime<Utc>,
286    /// Actual end date
287    pub actual_end_date: Option<DateTime<Utc>>,
288    /// Key milestones
289    pub milestones: Vec<Milestone>,
290    /// Progress updates
291    pub progress_updates: Vec<ProgressUpdate>,
292}
293
294/// Project milestone
295#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct Milestone {
297    /// Milestone name
298    pub name: String,
299    /// Description
300    pub description: String,
301    /// Planned date
302    pub planned_date: DateTime<Utc>,
303    /// Actual completion date
304    pub completed_date: Option<DateTime<Utc>>,
305    /// Status
306    pub status: MilestoneStatus,
307    /// Deliverables
308    pub deliverables: Vec<String>,
309}
310
311/// Milestone status
312#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
313pub enum MilestoneStatus {
314    /// Not started
315    NotStarted,
316    /// In progress
317    InProgress,
318    /// Completed
319    Completed,
320    /// Delayed
321    Delayed,
322    /// Cancelled
323    Cancelled,
324}
325
326/// Progress update
327#[derive(Debug, Clone, Serialize, Deserialize)]
328pub struct ProgressUpdate {
329    /// Update timestamp
330    pub timestamp: DateTime<Utc>,
331    /// Update author
332    pub author: String,
333    /// Progress summary
334    pub summary: String,
335    /// Detailed description
336    pub description: String,
337    /// Percentage completion
338    pub completion_percentage: f64,
339    /// Next steps
340    pub next_steps: Vec<String>,
341    /// Challenges encountered
342    pub challenges: Vec<String>,
343}
344
345/// Project settings
346#[derive(Debug, Clone, Serialize, Deserialize)]
347pub struct ProjectSettings {
348    /// Enable reproducibility tracking
349    pub enable_reproducibility: bool,
350    /// Enable automatic backups
351    pub enable_backups: bool,
352    /// Backup frequency (hours)
353    pub backup_frequency_hours: u32,
354    /// Data retention policy (days)
355    pub data_retention_days: u32,
356    /// Privacy settings
357    pub privacy_settings: PrivacySettings,
358    /// Collaboration settings
359    pub collaboration_settings: CollaborationSettings,
360    /// Publication settings
361    pub publication_settings: PublicationSettings,
362}
363
364/// Privacy settings
365#[derive(Debug, Clone, Serialize, Deserialize)]
366pub struct PrivacySettings {
367    /// Project visibility
368    pub visibility: ProjectVisibility,
369    /// Data sharing policy
370    pub data_sharing: DataSharingPolicy,
371    /// Enable anonymous access
372    pub allow_anonymous_access: bool,
373    /// Embargo period (days)
374    pub embargo_period_days: Option<u32>,
375}
376
377/// Project visibility
378#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
379pub enum ProjectVisibility {
380    /// Public - visible to everyone
381    Public,
382    /// Internal - visible to institution members
383    Internal,
384    /// Private - visible to project members only
385    Private,
386    /// Restricted - invitation only
387    Restricted,
388}
389
390/// Data sharing policy
391#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
392pub enum DataSharingPolicy {
393    /// Open data - freely available
394    Open,
395    /// On request - available upon request
396    OnRequest,
397    /// Restricted - limited sharing
398    Restricted,
399    /// No sharing - private data only
400    NoSharing,
401}
402
403/// Collaboration settings
404#[derive(Debug, Clone, Serialize, Deserialize)]
405pub struct CollaborationSettings {
406    /// Enable real-time collaboration
407    pub enable_realtime_collaboration: bool,
408    /// Enable version control
409    pub enable_version_control: bool,
410    /// Enable peer review
411    pub enable_peer_review: bool,
412    /// Enable discussion forums
413    pub enable_discussions: bool,
414    /// Maximum collaborators
415    pub max_collaborators: Option<u32>,
416}
417
418/// Publication settings
419#[derive(Debug, Clone, Serialize, Deserialize)]
420pub struct PublicationSettings {
421    /// Default publication format
422    pub default_format: PublicationFormat,
423    /// Enable automatic citations
424    pub enable_auto_citations: bool,
425    /// Citation style
426    pub citation_style: CitationStyle,
427    /// Enable preprint submission
428    pub enable_preprints: bool,
429    /// Target conferences/journals
430    pub target_venues: Vec<String>,
431}
432
433/// Publication formats
434#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
435pub enum PublicationFormat {
436    /// LaTeX
437    LaTeX,
438    /// Markdown
439    Markdown,
440    /// HTML
441    Html,
442    /// PDF
443    Pdf,
444    /// Word Document
445    Word,
446    /// Jupyter Notebook
447    Notebook,
448}
449
450/// Citation styles
451#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
452pub enum CitationStyle {
453    /// APA style
454    APA,
455    /// IEEE style
456    IEEE,
457    /// ACM style
458    ACM,
459    /// Nature style
460    Nature,
461    /// Science style
462    Science,
463    /// Custom BibTeX style
464    Custom(String),
465}
466
467/// Research project manager
468#[derive(Debug)]
469pub struct ResearchProjectManager {
470    /// Active projects
471    projects: HashMap<String, ResearchProject>,
472    /// Project storage directory
473    storage_dir: PathBuf,
474    /// Manager settings
475    settings: ManagerSettings,
476}
477
478/// Manager settings
479#[derive(Debug, Clone, Serialize, Deserialize)]
480pub struct ManagerSettings {
481    /// Default project template
482    pub default_template: Option<String>,
483    /// Auto-save frequency (minutes)
484    pub auto_save_frequency: u32,
485    /// Enable cloud backup
486    pub enable_cloud_backup: bool,
487    /// Cloud storage provider
488    pub cloud_provider: Option<String>,
489    /// Notification settings
490    pub notifications: NotificationSettings,
491}
492
493/// Notification settings
494#[derive(Debug, Clone, Serialize, Deserialize)]
495pub struct NotificationSettings {
496    /// Email notifications enabled
497    pub email_enabled: bool,
498    /// Slack notifications enabled
499    pub slack_enabled: bool,
500    /// Webhook URL for notifications
501    pub webhook_url: Option<String>,
502    /// Notification frequency
503    pub frequency: NotificationFrequency,
504}
505
506/// Notification frequency
507#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
508pub enum NotificationFrequency {
509    /// Real-time notifications
510    Realtime,
511    /// Daily digest
512    Daily,
513    /// Weekly digest
514    Weekly,
515    /// Monthly digest
516    Monthly,
517    /// On important events only
518    Important,
519    /// Disabled
520    Disabled,
521}
522
523impl ResearchProject {
524    /// Create a new research project
525    pub fn new(name: &str) -> Self {
526        let now = Utc::now();
527        Self {
528            name: name.to_string(),
529            description: String::new(),
530            research_area: ResearchArea::MachineLearning,
531            status: ProjectStatus::Planning,
532            researchers: Vec::new(),
533            funding: None,
534            timeline: ProjectTimeline {
535                start_date: now,
536                planned_end_date: now + chrono::Duration::days(365),
537                actual_end_date: None,
538                milestones: Vec::new(),
539                progress_updates: Vec::new(),
540            },
541            experiments: Vec::new(),
542            publications: Vec::new(),
543            settings: ProjectSettings::default(),
544            created_at: now,
545            modified_at: now,
546        }
547    }
548
549    /// Set project description
550    pub fn description(mut self, description: &str) -> Self {
551        self.description = description.to_string();
552        self.modified_at = Utc::now();
553        self
554    }
555
556    /// Set research area
557    pub fn research_area(mut self, area: ResearchArea) -> Self {
558        self.research_area = area;
559        self.modified_at = Utc::now();
560        self
561    }
562
563    /// Add a researcher to the project
564    pub fn add_researcher(mut self, name: &str, email: &str) -> Self {
565        let researcher = Researcher {
566            name: name.to_string(),
567            email: email.to_string(),
568            affiliation: String::new(),
569            orcid: None,
570            role: ResearcherRole::Collaborator,
571            expertise: Vec::new(),
572            contact_info: ContactInfo::default(),
573        };
574        self.researchers.push(researcher);
575        self.modified_at = Utc::now();
576        self
577    }
578
579    /// Set funding information
580    pub fn funding(mut self, funding: FundingInfo) -> Self {
581        self.funding = Some(funding);
582        self.modified_at = Utc::now();
583        self
584    }
585
586    /// Enable reproducibility tracking
587    pub fn enable_reproducibility(mut self, enabled: bool) -> Self {
588        self.settings.enable_reproducibility = enabled;
589        self.modified_at = Utc::now();
590        self
591    }
592
593    /// Add an experiment to the project
594    pub fn add_experiment(&mut self, experiment: Experiment) -> Result<()> {
595        self.experiments.push(experiment);
596        self.modified_at = Utc::now();
597        Ok(())
598    }
599
600    /// Add a publication to the project
601    pub fn add_publication(&mut self, publication: Publication) -> Result<()> {
602        self.publications.push(publication);
603        self.modified_at = Utc::now();
604        Ok(())
605    }
606
607    /// Generate project summary report
608    pub fn generate_summary_report(&self) -> String {
609        let mut report = String::new();
610
611        report.push_str(&format!("# {}\n\n", self.name));
612        report.push_str(&format!("**Description**: {}\n\n", self.description));
613        report.push_str(&format!("**Research Area**: {:?}\n\n", self.research_area));
614        report.push_str(&format!("**Status**: {:?}\n\n", self.status));
615
616        report.push_str("## Researchers\n\n");
617        for researcher in &self.researchers {
618            report.push_str(&format!(
619                "- {} ({}) - {:?}\n",
620                researcher.name, researcher.email, researcher.role
621            ));
622        }
623
624        if let Some(funding) = &self.funding {
625            report.push_str("\n## Funding\n\n");
626            report.push_str(&format!("**Agency**: {}\n", funding.agency));
627            report.push_str(&format!("**Grant**: {}\n", funding.grant_number));
628            if let Some(amount) = funding.amount {
629                report.push_str(&format!("**Amount**: {:.2} {}\n", amount, funding.currency));
630            }
631        }
632
633        report.push_str("\n## Progress\n\n");
634        report.push_str(&format!("**Experiments**: {}\n", self.experiments.len()));
635        report.push_str(&format!("**Publications**: {}\n", self.publications.len()));
636        report.push_str(&format!(
637            "**Milestones**: {}\n",
638            self.timeline.milestones.len()
639        ));
640
641        report
642    }
643}
644
645impl Default for ProjectSettings {
646    fn default() -> Self {
647        Self {
648            enable_reproducibility: true,
649            enable_backups: true,
650            backup_frequency_hours: 24,
651            data_retention_days: 1095, // 3 years
652            privacy_settings: PrivacySettings::default(),
653            collaboration_settings: CollaborationSettings::default(),
654            publication_settings: PublicationSettings::default(),
655        }
656    }
657}
658
659impl Default for PrivacySettings {
660    fn default() -> Self {
661        Self {
662            visibility: ProjectVisibility::Private,
663            data_sharing: DataSharingPolicy::OnRequest,
664            allow_anonymous_access: false,
665            embargo_period_days: Some(365),
666        }
667    }
668}
669
670impl Default for CollaborationSettings {
671    fn default() -> Self {
672        Self {
673            enable_realtime_collaboration: true,
674            enable_version_control: true,
675            enable_peer_review: true,
676            enable_discussions: true,
677            max_collaborators: Some(20),
678        }
679    }
680}
681
682impl Default for PublicationSettings {
683    fn default() -> Self {
684        Self {
685            default_format: PublicationFormat::LaTeX,
686            enable_auto_citations: true,
687            citation_style: CitationStyle::IEEE,
688            enable_preprints: true,
689            target_venues: Vec::new(),
690        }
691    }
692}
693
694impl ResearchProjectManager {
695    /// Create a new research project manager
696    pub fn new(storage_dir: PathBuf) -> Result<Self> {
697        std::fs::create_dir_all(&storage_dir)?;
698
699        Ok(Self {
700            projects: HashMap::new(),
701            storage_dir,
702            settings: ManagerSettings::default(),
703        })
704    }
705
706    /// Create a new research project
707    pub fn create_project(&mut self, name: &str) -> Result<&mut ResearchProject> {
708        if self.projects.contains_key(name) {
709            return Err(OptimError::InvalidConfig(format!(
710                "Project '{}' already exists",
711                name
712            )));
713        }
714
715        let project = ResearchProject::new(name);
716        self.projects.insert(name.to_string(), project);
717        self.save_project(name)?;
718
719        Ok(self.projects.get_mut(name).unwrap())
720    }
721
722    /// Load an existing project
723    pub fn load_project(&mut self, name: &str) -> Result<&mut ResearchProject> {
724        if !self.projects.contains_key(name) {
725            let project_file = self.storage_dir.join(format!("{}.json", name));
726            if project_file.exists() {
727                let content = std::fs::read_to_string(&project_file)?;
728                let project: ResearchProject = serde_json::from_str(&content)?;
729                self.projects.insert(name.to_string(), project);
730            } else {
731                return Err(OptimError::InvalidConfig(format!(
732                    "Project '{}' not found",
733                    name
734                )));
735            }
736        }
737
738        Ok(self.projects.get_mut(name).unwrap())
739    }
740
741    /// Save a project to disk
742    pub fn save_project(&self, name: &str) -> Result<()> {
743        if let Some(project) = self.projects.get(name) {
744            let project_file = self.storage_dir.join(format!("{}.json", name));
745            let content = serde_json::to_string_pretty(project)?;
746            std::fs::write(&project_file, content)?;
747        }
748
749        Ok(())
750    }
751
752    /// List all projects
753    pub fn list_projects(&self) -> Vec<&str> {
754        self.projects.keys().map(|s| s.as_str()).collect()
755    }
756
757    /// Delete a project
758    pub fn delete_project(&mut self, name: &str) -> Result<()> {
759        self.projects.remove(name);
760        let project_file = self.storage_dir.join(format!("{}.json", name));
761        if project_file.exists() {
762            std::fs::remove_file(&project_file)?;
763        }
764
765        Ok(())
766    }
767}
768
769impl Default for ManagerSettings {
770    fn default() -> Self {
771        Self {
772            default_template: None,
773            auto_save_frequency: 15, // 15 minutes
774            enable_cloud_backup: false,
775            cloud_provider: None,
776            notifications: NotificationSettings::default(),
777        }
778    }
779}
780
781impl Default for NotificationSettings {
782    fn default() -> Self {
783        Self {
784            email_enabled: true,
785            slack_enabled: false,
786            webhook_url: None,
787            frequency: NotificationFrequency::Daily,
788        }
789    }
790}
791
792#[cfg(test)]
793mod tests {
794    use super::*;
795    use tempfile::tempdir;
796
797    #[test]
798    fn test_research_project_creation() {
799        let project = ResearchProject::new("Test Project")
800            .description("A test research project")
801            .research_area(ResearchArea::MachineLearning)
802            .add_researcher("Dr. Test", "test@example.com")
803            .enable_reproducibility(true);
804
805        assert_eq!(project.name, "Test Project");
806        assert_eq!(project.description, "A test research project");
807        assert_eq!(project.research_area, ResearchArea::MachineLearning);
808        assert_eq!(project.researchers.len(), 1);
809        assert!(project.settings.enable_reproducibility);
810    }
811
812    #[test]
813    fn test_project_manager() {
814        let temp_dir = tempdir().unwrap();
815        let mut manager = ResearchProjectManager::new(temp_dir.path().to_path_buf()).unwrap();
816
817        let project = manager.create_project("Test Project").unwrap();
818        project.description = "Test description".to_string();
819
820        manager.save_project("Test Project").unwrap();
821
822        let projects = manager.list_projects();
823        assert!(projects.contains(&"Test Project"));
824
825        manager.delete_project("Test Project").unwrap();
826        let projects = manager.list_projects();
827        assert!(!projects.contains(&"Test Project"));
828    }
829}