diff --git a/LangLang/BusinessLogic/UseCases/CourseService.cs b/LangLang/BusinessLogic/UseCases/CourseService.cs index dcce6f0..d179d87 100644 --- a/LangLang/BusinessLogic/UseCases/CourseService.cs +++ b/LangLang/BusinessLogic/UseCases/CourseService.cs @@ -36,6 +36,11 @@ public void Update(Course course) _courses.Update(course); } + public List GetLanguages() + { + return GetAll().Select(course => course.Language).Distinct().ToList(); + } + public void Delete(int id) { _courses.Delete(id); diff --git a/LangLang/BusinessLogic/UseCases/DirectorService.cs b/LangLang/BusinessLogic/UseCases/DirectorService.cs index 31a0d96..6a9e1e0 100644 --- a/LangLang/BusinessLogic/UseCases/DirectorService.cs +++ b/LangLang/BusinessLogic/UseCases/DirectorService.cs @@ -16,5 +16,10 @@ public List GetAll() { return _directors.GetAll(); } + + public Director Get(int id) + { + return _directors.Get(id); + } } } diff --git a/LangLang/BusinessLogic/UseCases/ExamSlotService.cs b/LangLang/BusinessLogic/UseCases/ExamSlotService.cs index 99284a1..bb36a70 100644 --- a/LangLang/BusinessLogic/UseCases/ExamSlotService.cs +++ b/LangLang/BusinessLogic/UseCases/ExamSlotService.cs @@ -48,7 +48,14 @@ public List GetGraded() return gradedExams; } - + // returns all graded exams for a specified language + public List GetByLanguage(string language) + { + var exams = GetAll().Where(exam => exam.Language.Equals(language, StringComparison.OrdinalIgnoreCase)).ToList(); + var resultService = new ExamResultService(); + + return exams.Where(exam => !resultService.GetByExam(exam).All(result => result.Outcome != ExamOutcome.NotGraded && exam.ResultsGenerated)).ToList(); + } //function takes examslot and adds it to dictionary of examslots //function saves changes and returns if adding was successful diff --git a/LangLang/BusinessLogic/UseCases/PdfService.cs b/LangLang/BusinessLogic/UseCases/PdfService.cs index 07ffc8b..4e602a8 100644 --- a/LangLang/BusinessLogic/UseCases/PdfService.cs +++ b/LangLang/BusinessLogic/UseCases/PdfService.cs @@ -3,6 +3,7 @@ using Syncfusion.Pdf; using System.IO; using System; +using System.Collections.Generic; namespace LangLang.BusinessLogic.UseCases { @@ -10,33 +11,43 @@ public class PdfService { public static PdfDocument GeneratePdf(T data, string[] headers, string reportName, Func DataToGrid) { - { - using (PdfDocument document = new PdfDocument()) - { - document.PageSettings.Size = PdfPageSize.A4; + PdfDocument document = new PdfDocument(); + + document.PageSettings.Size = PdfPageSize.A4; + + PdfPage page = document.Pages.Add(); + PdfGraphics graphics = page.Graphics; - PdfPage page = document.Pages.Add(); - PdfGraphics graphics = page.Graphics; + PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 20); + graphics.DrawString(reportName, font, PdfBrushes.Black, new Syncfusion.Drawing.PointF(0, 0)); - PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 20); - graphics.DrawString(reportName, font, PdfBrushes.Black, new Syncfusion.Drawing.PointF(0, 0)); + PdfGrid pdfGrid = DataToGrid(data); + pdfGrid.Headers.Add(1); - PdfGrid pdfGrid = DataToGrid(data); - pdfGrid.Headers.Add(1); + PdfGridRow pdfGridHeader = pdfGrid.Headers[0]; + for (int i = 0; i < headers.Length; i++) + pdfGridHeader.Cells[i].Value = headers[i]; - PdfGridRow pdfGridHeader = pdfGrid.Headers[0]; - for (int i = 0; i < headers.Length; i++) - pdfGridHeader.Cells[i].Value = headers[i]; + pdfGrid.Draw(page, new Syncfusion.Drawing.PointF(0, 40)); - pdfGrid.Draw(page, new Syncfusion.Drawing.PointF(0, 40)); + string fileName = $"{reportName}.pdf"; + using (FileStream stream = new FileStream(fileName, FileMode.Create)) + document.Save(stream); - string fileName = $"{reportName}.pdf"; - using (FileStream stream = new FileStream(fileName, FileMode.Create)) - document.Save(stream); + return document; + } - return document; - } + public PdfGrid DataToGrid(Dictionary data) + { + PdfGrid grid = new PdfGrid(); + grid.Columns.Add(2); + foreach (var item in data) + { + PdfGridRow row = grid.Rows.Add(); + row.Cells[0].Value = item.Key; + row.Cells[1].Value = item.Value.ToString(); } + return grid; } } diff --git a/LangLang/BusinessLogic/UseCases/ReportService.cs b/LangLang/BusinessLogic/UseCases/ReportService.cs index 822086e..dad98fc 100644 --- a/LangLang/BusinessLogic/UseCases/ReportService.cs +++ b/LangLang/BusinessLogic/UseCases/ReportService.cs @@ -1,8 +1,9 @@ - +using System; using LangLang.Configuration; using LangLang.Domain.Enums; using LangLang.Domain.Models; using System.Collections.Generic; +using System.Linq; namespace LangLang.BusinessLogic.UseCases { @@ -105,5 +106,68 @@ public Dictionary> GetAverageGradesOfCourses() } return averages; } + + + // methods below for average penalty points + public Dictionary GetAveragePenaltyPoints() + { + var points = new Dictionary(); + var courseService = new CourseService(); + foreach (string language in courseService.GetLanguages()) + points[language] = GetAveragePenaltyPoints(language); + return points; + } + + private double GetAveragePenaltyPoints(string language) + { + int points = 0; + + var courseService = new CourseService(); + var penaltyPointService = new PenaltyPointService(); + + var courses = courseService.GetAll().Where(course => course.Language.Equals(language, StringComparison.OrdinalIgnoreCase)); + foreach (Course course in courses) + points += penaltyPointService.GetByCourse(course).Count; + + return points; + } + + // methods below for average points + public Dictionary GetAveragePoints() + { + var courseService = new CourseService(); + var points = new Dictionary(); + foreach (string language in courseService.GetLanguages()) + points[language] = GetAveragePoints(language); + return points; + } + + private double GetAveragePoints(string language) + { + var examService = new ExamSlotService(); + var resultService = new ExamResultService(); + var exams = examService.GetByLanguage(language); + + int total = 0; + int examinees = 0; + + foreach (ExamSlot exam in exams) + { + var results = resultService.GetByExam(exam); + total += GetTotalPoints(results); + examinees += results.Count; + } + + return examinees == 0 ? 0 : (double)total / examinees; + } + + private int GetTotalPoints(List results) + { + int total = 0; + foreach (ExamResult result in results) + total += result.ListeningPoints + result.ReadingPoints + result.SpeakingPoints + result.WritingPoints; + return total; + } + } } diff --git a/LangLang/BusinessLogic/UseCases/SenderService.cs b/LangLang/BusinessLogic/UseCases/SenderService.cs index 2e96c81..cab8127 100644 --- a/LangLang/BusinessLogic/UseCases/SenderService.cs +++ b/LangLang/BusinessLogic/UseCases/SenderService.cs @@ -1,4 +1,4 @@ -using LangLang.Composition; +using LangLang.Composition; using LangLang.Configuration; using LangLang.Domain.Enums; using LangLang.Domain.Models; @@ -10,6 +10,7 @@ namespace LangLang.BusinessLogic.UseCases { public class SenderService { + private IEmailRepository _emails; public SenderService() @@ -37,6 +38,29 @@ public void SendResults(ExamSlot exam) } } + public void SendAveragePoints(Director director) + { + var reportService = new ReportService(); + var pdfService = new PdfService(); + + var reportName = "Average points per language"; + var headers = new string[] { "Language", "Average points" }; + + var document = PdfService.GeneratePdf>(reportService.GetAveragePoints(), headers, reportName, data => pdfService.DataToGrid(data)); + EmailService.SendEmail(director.Profile.Email, reportName, "", document); + } + + public void SendAveragePenaltyPoints(Director director) + { + var reportService = new ReportService(); + var pdfService = new PdfService(); + + var reportName = "Average penalty points per language"; + var headers = new string[] { "Language", "Average penalty points" }; + + var document = PdfService.GeneratePdf>(reportService.GetAveragePenaltyPoints(), headers, reportName, data => pdfService.DataToGrid(data)); + EmailService.SendEmail(director.Profile.Email, reportName, "", document); + } public void SendGratitudeMail(Course course, List students) { foreach (var student in students) @@ -123,6 +147,5 @@ private string GetGratitudeSubject() { return _emails.GetContent("gratitudeSubject"); } - } } diff --git a/LangLang/Domain/RepositoryInterfaces/IDirectorRepository.cs b/LangLang/Domain/RepositoryInterfaces/IDirectorRepository.cs index fc4c14a..2f47be1 100644 --- a/LangLang/Domain/RepositoryInterfaces/IDirectorRepository.cs +++ b/LangLang/Domain/RepositoryInterfaces/IDirectorRepository.cs @@ -5,6 +5,7 @@ namespace LangLang.Domain.RepositoryInterfaces { public interface IDirectorRepository{ public List GetAll(); + public Director Get(int id); public void Save(); public Dictionary Load(); } diff --git a/LangLang/Repositories/DirectorRepository.cs b/LangLang/Repositories/DirectorRepository.cs index d3f59c4..57dbfe3 100644 --- a/LangLang/Repositories/DirectorRepository.cs +++ b/LangLang/Repositories/DirectorRepository.cs @@ -20,6 +20,11 @@ public List GetAll() return _directors.Values.ToList(); } + public Director Get(int id) + { + return _directors[id]; + } + // NOTE: The methods below are temporary until connecting to the database. public void Save() diff --git a/LangLang/WPF/ViewModels/DirectorViewModels/ReportsViewModel.cs b/LangLang/WPF/ViewModels/DirectorViewModels/ReportsViewModel.cs index ac606dc..c951099 100644 --- a/LangLang/WPF/ViewModels/DirectorViewModels/ReportsViewModel.cs +++ b/LangLang/WPF/ViewModels/DirectorViewModels/ReportsViewModel.cs @@ -1,8 +1,34 @@ -namespace LangLang.WPF.ViewModels.DirectorViewModels +using LangLang.BusinessLogic.UseCases; +using LangLang.Domain.Models; +using System.Windows; + +namespace LangLang.WPF.ViewModels.DirectorViewModels { public class ReportsViewModel { - public ReportsViewModel() {} - + private Director _director; + public ReportsViewModel(Director director) { + _director = director; + } + + public void SentAveragePoints() + { + var senderService = new SenderService(); + senderService.SendAveragePoints(_director); + ShowSuccess(); + } + + public void SentAveragePenaltyPoints() + { + var senderService = new SenderService(); + senderService.SendAveragePenaltyPoints(_director); + ShowSuccess(); + } + + private void ShowSuccess() + { + MessageBox.Show("Successfully completed!", "Notification", MessageBoxButton.OK, MessageBoxImage.Information); + } + } } diff --git a/LangLang/WPF/ViewModels/MainWindowViewModel.cs b/LangLang/WPF/ViewModels/MainWindowViewModel.cs index 3a72339..c897355 100644 --- a/LangLang/WPF/ViewModels/MainWindowViewModel.cs +++ b/LangLang/WPF/ViewModels/MainWindowViewModel.cs @@ -87,7 +87,7 @@ private void OpenAppropriateWindow(Profile profile) } else if (profile.Role == UserType.Director) { - DirectorWindow directorWindow = new(); + DirectorWindow directorWindow = new(profile); directorWindow.Show(); } } diff --git a/LangLang/WPF/Views/DirectorView/DirectorWindow.xaml.cs b/LangLang/WPF/Views/DirectorView/DirectorWindow.xaml.cs index c87baea..dad9fe3 100644 --- a/LangLang/WPF/Views/DirectorView/DirectorWindow.xaml.cs +++ b/LangLang/WPF/Views/DirectorView/DirectorWindow.xaml.cs @@ -1,16 +1,20 @@ using System.Windows; using System.Windows.Controls; +using LangLang.BusinessLogic.UseCases; +using LangLang.Domain.Models; using LangLang.WPF.Views.DirectorView.Tabs; namespace LangLang.WPF.Views.DirectorView { public partial class DirectorWindow : Window { - - public DirectorWindow() + public Director CurrentlyLoggedIn { get; set; } + public DirectorWindow(Profile currentlyLoggedIn) { InitializeComponent(); DataContext = this; + var directorService = new DirectorService(); + CurrentlyLoggedIn = directorService.Get(currentlyLoggedIn.Id); GenerateTabs(); } @@ -22,7 +26,7 @@ private void GenerateTabs() AddTab("Results Sending", resultsTab); var gradedCoursesTab = new GradedCourses(); AddTab("Graded courses", gradedCoursesTab); - var reportsTab = new Reports(); + var reportsTab = new Reports(CurrentlyLoggedIn); AddTab("Reports", reportsTab); var coursesTab = new CoursesReview(); AddTab("Courses", coursesTab); diff --git a/LangLang/WPF/Views/DirectorView/Tabs/Reports.xaml b/LangLang/WPF/Views/DirectorView/Tabs/Reports.xaml index 4375b49..29601f1 100644 --- a/LangLang/WPF/Views/DirectorView/Tabs/Reports.xaml +++ b/LangLang/WPF/Views/DirectorView/Tabs/Reports.xaml @@ -22,8 +22,8 @@