diff --git a/Source/SeaInk.Core/APIs/IUniversitySystemApi.cs b/Source/SeaInk.Core/APIs/IUniversitySystemApi.cs index 40ab45d..fe154e6 100644 --- a/Source/SeaInk.Core/APIs/IUniversitySystemApi.cs +++ b/Source/SeaInk.Core/APIs/IUniversitySystemApi.cs @@ -1,4 +1,5 @@ -using SeaInk.Core.Entities; +using System.Collections.Generic; +using SeaInk.Core.Entities; namespace SeaInk.Core.APIs { @@ -12,6 +13,7 @@ public interface IUniversitySystemApi Subject GetSubject(int id); StudentAssignmentProgress GetStudentAssignmentProgress(int studentId, int assignmentId); Division GetDivision(int mentorId, int subjectId); + List GetStudyGroupSubjects(int mentorId, int subjectId); void SaveUser(User user); void SaveStudent(Student student); diff --git a/Source/SeaInk.Core/Entities/Division.cs b/Source/SeaInk.Core/Entities/Division.cs index b44820e..0b03f93 100644 --- a/Source/SeaInk.Core/Entities/Division.cs +++ b/Source/SeaInk.Core/Entities/Division.cs @@ -10,8 +10,6 @@ public class Division: IEntity public string Title { get; set; } public string SpreadsheetId { get; set; } - public virtual Mentor Mentor { get; set; } - public virtual Subject Subject { get; set; } - public virtual List Groups { get; set; } = new(); + public virtual List StudyGroupSubjects { get; set; } = new(); } } \ No newline at end of file diff --git a/Source/SeaInk.Core/Entities/Mentor.cs b/Source/SeaInk.Core/Entities/Mentor.cs index 6a14471..0581e72 100644 --- a/Source/SeaInk.Core/Entities/Mentor.cs +++ b/Source/SeaInk.Core/Entities/Mentor.cs @@ -2,8 +2,8 @@ namespace SeaInk.Core.Entities { - public class Mentor: User + public class Mentor : User { - public virtual List Divisions { get; set; } = new(); + public virtual List StudyGroupSubjects { get; set; } = new(); } } \ No newline at end of file diff --git a/Source/SeaInk.Core/Entities/StudyGroupSubject.cs b/Source/SeaInk.Core/Entities/StudyGroupSubject.cs new file mode 100644 index 0000000..044ad7e --- /dev/null +++ b/Source/SeaInk.Core/Entities/StudyGroupSubject.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace SeaInk.Core.Entities +{ + public class StudyGroupSubject : IEntity + { + public int Id { get; set; } + + public virtual StudyGroup StudyGroup { get; set; } + public virtual Subject Subject { get; set; } + public virtual List Mentors { get; set; } + } +} \ No newline at end of file diff --git a/Source/SeaInk.Endpoints.Shared/Dto/DivisionDto.cs b/Source/SeaInk.Endpoints.Shared/Dto/DivisionDto.cs index 34974b5..c7516e6 100644 --- a/Source/SeaInk.Endpoints.Shared/Dto/DivisionDto.cs +++ b/Source/SeaInk.Endpoints.Shared/Dto/DivisionDto.cs @@ -8,10 +8,7 @@ public record DivisionDto( int Id, string Title, string SpreadsheetId, - int MentorId, - string MentorName, - SubjectDto Subject, - IReadOnlyList Groups); + IReadOnlyList StudyGroupSubjects); public static class DivisionExtension { @@ -20,10 +17,7 @@ public static DivisionDto ToDto(this Division division) return new DivisionDto(division.Id, division.Title, division.SpreadsheetId, - division.Mentor.Id, - division.Mentor.FullName, - division.Subject.ToDto(), - division.Groups.Select(g => g.ToDto()).ToList()); + division.StudyGroupSubjects.Select(s => s.ToDto()).ToList()); } } } \ No newline at end of file diff --git a/Source/SeaInk.Endpoints.Shared/Dto/MentorDto.cs b/Source/SeaInk.Endpoints.Shared/Dto/MentorDto.cs index 585b22c..0719ca9 100644 --- a/Source/SeaInk.Endpoints.Shared/Dto/MentorDto.cs +++ b/Source/SeaInk.Endpoints.Shared/Dto/MentorDto.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using MoreLinq; using SeaInk.Core.Entities; namespace SeaInk.Endpoints.Shared.Dto @@ -12,8 +11,7 @@ public record MentorDto( string LastName, string MiddleName, string FullName, - IReadOnlyList Subjects, - IReadOnlyList Divisions); + List StudyGroupSubjects); public static class MentorExtension { @@ -25,13 +23,7 @@ public static MentorDto ToDto(this Mentor mentor) mentor.LastName, mentor.MiddleName, mentor.FullName, - mentor.Divisions - .Select(d => d.Subject.ToDto()) - .DistinctBy(s => s.Id) - .ToList(), - mentor.Divisions - .Select(d => d.ToDto()) - .ToList()); + mentor.StudyGroupSubjects.Select(s => s.ToDto()).ToList()); } } } \ No newline at end of file diff --git a/Source/SeaInk.Endpoints.Shared/Dto/StudyGroupSubjectDto.cs b/Source/SeaInk.Endpoints.Shared/Dto/StudyGroupSubjectDto.cs new file mode 100644 index 0000000..04a3d14 --- /dev/null +++ b/Source/SeaInk.Endpoints.Shared/Dto/StudyGroupSubjectDto.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.Linq; +using SeaInk.Core.Entities; + +namespace SeaInk.Endpoints.Shared.Dto +{ + public record StudyGroupSubjectDto( + int Id, + StudyGroupDto StudyGroup, + SubjectDto Subject, + List MentorIds); + + public static class StudyGroupSubjectExtension + { + public static StudyGroupSubjectDto ToDto(this StudyGroupSubject studyGroupSubject) + { + return new StudyGroupSubjectDto( + studyGroupSubject.Id, + studyGroupSubject.StudyGroup.ToDto(), + studyGroupSubject.Subject.ToDto(), + studyGroupSubject.Mentors.Select(m => m.Id).ToList()); + } + } +} diff --git a/Source/SeaInk.Endpoints/Client/Pages/Groups/GroupsPage.razor.cs b/Source/SeaInk.Endpoints/Client/Pages/Groups/GroupsPage.razor.cs index 30be27b..56cc5be 100644 --- a/Source/SeaInk.Endpoints/Client/Pages/Groups/GroupsPage.razor.cs +++ b/Source/SeaInk.Endpoints/Client/Pages/Groups/GroupsPage.razor.cs @@ -17,7 +17,6 @@ public partial class GroupsPage private int _selectedSubjectId; private IReadOnlyList _divisions; - private int _selectedDivisionId; private IReadOnlyList _groups; private string _selectedGroupId; @@ -26,7 +25,8 @@ protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); _currentMentor = await Client.CurrentAsync(); - _subjects = _currentMentor.Subjects.ToList(); + _divisions = (await Client.DivisionsAsync(_currentMentor.Id)).ToList(); + _subjects = _currentMentor.StudyGroupSubjects.Select(sgs => sgs.Subject).ToList(); if (_subjects.Count != 0) OnSelectedSubjectChanged(_subjects[0].Id); @@ -35,7 +35,6 @@ protected override async Task OnInitializedAsync() private void OnSelectedSubjectChanged(int subjectId) { _selectedSubjectId = subjectId; - _divisions = _currentMentor.Divisions.Where(d => d.Subject.Id == _selectedSubjectId).ToList(); if (_divisions.Count != 0) OnSelectedDivisionChanged(_divisions[0].Id); @@ -43,10 +42,13 @@ private void OnSelectedSubjectChanged(int subjectId) private void OnSelectedDivisionChanged(int divisionId) { - _selectedDivisionId = divisionId; - _groups = _currentMentor.Divisions - .Single(d => d.Subject.Id == _selectedSubjectId && d.Id == _selectedDivisionId) - .Groups + _groups = _divisions + .Where(d => d.Id == divisionId) + .SelectMany(d => d.StudyGroupSubjects) + .Where(sgs => sgs.Subject.Id == _selectedSubjectId) + .Select(sgs => sgs.StudyGroup) + .GroupBy(g => g.Id) + .Select(gg => gg.First()) .ToList(); if (_groups.Count == 0) diff --git a/Source/SeaInk.Endpoints/Client/SeaInk.Endpoints.Client.csproj b/Source/SeaInk.Endpoints/Client/SeaInk.Endpoints.Client.csproj index a0c6b3c..dc4de16 100644 --- a/Source/SeaInk.Endpoints/Client/SeaInk.Endpoints.Client.csproj +++ b/Source/SeaInk.Endpoints/Client/SeaInk.Endpoints.Client.csproj @@ -1,4 +1,4 @@ - + net5.0 diff --git a/Source/SeaInk.Endpoints/SeaInk.Endpoints.Sdk/ApiClients/SeaInkApiClient.cs b/Source/SeaInk.Endpoints/SeaInk.Endpoints.Sdk/ApiClients/SeaInkApiClient.cs index 218949f..ea76c9d 100644 --- a/Source/SeaInk.Endpoints/SeaInk.Endpoints.Sdk/ApiClients/SeaInkApiClient.cs +++ b/Source/SeaInk.Endpoints/SeaInk.Endpoints.Sdk/ApiClients/SeaInkApiClient.cs @@ -272,6 +272,84 @@ public async System.Threading.Tasks.Task MentorsAsync(int mentorId, S } } + /// Success + /// A server side error occurred. + public System.Threading.Tasks.Task> DivisionsAsync(int mentorId) + { + return DivisionsAsync(mentorId, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// Success + /// A server side error occurred. + public async System.Threading.Tasks.Task> DivisionsAsync(int mentorId, System.Threading.CancellationToken cancellationToken) + { + if (mentorId == null) + throw new System.ArgumentNullException("mentorId"); + + var urlBuilder_ = new System.Text.StringBuilder(); + urlBuilder_.Append("mentors/{mentorId}/divisions"); + urlBuilder_.Replace("{mentorId}", System.Uri.EscapeDataString(ConvertToString(mentorId, System.Globalization.CultureInfo.InvariantCulture))); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value); + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + protected struct ObjectResponseResult { public ObjectResponseResult(T responseObject, string responseText) @@ -384,17 +462,8 @@ public partial class DivisionDto [System.Text.Json.Serialization.JsonPropertyName("spreadsheetId")] public string SpreadsheetId { get; set; } - [System.Text.Json.Serialization.JsonPropertyName("mentorId")] - public int MentorId { get; set; } - - [System.Text.Json.Serialization.JsonPropertyName("mentorName")] - public string MentorName { get; set; } - - [System.Text.Json.Serialization.JsonPropertyName("subject")] - public SubjectDto Subject { get; set; } - - [System.Text.Json.Serialization.JsonPropertyName("groups")] - public System.Collections.Generic.ICollection Groups { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("studyGroupSubjects")] + public System.Collections.Generic.ICollection StudyGroupSubjects { get; set; } } @@ -420,11 +489,8 @@ public partial class MentorDto [System.Text.Json.Serialization.JsonPropertyName("fullName")] public string FullName { get; set; } - [System.Text.Json.Serialization.JsonPropertyName("subjects")] - public System.Collections.Generic.ICollection Subjects { get; set; } - - [System.Text.Json.Serialization.JsonPropertyName("divisions")] - public System.Collections.Generic.ICollection Divisions { get; set; } + [System.Text.Json.Serialization.JsonPropertyName("studyGroupSubjects")] + public System.Collections.Generic.ICollection StudyGroupSubjects { get; set; } } @@ -499,6 +565,24 @@ public partial class StudyGroupDto public System.Collections.Generic.ICollection Students { get; set; } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v11.0.0.0)")] + public partial class StudyGroupSubjectDto + { + [System.Text.Json.Serialization.JsonPropertyName("id")] + public int Id { get; set; } + + [System.Text.Json.Serialization.JsonPropertyName("studyGroup")] + public StudyGroupDto StudyGroup { get; set; } + + [System.Text.Json.Serialization.JsonPropertyName("subject")] + public SubjectDto Subject { get; set; } + + [System.Text.Json.Serialization.JsonPropertyName("mentorIds")] + public System.Collections.Generic.ICollection MentorIds { get; set; } + + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.4.4.0 (Newtonsoft.Json v11.0.0.0)")] diff --git a/Source/SeaInk.Endpoints/Server/Controllers/MentorController.cs b/Source/SeaInk.Endpoints/Server/Controllers/MentorController.cs index c29dbb8..e775174 100644 --- a/Source/SeaInk.Endpoints/Server/Controllers/MentorController.cs +++ b/Source/SeaInk.Endpoints/Server/Controllers/MentorController.cs @@ -23,7 +23,7 @@ public MentorController(DatabaseContext databaseContext) public ActionResult GetCurrentMentor() { Mentor mentor = _databaseContext.Mentors - .MaxBy(m => m.Divisions.Count) + .MaxBy(m => m.StudyGroupSubjects.Count) .First(); return Ok(mentor.ToDto()); } @@ -45,7 +45,7 @@ public ActionResult> GetSubjects(int mentorId) if (mentor is null) return NotFound(); - List subjects = mentor.Divisions + List subjects = mentor.StudyGroupSubjects .Select(d => d.Subject) .DistinctBy(s => s.Id) .Select(s => s.ToDto()) @@ -53,5 +53,20 @@ public ActionResult> GetSubjects(int mentorId) return Ok(subjects); } + + [HttpGet("{mentorId:int}/divisions")] + public ActionResult> GetDivisions(int mentorId) + { + Mentor mentor = _databaseContext.Mentors.Find(mentorId); + if (mentor is null) + return NotFound(); + + List divisions = _databaseContext.Divisions + .Where(d => d.StudyGroupSubjects.Any(sgs => sgs.Mentors.Any(m => m.Id == mentorId))) + .Select(d => d.ToDto()) + .ToList(); + + return Ok(divisions); + } } } \ No newline at end of file diff --git a/Source/SeaInk.Infrastructure/APIs/FakeUniversitySystemApi.cs b/Source/SeaInk.Infrastructure/APIs/FakeUniversitySystemApi.cs index 3fd5405..0c88a5f 100644 --- a/Source/SeaInk.Infrastructure/APIs/FakeUniversitySystemApi.cs +++ b/Source/SeaInk.Infrastructure/APIs/FakeUniversitySystemApi.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using Bogus; using SeaInk.Core.Entities; using SeaInk.Core.Models; @@ -10,13 +9,6 @@ namespace Infrastructure.APIs { public class FakeUniversitySystemApi: ITestUniversitySystemApi { - private int _currentUserId = -1; - private int _currentStudentId = -1; - private int _currentMentorId = -1; - private int _currentGroupId = -1; - private int _currentAssignmentId = -1; - private int _currentSubjectId = -1; - private readonly Faker _userFaker; private readonly Faker _studentFaker; private readonly Faker _mentorFaker; @@ -26,54 +18,15 @@ public class FakeUniversitySystemApi: ITestUniversitySystemApi private readonly Faker _studentAssignmentProgressFaker; private readonly Faker _divisionFaker; - private int _totalCallCount; - - private int _getUserCallCount; - private int _getStudentCallCount; - private int _getMentorCallCount; - private int _getStudyGroupCallCount; - private int _getStudyAssignmentCallCount; - private int _getSubjectCallCount; - private int _getStudentAssignmentProgressCallCount; - private int _getDivisionCallCount; - - private int _saveUserCallCount; - private int _saveStudentCallCount; - private int _saveMentorCallCount; - private int _saveStudyGroupCallCount; - private int _saveStudyAssignmentCallCount; - private int _saveSubjectCallCount; - private int _saveStudentAssignmentProgressCallCount; - private int _saveDivisionCallCount; - public List Users { get; } = new(); public List Students { get; } = new(); public List Mentors { get; } = new(); public List Groups { get; } = new(); - public List Assignments { get; } = new(); + public List StudyAssignments { get; } = new(); public List Subjects { get; } = new(); public List StudentAssignmentProgresses { get; } = new(); public List Divisions { get; } = new(); - - public int TotalCallCount => _totalCallCount; - - public int GetUserCallCount => _getUserCallCount; - public int GetStudentCallCount => _getStudentCallCount; - public int GetMentorCallCount => _getMentorCallCount; - public int GetStudyGroupCallCount => _getStudyGroupCallCount; - public int GetStudyAssignmentCallCount => _getStudyAssignmentCallCount; - public int GetSubjectCallCount => _getSubjectCallCount; - public int GetStudentAssignmentProgressCallCount => _getStudentAssignmentProgressCallCount; - public int GetDivisionCallCount => _getDivisionCallCount; - - public int SaveUserCallCount => _saveUserCallCount; - public int SaveStudentCallCount => _saveStudentCallCount; - public int SaveMentorCallCount => _saveMentorCallCount; - public int SaveStudyGroupCallCount => _saveStudyGroupCallCount; - public int SaveStudyAssignmentCallCount => _saveStudyAssignmentCallCount; - public int SaveSubjectCallCount => _saveSubjectCallCount; - public int SaveStudentAssignmentProgressCallCount => _saveStudentAssignmentProgressCallCount; - public int SaveDivisionCallCount => _saveDivisionCallCount; + public List StudyGroupSubjects { get; } = new(); public event ITestUniversitySystemApi.HandleLog Log; @@ -82,7 +35,7 @@ public FakeUniversitySystemApi(int mentorCount = 1) _userFaker = new Faker("ru") .CustomInstantiator(faker => new User { - UniversityId = Interlocked.Increment(ref _currentUserId), + UniversityId = faker.IndexFaker, FirstName = faker.Person.FirstName, MiddleName = faker.Person.UserName, LastName = faker.Person.LastName @@ -91,7 +44,7 @@ public FakeUniversitySystemApi(int mentorCount = 1) _studentFaker = new Faker("ru") .CustomInstantiator(faker => new Student { - UniversityId = Interlocked.Increment(ref _currentStudentId), + UniversityId = faker.IndexFaker, FirstName = faker.Person.FirstName, MiddleName = faker.Person.UserName, LastName = faker.Person.LastName @@ -100,7 +53,7 @@ public FakeUniversitySystemApi(int mentorCount = 1) _mentorFaker = new Faker("ru") .CustomInstantiator(faker => new Mentor { - UniversityId = Interlocked.Increment(ref _currentMentorId), + UniversityId = faker.IndexFaker, FirstName = faker.Person.FirstName, MiddleName = faker.Person.UserName, LastName = faker.Person.LastName @@ -109,7 +62,7 @@ public FakeUniversitySystemApi(int mentorCount = 1) _groupFaker = new Faker() .CustomInstantiator(faker => new StudyGroup { - UniversityId = Interlocked.Increment(ref _currentGroupId), + UniversityId = faker.IndexFaker, Name = faker.Lorem.Letter().ToUpper() + faker.Random.Number(1000, 9999) }) .Rules((f, g) => @@ -126,7 +79,7 @@ public FakeUniversitySystemApi(int mentorCount = 1) _assignmentsFaker = new Faker("ru") .CustomInstantiator(faker => new StudyAssignment { - UniversityId = Interlocked.Increment(ref _currentAssignmentId), + UniversityId = faker.IndexFaker, Title = faker.Name.JobType(), IsMilestone = faker.Random.Bool(), MaxPoints = faker.Random.Float(5, 10), @@ -136,11 +89,11 @@ public FakeUniversitySystemApi(int mentorCount = 1) _subjectFaker = new Faker() .CustomInstantiator(faker => new Subject { - UniversityId = Interlocked.Increment(ref _currentSubjectId), + UniversityId = faker.IndexFaker, Name = faker.Name.JobArea(), StartDate = faker.Date.Past(), EndDate = faker.Date.Future(), - Assignments = faker.Random.ArrayElements(Assignments.ToArray(), faker.Random.Int(5, 10)).ToList() + Assignments = faker.Random.ArrayElements(StudyAssignments.ToArray(), faker.Random.Int(5, 10)).ToList() }) .FinishWith((f, s) => { @@ -155,7 +108,7 @@ public FakeUniversitySystemApi(int mentorCount = 1) _studentAssignmentProgressFaker = new Faker() .CustomInstantiator(faker => new StudentAssignmentProgress { - Assignment = faker.Random.ArrayElement(Assignments.ToArray()), + Assignment = faker.Random.ArrayElement(StudyAssignments.ToArray()), Student = faker.Random.ArrayElement(Students.ToArray()) }) .RuleFor(p => p.Progress, @@ -165,15 +118,24 @@ public FakeUniversitySystemApi(int mentorCount = 1) f.Random.Double(p.Assignment.MinPoints, p.Assignment.MaxPoints) )); + Faker studyGroupSubjectFaker = new Faker() + .CustomInstantiator(faker => new StudyGroupSubject + { + Id = faker.IndexFaker, + StudyGroup = faker.Random.ArrayElement(Groups.ToArray()), + Subject = faker.Random.ArrayElement(Subjects.ToArray()), + Mentors = new List { faker.Random.ArrayElement(Mentors.ToArray()) } + }); + + _divisionFaker = new Faker("ru") .CustomInstantiator(faker => new Division { + Id = faker.IndexFaker, SpreadsheetId = faker.Internet.Url(), - Subject = faker.Random.ArrayElement(Subjects.ToArray()), - Mentor = faker.Random.ArrayElement(Mentors.ToArray()), - Groups = faker.Random.ArrayElements(Groups.ToArray(), faker.Random.Int(1, 4)).ToList() + StudyGroupSubjects = studyGroupSubjectFaker.Generate(faker.Random.Int(1,4)) }) - .FinishWith((_, d) => { d.Mentor.Divisions.Add(d); }); + .FinishWith((_, d) => { d.StudyGroupSubjects.ForEach(sgs => sgs.Mentors.ForEach(m => m.StudyGroupSubjects.Add(sgs))); }); GenerateInitialData(mentorCount); } @@ -192,64 +154,51 @@ private void GenerateInitialData(int mentorCount) Students.AddRange(_studentFaker.Generate(studentCount)); Mentors.AddRange(_mentorFaker.Generate(mentorCount)); Groups.AddRange(_groupFaker.Generate(groupCount)); - Assignments.AddRange(_assignmentsFaker.Generate(assignmentCount)); + StudyAssignments.AddRange(_assignmentsFaker.Generate(assignmentCount)); Subjects.AddRange(_subjectFaker.Generate(subjectCount)); StudentAssignmentProgresses.AddRange(_studentAssignmentProgressFaker.Generate(studentAssignmentProgressCount)); Divisions.AddRange(_divisionFaker.Generate(divisionCount)); + StudyGroupSubjects.AddRange(Divisions.SelectMany(d => d.StudyGroupSubjects)); } public User GetUser(int id) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getUserCallCount); Log?.Invoke("Got user"); return Users.SingleOrDefault(u => u.UniversityId == id); } public Student GetStudent(int id) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getStudentCallCount); Log?.Invoke("Got student"); return Students.SingleOrDefault(x => x.UniversityId == id); } public Mentor GetMentor(int id) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getMentorCallCount); Log?.Invoke("Got mentor"); return Mentors.SingleOrDefault(x => x.UniversityId == id); } public StudyGroup GetStudyGroup(int id) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getStudyGroupCallCount); Log?.Invoke("Got study group"); return Groups.SingleOrDefault(x => x.UniversityId == id); } public StudyAssignment GetStudyAssignment(int id) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getStudyAssignmentCallCount); Log?.Invoke("Got study assignment"); - return Assignments.SingleOrDefault(x => x.UniversityId == id); + return StudyAssignments.SingleOrDefault(x => x.UniversityId == id); } public Subject GetSubject(int id) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getSubjectCallCount); Log?.Invoke("Got subject"); return Subjects.SingleOrDefault(x => x.UniversityId == id); } public StudentAssignmentProgress GetStudentAssignmentProgress(int studentId, int assignmentId) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getStudentAssignmentProgressCallCount); Log?.Invoke("Got student assignment progress"); return StudentAssignmentProgresses .SingleOrDefault(p => p.Student.UniversityId == studentId && p.Assignment.UniversityId == assignmentId); @@ -257,65 +206,58 @@ public StudentAssignmentProgress GetStudentAssignmentProgress(int studentId, int public Division GetDivision(int mentorId, int subjectId) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _getDivisionCallCount); Log?.Invoke("Got division"); - return Divisions.SingleOrDefault(d => d.Mentor.UniversityId == mentorId && d.Subject.UniversityId == subjectId); + return Divisions + .SingleOrDefault(d => d.StudyGroupSubjects + .Where(sgs => sgs.Subject.Id == subjectId) + .Any(sgs => sgs.Mentors.Any(m => m.Id == mentorId))); + } + + public List GetStudyGroupSubjects(int mentorId, int subjectId) + { + return StudyGroupSubjects + .Where(sgs => sgs.Subject.Id == subjectId) + .Where(sgs => sgs.Mentors.Any(m => m.Id == mentorId)) + .ToList(); } public void SaveUser(User user) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveUserCallCount); Log?.Invoke($"Saved {nameof(user)}"); } public void SaveStudent(Student student) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveStudentCallCount); Log?.Invoke($"Saved {nameof(student)}"); } public void SaveMentor(Mentor mentor) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveMentorCallCount); Log?.Invoke($"Saved {nameof(mentor)}"); } public void SaveStudyGroup(StudyGroup group) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveStudyGroupCallCount); Log?.Invoke($"Saved {nameof(group)}"); } public void SaveSubject(Subject subject) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveSubjectCallCount); Log?.Invoke($"Saved {nameof(subject)}"); } public void SaveDivision(Division division) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveDivisionCallCount); Log?.Invoke($"Saved {nameof(division)}"); } public void SaveStudyAssignment(StudyAssignment assignment) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveStudyAssignmentCallCount); Log?.Invoke($"Saved {nameof(assignment)}"); } public void SaveAssignmentProgress(StudentAssignmentProgress progress) { - Interlocked.Increment(ref _totalCallCount); - Interlocked.Increment(ref _saveStudentAssignmentProgressCallCount); Log?.Invoke($"Saved {nameof(progress)}"); } } diff --git a/Source/SeaInk.Infrastructure/APIs/ITestUniversitySystemApi.cs b/Source/SeaInk.Infrastructure/APIs/ITestUniversitySystemApi.cs index eb83c12..857fed8 100644 --- a/Source/SeaInk.Infrastructure/APIs/ITestUniversitySystemApi.cs +++ b/Source/SeaInk.Infrastructure/APIs/ITestUniversitySystemApi.cs @@ -10,7 +10,7 @@ public interface ITestUniversitySystemApi: IUniversitySystemApi List Students { get; } List Mentors { get; } List Groups { get; } - List Assignments { get; } + List StudyAssignments { get; } List Subjects { get; } List StudentAssignmentProgresses { get; } List Divisions { get; } @@ -18,25 +18,5 @@ public interface ITestUniversitySystemApi: IUniversitySystemApi delegate void HandleLog(string message); event HandleLog Log; - - int TotalCallCount { get; } - - int GetUserCallCount { get; } - int GetStudentCallCount { get; } - int GetMentorCallCount { get; } - int GetStudyGroupCallCount { get; } - int GetStudyAssignmentCallCount { get; } - int GetSubjectCallCount { get; } - int GetStudentAssignmentProgressCallCount { get; } - int GetDivisionCallCount { get; } - - int SaveUserCallCount { get; } - int SaveStudentCallCount { get; } - int SaveMentorCallCount { get; } - int SaveStudyGroupCallCount { get; } - int SaveStudyAssignmentCallCount { get; } - int SaveSubjectCallCount { get; } - int SaveStudentAssignmentProgressCallCount { get; } - int SaveDivisionCallCount { get; } } } \ No newline at end of file diff --git a/Source/SeaInk.Infrastructure/Database/DatabaseContext.cs b/Source/SeaInk.Infrastructure/Database/DatabaseContext.cs index 8cb59b3..e2b730c 100644 --- a/Source/SeaInk.Infrastructure/Database/DatabaseContext.cs +++ b/Source/SeaInk.Infrastructure/Database/DatabaseContext.cs @@ -13,6 +13,7 @@ public sealed class DatabaseContext: DbContext public DbSet Divisions { get; private set; } public DbSet Subjects { get; private set; } public DbSet StudyGroups { get; private set; } + public DbSet StudyGroupSubjects { get; private set; } public DbSet StudyAssignments { get; private set; } public DbSet StudentAssignmentProgresses { get; private set; } @@ -55,7 +56,7 @@ public static DatabaseContext Seed(DatabaseContext databaseContext) databaseContext.Students.AddRange(api.Students); databaseContext.Mentors.AddRange(api.Mentors); databaseContext.StudyGroups.AddRange(api.Groups); - databaseContext.StudyAssignments.AddRange(api.Assignments); + databaseContext.StudyAssignments.AddRange(api.StudyAssignments); databaseContext.Subjects.AddRange(api.Subjects); databaseContext.StudentAssignmentProgresses.AddRange(api.StudentAssignmentProgresses); databaseContext.Divisions.AddRange(api.Divisions); diff --git a/Source/SeaInk.Tests.Infrastructure/EntityFrameworkTests.cs b/Source/SeaInk.Tests.Infrastructure/EntityFrameworkTests.cs index c963f8b..2420616 100644 --- a/Source/SeaInk.Tests.Infrastructure/EntityFrameworkTests.cs +++ b/Source/SeaInk.Tests.Infrastructure/EntityFrameworkTests.cs @@ -40,49 +40,5 @@ public void StudentAssignmentProgressRepositoryTest_SAP_AddedToDatabase() Assert.AreEqual(progress.Progress, createdProgress.Progress); Assert.AreEqual(progress.Student.Id, createdProgress.Student.Id); } - - [Test] - public void DivisionRepositoryTest_DivisionAddedToDatabase() - { - DbSet repository = _context.Divisions; - - Division division = _api.Divisions.First(); - repository.Add(division); - _context.SaveChanges(); - - Division createdDivision = repository.Find(division.Id); - - Assert.NotNull(createdDivision); - Assert.AreEqual(division.Id, createdDivision.Id); - Assert.AreEqual(division.Mentor.Id, createdDivision.Mentor.Id); - Assert.AreEqual(division.Mentor.UniversityId, createdDivision.Mentor.UniversityId); - Assert.AreEqual(division.Subject.Id, createdDivision.Subject.Id); - Assert.AreEqual(division.Subject.UniversityId, createdDivision.Subject.UniversityId); - Assert.True(division.Groups.ToIds().ToHashSet() - .SetEquals(createdDivision.Groups.ToIds())); - - List<(StudyGroup found, StudyGroup created)> matchedGroups = division.Groups - .Select(f => (f, createdDivision.Groups.Single(c => c.Id == f.Id))).ToList(); - - foreach (var groupPair in matchedGroups) - { - Assert.AreEqual(groupPair.found.Name, groupPair.created.Name); - Assert.AreEqual(groupPair.found.AdminId, groupPair.created.AdminId); - Assert.AreEqual(groupPair.found.UniversityId, groupPair.created.UniversityId); - Assert.True(groupPair.found.Students.ToIds().ToHashSet() - .SetEquals(groupPair.created.Students.ToIds())); - - List<(Student found, Student created)> matchedStudents = groupPair.found.Students - .Select(f => (f, groupPair.created.Students.Single(c => c.Id == f.Id))).ToList(); - - foreach (var studentPair in matchedStudents) - { - Assert.AreEqual(studentPair.found.FirstName, studentPair.created.FirstName); - Assert.AreEqual(studentPair.found.MiddleName, studentPair.created.MiddleName); - Assert.AreEqual(studentPair.found.LastName, studentPair.created.LastName); - Assert.AreEqual(studentPair.found.UniversityId, studentPair.created.UniversityId); - } - } - } } } \ No newline at end of file diff --git a/Source/SeaInk.sln b/Source/SeaInk.sln index 62b1d63..d3b8af3 100644 --- a/Source/SeaInk.sln +++ b/Source/SeaInk.sln @@ -23,9 +23,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeaInk.Tests.Infrastructure EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeaInk.Tests.Endpoints", "SeaInk.Tests.Endpoints\SeaInk.Tests.Endpoints.csproj", "{D56D94AA-F9F4-429C-A8DC-13FECB56122C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeaInk.Endpoints.Sdk", "SeaInk.Endpoints\SeaInk.Endpoints.Sdk\SeaInk.Endpoints.Sdk.csproj", "{3375A8BD-106C-421A-BA46-FC1C51340B48}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeaInk.Endpoints.Sdk", "SeaInk.Endpoints\SeaInk.Endpoints.Sdk\SeaInk.Endpoints.Sdk.csproj", "{3375A8BD-106C-421A-BA46-FC1C51340B48}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeaInk.Tests.Core", "SeaInk.Tests.Core\SeaInk.Tests.Core.csproj", "{AC8B491C-D52A-437D-93C8-6BA383CB4F36}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeaInk.Tests.Core", "SeaInk.Tests.Core\SeaInk.Tests.Core.csproj", "{AC8B491C-D52A-437D-93C8-6BA383CB4F36}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -65,6 +65,10 @@ Global {D56D94AA-F9F4-429C-A8DC-13FECB56122C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D56D94AA-F9F4-429C-A8DC-13FECB56122C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D56D94AA-F9F4-429C-A8DC-13FECB56122C}.Release|Any CPU.Build.0 = Release|Any CPU + {3375A8BD-106C-421A-BA46-FC1C51340B48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3375A8BD-106C-421A-BA46-FC1C51340B48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3375A8BD-106C-421A-BA46-FC1C51340B48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3375A8BD-106C-421A-BA46-FC1C51340B48}.Release|Any CPU.Build.0 = Release|Any CPU {AC8B491C-D52A-437D-93C8-6BA383CB4F36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AC8B491C-D52A-437D-93C8-6BA383CB4F36}.Debug|Any CPU.Build.0 = Debug|Any CPU {AC8B491C-D52A-437D-93C8-6BA383CB4F36}.Release|Any CPU.ActiveCfg = Release|Any CPU