Skip to content

Commit 35f1ad3

Browse files
committed
Merge branch 'google-sheets' of https://github.com/InteIIigeNET/HwProj-2.0.1 into google-sheets
2 parents 0ba1632 + c505b8c commit 35f1ad3

File tree

33 files changed

+855
-252
lines changed

33 files changed

+855
-252
lines changed

HwProj.APIGateway/HwProj.APIGateway.API/Controllers/SolutionsController.cs

Lines changed: 133 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using HwProj.APIGateway.API.Models.Solutions;
88
using HwProj.AuthService.Client;
99
using HwProj.CoursesService.Client;
10+
using HwProj.Models.AuthService.DTO;
1011
using HwProj.Models.CoursesService.ViewModels;
1112
using HwProj.Models.Roles;
1213
using HwProj.Models.SolutionsService;
@@ -33,14 +34,6 @@ public SolutionsController(ISolutionsServiceClient solutionsClient, IAuthService
3334
_coursesServiceClient = coursesServiceClient;
3435
}
3536

36-
[HttpGet]
37-
[ProducesResponseType(typeof(Solution[]), (int)HttpStatusCode.OK)]
38-
public async Task<IActionResult> GetAllSolutions()
39-
{
40-
var result = await _solutionsClient.GetAllSolutions();
41-
return Ok(result);
42-
}
43-
4437
[HttpGet("{solutionId}")]
4538
[ProducesResponseType(typeof(Solution), (int)HttpStatusCode.OK)]
4639
public async Task<IActionResult> GetSolutionById(long solutionId)
@@ -53,19 +46,94 @@ public async Task<IActionResult> GetSolutionById(long solutionId)
5346

5447
[HttpGet("taskSolution/{taskId}/{studentId}")]
5548
[Authorize]
56-
public async Task<UserTaskSolutions> GetStudentSolution(long taskId, string studentId)
49+
[ProducesResponseType(typeof(UserTaskSolutions), (int)HttpStatusCode.OK)]
50+
public async Task<IActionResult> GetStudentSolution(long taskId, string studentId)
51+
{
52+
var course = await _coursesServiceClient.GetCourseByTask(taskId);
53+
if (course == null) return NotFound();
54+
55+
var courseMate = course.CourseMates.FirstOrDefault(t => t.StudentId == studentId);
56+
if (courseMate == null || !courseMate.IsAccepted)
57+
return NotFound();
58+
59+
var student = await AuthServiceClient.GetAccountData(studentId);
60+
var studentSolutions = await _solutionsClient.GetUserSolutions(taskId, studentId);
61+
62+
var solutionsGroupsIds = studentSolutions
63+
.Select(s => s.GroupId)
64+
.Distinct();
65+
var solutionsGroups = course.Groups
66+
.Where(g => solutionsGroupsIds.Contains(g.Id))
67+
.ToDictionary(t => t.Id);
68+
69+
var groupMatesIds = course.Groups
70+
.Where(g => solutionsGroupsIds.Contains(g.Id))
71+
.SelectMany(g => g.StudentsIds)
72+
.Distinct()
73+
.ToArray();
74+
var groupMates = groupMatesIds.Any()
75+
? await AuthServiceClient.GetAccountsData(groupMatesIds)
76+
: Array.Empty<AccountDataDto>();
77+
78+
var solutions = studentSolutions
79+
.Select(s =>
80+
new GetSolutionModel(s,
81+
s.GroupId is { } groupId
82+
? groupMates
83+
.Where(t => solutionsGroups[groupId].StudentsIds.Contains(t.UserId))
84+
.ToArray()
85+
: null))
86+
.ToArray();
87+
88+
return Ok(new UserTaskSolutions()
89+
{
90+
User = student,
91+
Solutions = solutions
92+
});
93+
}
94+
95+
[Authorize]
96+
[HttpGet("tasks/{taskId}")]
97+
[ProducesResponseType(typeof(TaskSolutionStatisticsPageData), (int)HttpStatusCode.OK)]
98+
public async Task<IActionResult> GetTaskSolutionsPageData(long taskId)
5799
{
58-
var getSolutionsTask = _solutionsClient.GetUserSolutions(taskId, studentId);
59-
var getUserTask = AuthServiceClient.GetAccountData(studentId);
100+
var course = await _coursesServiceClient.GetCourseByTask(taskId);
101+
//TODO: CourseMentorOnlyAttribute
102+
if (course == null || !course.MentorIds.Contains(UserId)) return Forbid();
60103

61-
await Task.WhenAll(getSolutionsTask, getUserTask);
104+
var studentIds = course.CourseMates
105+
.Where(t => t.IsAccepted)
106+
.Select(t => t.StudentId)
107+
.ToArray();
108+
109+
var getStudentsDataTask = AuthServiceClient.GetAccountsData(studentIds);
110+
var getStatisticsTask = _solutionsClient.GetTaskSolutionStatistics(course.Id, taskId);
111+
112+
await Task.WhenAll(getStudentsDataTask, getStatisticsTask);
62113

63-
var result = new UserTaskSolutions
114+
var usersData = getStudentsDataTask.Result.ToDictionary(t => t.UserId);
115+
var statistics = getStatisticsTask.Result.ToDictionary(t => t.StudentId);
116+
var groups = course.Groups.ToDictionary(
117+
t => t.Id,
118+
t => t.StudentsIds.Select(s => usersData[s]).ToArray());
119+
120+
var result = new TaskSolutionStatisticsPageData()
64121
{
65-
User = getUserTask.Result,
66-
Solutions = getSolutionsTask.Result,
122+
CourseId = course.Id,
123+
StudentsSolutions = studentIds.Select(studentId => new UserTaskSolutions
124+
{
125+
Solutions = statistics.TryGetValue(studentId, out var studentSolutions)
126+
? studentSolutions.Solutions.Select(t => new GetSolutionModel(t,
127+
t.GroupId is { } groupId ? groups[groupId] : null)).ToArray()
128+
: Array.Empty<GetSolutionModel>(),
129+
User = usersData[studentId]
130+
})
131+
.OrderBy(t => t.User.Surname)
132+
.ThenBy(t => t.User.Name)
133+
.ToArray()
67134
};
68-
return result;
135+
136+
return Ok(result);
69137
}
70138

