Skip to content

Commit

Permalink
Merge pull request #390 from fujaba/feat/assignment-passing
Browse files Browse the repository at this point in the history
Assignment Passing Points
  • Loading branch information
Clashsoft authored Nov 27, 2023
2 parents 9842474 + 576daec commit 5b2455f
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 10 deletions.
1 change: 1 addition & 0 deletions frontend/src/app/assignment/model/assignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class Assignment {

classroom?: ClassroomInfo;

passingPoints?: number;
tasks: Task[];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,23 @@
</td>
}
@for (solution of student.solutions;track solution;let i = $index) {
<td class="text-end"
[class.text-danger]="!solution"
[class.text-muted]="solution && solution.points === undefined">
<a class="d-block text-body text-decoration-none"
[routerLink]="solution && ['/assignments', course?.assignments?.[i], 'solutions', solution._id]"
[ngbTooltip]="solution ? 'View Solution' : 'No Solution'" container="body">

{{ solution?.points || 0 }}</a>
<td class="text-end">
@if (!solution) {
<span class="d-block text-danger" ngbTooltip="No Solution">0</span>
} @else {
<a
[class]="[
'd-block',
'text-decoration-none',
solution.points === undefined ? 'text-muted'
: solution.points < assignmentPoints[i] ? 'text-warning'
: 'text-body'
] // TODO make passing threshold configurable"
[routerLink]="['/assignments', course?.assignments?.[i], 'solutions', solution._id]"
ngbTooltip="View Solution">
{{ solution.points ?? '-' }}
</a>
}
</td>
<td [style.background-color]="solution?.assignee | assigneeColor">
@if (solution && course) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {ReadAssignmentDto} from "../../../model/assignment";
import {AssigneeService} from "../../../services/assignee.service";
import {BulkUpdateAssigneeDto} from "../../../model/assignee";
import {ToastService} from "@mean-stream/ngbx";
import {TaskService} from "../../../services/task.service";

@Component({
selector: 'app-students',
Expand All @@ -19,6 +20,7 @@ export class StudentsComponent implements OnInit {
course?: Course;
students?: CourseStudent[];
assignments: (ReadAssignmentDto | undefined)[] = [];
assignmentPoints: number[] = [];
assignmentNames: string[] = [];
assignees: string[] = [];

Expand All @@ -30,6 +32,7 @@ export class StudentsComponent implements OnInit {
private assignmentService: AssignmentService,
private assigneeService: AssigneeService,
private toastService: ToastService,
private taskService: TaskService,
) {
}

Expand All @@ -41,6 +44,7 @@ export class StudentsComponent implements OnInit {
).subscribe(assignments => {
this.assignments = assignments;
this.assignmentNames = this.courseService.getAssignmentNames(assignments);
this.assignmentPoints = assignments.map(a => a ? a.passingPoints ?? this.taskService.sumPositivePoints(a.tasks) / 2 : 0);
});

this.route.params.pipe(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
<div class="mb-3">
<label for="passing-points" class="form-label">Passing Points</label>
<div class="input-group">
<input type="number" class="form-control" id="passing-points" [(ngModel)]="context.assignment.passingPoints" (change)="context.saveDraft()"/>
<button class="btn btn-outline-secondary input-group-btn bi-magic" ngbTooltip="Calculate Automatically" (click)="setPassingPoints()"></button>
</div>
<div class="form-text">
The minimum number of points required to pass the assignment.
Defaults to 50% of the maximum points.
</div>
</div>
<div class="btn-group mb-3" role="group">
<button class="btn btn-primary" [class.active]="markdown !== undefined" (click)="switchMarkdown(true)">Markdown</button>
<button class="btn btn-primary" [class.active]="markdown === undefined" (click)="switchMarkdown(false)">List</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Component, OnDestroy} from '@angular/core';
import {AssignmentContext} from '../../../services/assignment.context';
import {TaskMarkdownService} from '../task-markdown.service';
import {TaskService} from "../../../services/task.service";

@Component({
selector: 'app-edit-assignment-tasks',
Expand All @@ -12,6 +13,7 @@ export class TasksComponent implements OnDestroy {

constructor(
private taskMarkdownService: TaskMarkdownService,
private taskService: TaskService,
public context: AssignmentContext,
) {
}
Expand All @@ -33,4 +35,9 @@ export class TasksComponent implements OnDestroy {
}
}

setPassingPoints() {
const tasks = this.markdown ? this.taskMarkdownService.parseTasks(this.markdown) : this.context.assignment.tasks;
this.context.assignment.passingPoints = this.taskService.sumPositivePoints(tasks) / 2;
this.context.saveDraft();
}
}
7 changes: 7 additions & 0 deletions services/apps/assignments/src/assignment/assignment.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
IsNotEmpty,
IsNumber,
IsOptional,
IsPositive,
IsString,
IsUrl,
ValidateNested,
Expand Down Expand Up @@ -185,6 +186,12 @@ export class Assignment {
@Type(() => ClassroomInfo)
classroom?: ClassroomInfo;

@Prop()
@ApiPropertyOptional()
@IsOptional()
@IsPositive()
passingPoints?: number;

@Prop()
@ApiProperty({type: [Task]})
@IsArray()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export class StatisticsService {
}

private async solutionStatistics(assignment: AssignmentDocument): Promise<SolutionStatistics> {
const passingMin = assignment.tasks.reduce((a, c) => c.points > 0 ? a + c.points : a, 0) / 2;
const passingPoints = assignment.passingPoints ?? assignment.tasks.reduce((a, c) => c.points > 0 ? a + c.points : a, 0) / 2;
const [result] = await this.solutionService.model.aggregate([
{$match: {assignment: assignment._id}},
{
Expand All @@ -172,7 +172,7 @@ export class StatisticsService {
total: {$sum: 1},
points: {$sum: '$points'},
graded: {$sum: {$cond: [{$gt: ['$points', null]}, 1, 0]}},
passed: {$sum: {$cond: [{$gte: ['$points', passingMin]}, 1, 0]}},
passed: {$sum: {$cond: [{$gte: ['$points', passingPoints]}, 1, 0]}},
},
},
]);
Expand Down

0 comments on commit 5b2455f

Please sign in to comment.