Skip to content

Commit

Permalink
Merge pull request #434 from kzi-nastava/feat/add-reports-for-average…
Browse files Browse the repository at this point in the history
…-points

[feat] Implement functionality for director so he can receive reports average number of points and penalty points) via email.
  • Loading branch information
anasinik authored May 27, 2024
2 parents d87decf + adfa3c9 commit 96ff622
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 34 deletions.
5 changes: 5 additions & 0 deletions LangLang/BusinessLogic/UseCases/CourseService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public void Update(Course course)
_courses.Update(course);
}

public List<string> GetLanguages()
{
return GetAll().Select(course => course.Language).Distinct().ToList();
}

public void Delete(int id)
{
_courses.Delete(id);
Expand Down
5 changes: 5 additions & 0 deletions LangLang/BusinessLogic/UseCases/DirectorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@ public List<Director> GetAll()
{
return _directors.GetAll();
}

public Director Get(int id)
{
return _directors.Get(id);
}
}
}
9 changes: 8 additions & 1 deletion LangLang/BusinessLogic/UseCases/ExamSlotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ public List<ExamSlot> GetGraded()
return gradedExams;
}


// returns all graded exams for a specified language
public List<ExamSlot> 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
Expand Down
49 changes: 30 additions & 19 deletions LangLang/BusinessLogic/UseCases/PdfService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,51 @@
using Syncfusion.Pdf;
using System.IO;
using System;
using System.Collections.Generic;

namespace LangLang.BusinessLogic.UseCases
{
public class PdfService
{
public static PdfDocument GeneratePdf<T>(T data, string[] headers, string reportName, Func<T, PdfGrid> 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<string, double> 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;
}

}
Expand Down
66 changes: 65 additions & 1 deletion LangLang/BusinessLogic/UseCases/ReportService.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -105,5 +106,68 @@ public Dictionary<Course, List<double>> GetAverageGradesOfCourses()
}
return averages;
}


// methods below for average penalty points
public Dictionary<string, double> GetAveragePenaltyPoints()
{
var points = new Dictionary<string, double>();
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<string, double> GetAveragePoints()
{
var courseService = new CourseService();
var points = new Dictionary<string, double>();
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<ExamResult> results)
{
int total = 0;
foreach (ExamResult result in results)
total += result.ListeningPoints + result.ReadingPoints + result.SpeakingPoints + result.WritingPoints;
return total;
}

}
}
27 changes: 25 additions & 2 deletions LangLang/BusinessLogic/UseCases/SenderService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using LangLang.Composition;
using LangLang.Composition;
using LangLang.Configuration;
using LangLang.Domain.Enums;
using LangLang.Domain.Models;
Expand All @@ -10,6 +10,7 @@ namespace LangLang.BusinessLogic.UseCases
{
public class SenderService
{

private IEmailRepository _emails;

public SenderService()
Expand Down Expand Up @@ -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<Dictionary<string, double>>(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<Dictionary<string, double>>(reportService.GetAveragePenaltyPoints(), headers, reportName, data => pdfService.DataToGrid(data));
EmailService.SendEmail(director.Profile.Email, reportName, "", document);
}
public void SendGratitudeMail(Course course, List<Student> students)
{
foreach (var student in students)
Expand Down Expand Up @@ -123,6 +147,5 @@ private string GetGratitudeSubject()
{
return _emails.GetContent("gratitudeSubject");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace LangLang.Domain.RepositoryInterfaces
{
public interface IDirectorRepository{
public List<Director> GetAll();
public Director Get(int id);
public void Save();
public Dictionary<int, Director> Load();
}
Expand Down
5 changes: 5 additions & 0 deletions LangLang/Repositories/DirectorRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public List<Director> 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()
Expand Down
32 changes: 29 additions & 3 deletions LangLang/WPF/ViewModels/DirectorViewModels/ReportsViewModel.cs
Original file line number Diff line number Diff line change
@@ -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);
}

}
}
2 changes: 1 addition & 1 deletion LangLang/WPF/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private void OpenAppropriateWindow(Profile profile)
}
else if (profile.Role == UserType.Director)
{
DirectorWindow directorWindow = new();
DirectorWindow directorWindow = new(profile);
directorWindow.Show();
}
}
Expand Down
10 changes: 7 additions & 3 deletions LangLang/WPF/Views/DirectorView/DirectorWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -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();
}

Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions LangLang/WPF/Views/DirectorView/Tabs/Reports.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

<Button Grid.Row="0" Content="The number of penalty points received in each course in the past year" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
<Button Grid.Row="1" Content="The average grade of students who had n points (0 ≤ n ≤ 3)" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
<Button Grid.Row="2" Content="Number of average points per language" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
<Button Grid.Row="3" Content="Number of average penalty points per language" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
<Button Grid.Row="2" Content="Number of average points per language" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" Click="AveragePoints_Click" />
<Button Grid.Row="3" Content="Number of average penalty points per language" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" Click="AveragePenaltyPoints_Click" />
<Button Grid.Row="4" Content="Number of created courses for each of the existing languages in the system in the last year" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
<Button Grid.Row="5" Content="Number of created exams for each of the existing languages in the system in the last year" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
<Button Grid.Row="6" Content="Report b" BorderBrush="White" Background="#FFFFDBDB" Foreground="#FF817C7C" FontFamily="Segoe UI Black" />
Expand Down
14 changes: 12 additions & 2 deletions LangLang/WPF/Views/DirectorView/Tabs/Reports.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using LangLang.WPF.ViewModels.DirectorViewModels;
using System.Windows.Controls;
using LangLang.Domain.Models;

namespace LangLang.WPF.Views.DirectorView.Tabs
{
Expand All @@ -9,12 +10,21 @@ namespace LangLang.WPF.Views.DirectorView.Tabs
public partial class Reports : UserControl
{
private ReportsViewModel _viewModel;
public Reports()
public Reports(Director loggedIn)
{
InitializeComponent();
_viewModel = new();
_viewModel = new(loggedIn);
DataContext = _viewModel;
}

private void AveragePoints_Click(object sender, System.Windows.RoutedEventArgs e)
{
_viewModel.SentAveragePoints();
}

private void AveragePenaltyPoints_Click(object sender, System.Windows.RoutedEventArgs e)
{
_viewModel.SentAveragePenaltyPoints();
}
}
}

0 comments on commit 96ff622

Please sign in to comment.