71139
[Authorize]
@@ -110,13 +178,58 @@ public async Task<IActionResult> GetTaskSolutionsPageData(long taskId)
110178
}
111179

112180
[HttpPost("{taskId}")]
113-
[Authorize]
181+
[Authorize(Roles = Roles.StudentRole)]
114182
[ProducesResponseType(typeof(long), (int)HttpStatusCode.OK)]
115183
public async Task<IActionResult> PostSolution(SolutionViewModel model, long taskId)
116184
{
117-
model.StudentId = UserId;
118-
var result = await _solutionsClient.PostSolution(model, taskId);
119-
return Ok(result);
185+
var solutionModel = new PostSolutionModel(model)
186+
{
187+
StudentId = UserId
188+
};
189+
190+
var course = await _coursesServiceClient.GetCourseByTask(taskId);
191+
if (course is null) return BadRequest();
192+
193+
var courseMate = course.CourseMates.FirstOrDefault(t => t.StudentId == solutionModel.StudentId);
194+
if (courseMate == null || !courseMate.IsAccepted)
195+
return BadRequest($"Студента с id {solutionModel.StudentId} не существует");
196+
197+
if (model.GroupMateIds == null || model.GroupMateIds.Length == 0)
198+
{
199+
var result = await _solutionsClient.PostSolution(taskId, solutionModel);
200+
return Ok(result);
201+
}
202+
203+
var fullStudentsGroup = model.GroupMateIds.ToList();
204+
fullStudentsGroup.Add(solutionModel.StudentId);
205+
var arrFullStudentsGroup = fullStudentsGroup.Distinct().ToArray();
206+
207+
if (arrFullStudentsGroup.Intersect(course.CourseMates.Select(x =>
208+
x.StudentId)).Count() != arrFullStudentsGroup.Length) return BadRequest();
209+
210+
var existedGroup = course.Groups.SingleOrDefault(x =>
211+
x.StudentsIds.Intersect(arrFullStudentsGroup).Count() == arrFullStudentsGroup.Length);
212+
213+
solutionModel.GroupId =
214+
existedGroup?.Id ??
215+
await _coursesServiceClient.CreateCourseGroup(new CreateGroupViewModel(arrFullStudentsGroup, course.Id),
216+
taskId);
217+
218+
await _solutionsClient.PostSolution(taskId, solutionModel);
219+
return Ok(solutionModel);
220+
}
221+
222+
[HttpPost("rateEmptySolution/{taskId}")]
223+
[Authorize(Roles = Roles.LecturerRole)]
224+
public async Task<IActionResult> PostEmptySolutionWithRate(long taskId, SolutionViewModel model)
225+
{
226+
var course = await _coursesServiceClient.GetCourseByTask(taskId);
227+
if (course == null || !course.MentorIds.Contains(UserId)) return Forbid();
228+
if (course.CourseMates.All(t => t.StudentId != model.StudentId))
229+
return BadRequest($"Студента с id {model.StudentId} не существует");
230+
231+
await _solutionsClient.PostEmptySolutionWithRate(taskId, model);
232+
return Ok();
120233
}
121234

122235
[HttpPost("rateEmptySolution/{taskId}")]
@@ -157,26 +270,6 @@ public async Task<IActionResult> DeleteSolution(long solutionId)
157270
return Ok();
158271
}
159272

160-
[HttpPost("{groupId}/{taskId}")]
161-
[Authorize]
162-
[ProducesResponseType(typeof(long), (int)HttpStatusCode.OK)]
163-
public async Task<IActionResult> PostGroupSolution(SolutionViewModel model, long taskId, long groupId)
164-
{
165-
var result = await _solutionsClient.PostGroupSolution(model, taskId, groupId);
166-
return Ok(result);
167-
}
168-
169-
[HttpGet("{groupId}/taskSolutions/{taskId}")]
170-
[Authorize]
171-
[ProducesResponseType(typeof(Solution[]), (int)HttpStatusCode.OK)]
172-
public async Task<IActionResult> GetGroupSolutions(long groupId, long taskId)
173-
{
174-
var result = await _solutionsClient.GetTaskSolutions(groupId, taskId);
175-
return result == null
176-
? NotFound() as IActionResult
177-
: Ok(result);
178-
}
179-
180273
[HttpGet("unratedSolutions")]
181274
[Authorize(Roles = Roles.LecturerRole)]
182275
public async Task<UnratedSolutionPreviews> GetUnratedSolutions(long? taskId)

HwProj.APIGateway/HwProj.APIGateway.API/Models/Solutions/UserTaskSolutions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace HwProj.APIGateway.API.Models.Solutions
55
{
66
public class UserTaskSolutions
77
{
8-
public Solution[] Solutions { get; set; }
8+
public GetSolutionModel[] Solutions { get; set; }
99
public AccountDataDto User { get; set; }
1010
}
1111

HwProj.APIGateway/HwProj.APIGateway.API/Startup.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
using Microsoft.IdentityModel.Tokens;
1616
using Newtonsoft.Json.Linq;
1717

18-
1918
namespace HwProj.APIGateway.API
2019
{
2120
public class Startup

HwProj.AuthService/HwProj.AuthService.Client/AuthServiceClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async Task<AccountDataDto> GetAccountData(string userId)
3232
return await response.DeserializeAsync<AccountDataDto>().ConfigureAwait(false);
3333
}
3434

35-
public async Task<AccountDataDto?[]> GetAccountsData(string[] userIds)
35+
public async Task<AccountDataDto[]> GetAccountsData(string[] userIds)
3636
{
3737
using var httpRequest = new HttpRequestMessage(
3838
HttpMethod.Get,
@@ -45,7 +45,7 @@ public async Task<AccountDataDto> GetAccountData(string userId)
4545
};
4646

4747
var response = await _httpClient.SendAsync(httpRequest);
48-
return await response.DeserializeAsync<AccountDataDto?[]>();
48+
return await response.DeserializeAsync<AccountDataDto[]>();
4949
}
5050

5151
public async Task<Result<TokenCredentials>> Register(RegisterViewModel model)

HwProj.AuthService/HwProj.AuthService.Client/IAuthServiceClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace HwProj.AuthService.Client
88
public interface IAuthServiceClient
99
{
1010
Task<AccountDataDto> GetAccountData(string userId);
11-
Task<AccountDataDto?[]> GetAccountsData(string[] userId);
11+
Task<AccountDataDto[]> GetAccountsData(string[] userId);
1212
Task<Result<TokenCredentials>> Register(RegisterViewModel model);
1313
Task<Result<TokenCredentials>> Login(LoginViewModel model);
1414
Task<Result> Edit(EditAccountViewModel model, string userId);

HwProj.Common/HwProj.Models/CoursesService/ViewModels/CourseViewModels.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.ComponentModel.DataAnnotations;
1+
using System;
2+
using System.ComponentModel.DataAnnotations;
23
using HwProj.Models.AuthService.DTO;
34

45
namespace HwProj.Models.CoursesService.ViewModels
@@ -33,6 +34,7 @@ public class CourseDTO : CoursePreview
3334
public string InviteCode { get; set; }
3435
public CourseMateViewModel[] CourseMates { get; set; }
3536
public HomeworkViewModel[] Homeworks { get; set; }
37+
public GroupViewModel[] Groups { get; set; } = Array.Empty<GroupViewModel>();
3638
}
3739

3840
public class CourseViewModel
@@ -58,4 +60,4 @@ public class CoursePreview
5860
public bool IsCompleted { get; set; }
5961
public string[] MentorIds { get; set; }
6062
}
61-
}
63+
}

HwProj.Common/HwProj.Models/CoursesService/ViewModels/GroupViewModel.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,26 @@ namespace HwProj.Models.CoursesService.ViewModels
66
public class GroupViewModel
77
{
88
public long Id { get; set; }
9-
10-
public long CourseId { get; set; }
11-
12-
public string Name { get; set; }
13-
14-
public List<long> Tasks { get; set; } = new List<long>();
15-
16-
public List<GroupMateViewModel> GroupMates { get; set; } = new List<GroupMateViewModel>();
9+
public string[] StudentsIds { get; set; }
1710
}
1811

1912
public class CreateGroupViewModel
2013
{
21-
[Required]
22-
[RegularExpression(@"^\S+.*", ErrorMessage = "Name shouldn't start with white spaces.")]
2314
public string Name { get; set; }
2415

25-
[Required] public List<GroupMateViewModel> GroupMates { get; set; } = new List<GroupMateViewModel>();
16+
[Required]
17+
public string[] GroupMatesIds { get; set; }
2618

2719
[Required]
2820
public long CourseId { get; set; }
2921

30-
[Required]
31-
public List<long> Tasks { get; set; } = new List<long>();
22+
public CreateGroupViewModel(string[] groupMatesIds, long courseId)
23+
{
24+
Name = "";
25+
GroupMatesIds = groupMatesIds;
26+
CourseId = courseId;
27+
}
28+
3229
}
3330

3431
public class UpdateGroupViewModel
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using System.Linq;
3+
using HwProj.Models.AuthService.DTO;
4+
5+
namespace HwProj.Models.SolutionsService
6+
{
7+
public class GetSolutionModel
8+
{
9+
public GetSolutionModel(Solution model, AccountDataDto[]? groupMates)
10+
{
11+
Id = model.Id;
12+
GithubUrl = model.GithubUrl;
13+
Comment = model.Comment;
14+
StudentId = model.StudentId;
15+
GroupMates = groupMates?
16+
.OrderBy(t => t.Surname)
17+
.ThenBy(t => t.Name)
18+
.ToArray()
19+
?? Array.Empty<AccountDataDto>();
20+
LecturerComment = model.LecturerComment;
21+
PublicationDate = model.PublicationDate;
22+
Rating = model.Rating;
23+
StudentId = model.StudentId;
24+
TaskId = model.TaskId;
25+
State = model.State;
26+
}
27+
28+
public long Id { get; set; }
29+
30+
public string GithubUrl { get; set; }
31+
32+
public string Comment { get; set; }
33+
34+
public SolutionState State { get; set; }
35+
36+
public int Rating { get; set; }
37+
38+
public string StudentId { get; set; }
39+
40+
public long TaskId { get; set; }
41+
42+
public DateTime PublicationDate { get; set; }
43+
44+
public string LecturerComment { get; set; }
45+
46+
public AccountDataDto[] GroupMates { get; set; }
47+
}
48+
}

0 commit comments

Comments
 (0)