Skip to content

Commit dc73299

Browse files
authored
Merge pull request #22 from dicoding-dev/enhancement/enable-full-autograde
feat: enable full autograding based on rejection thresholds
2 parents 7da564b + c94044a commit dc73299

File tree

7 files changed

+232
-19
lines changed

7 files changed

+232
-19
lines changed

src/entities/review-result/course-submission-review/course-submission-review.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ class CourseSubmissionReview {
4040
message: courseSubmissionAcception.messages,
4141
status: ReviewResultStatus.Approve,
4242
checklist: this.submissionCriteriaCheck.reviewChecklistResult,
43-
draft: false,
4443
}
4544
}
4645

@@ -54,7 +53,6 @@ class CourseSubmissionReview {
5453
message: courseSubmissionRejection.messages,
5554
status: ReviewResultStatus.Reject,
5655
checklist: this.submissionCriteriaCheck.reviewChecklistResult,
57-
draft: true,
5856
}
5957
}
6058
}

src/entities/review-result/course-submission-review/review-result.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ interface ReviewResult {
55
message: string,
66
status: ReviewResultStatus,
77
checklist: SubmissionRequirement,
8-
draft: boolean,
98
}
109

1110
export enum ReviewResultStatus {

src/service/report-generator/report-generator.test.ts

Lines changed: 187 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@ function itShouldMeetAGRSReportSpec(report: any): void {
1313
expect(report.is_passed).toBeDefined()
1414
expect(typeof report.is_passed).toEqual('boolean')
1515
expect(report.is_draft).toBeDefined()
16-
expect(typeof report.is_draft).toEqual('boolean')
1716
expect(report.checklist_keys).toBeDefined()
1817
expect(Array.isArray(report.checklist_keys)).toEqual(true)
1918
}
2019

2120
describe('checklist id resolver test', () => {
22-
const reportGenerator = new ReportGenerator('./test/student/review-result/')
2321

2422
it('should generate report properly', function () {
23+
const projectTestPath = './test/student-project/project-with-correct-autoreview-config';
24+
const reportGenerator = new ReportGenerator(projectTestPath)
25+
2526
const submissionRequirement = getSubmissionRequirement()
2627
submissionRequirement.api_can_delete_book.status = true
2728
submissionRequirement.api_can_update_book.status = true
@@ -37,13 +38,11 @@ describe('checklist id resolver test', () => {
3738
status: ReviewResultStatus.Approve,
3839
checklist: submissionRequirement,
3940
message: 'Selamat',
40-
draft: false,
4141
}
4242

43-
const studentProjectPath = './test/student-project/project-with-correct-autoreview-config'
44-
reportGenerator.generate(reviewResult, studentProjectPath)
43+
reportGenerator.generate(reviewResult, projectTestPath)
4544

46-
const result = JSON.parse(fs.readFileSync('./test/student/review-result/report.json').toString())[0]
45+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
4746

4847
itShouldMeetAGRSReportSpec(result)
4948

@@ -58,5 +57,187 @@ describe('checklist id resolver test', () => {
5857
])
5958
expect(result.message).toStrictEqual('<p>Hallo <strong>snder12</strong>, terima kasih telah sabar menunggu. Kami membutuhkan waktu untuk bisa memberikan <em>feedback</em> sekomprehensif mungkin kepada setiap peserta kelas. Dalam kesempatan ini ada &nbsp;4 (empat) hal yang ingin kami sampaikan.&nbsp;</p><p><strong>Pertama</strong>, kami ingin mengucapkan selamat! Karena kamu telah menyelesaikan tugas submission dari kelas Belajar Membuat Aplikasi Back-End untuk Pemula. Jangan lihat bintang yang kamu raih, tapi lihat kemajuan yang sudah kamu capai. Ingat semua <em>expert&nbsp;</em>dahulu pemula.&nbsp;</p><p><strong>K</strong><strong>edua</strong>, kamu boleh bangga karena telah menyelesaikan submission sesuai dengan kriteria yang telah kami tentukan. Mumpung masih hangat semangatnya langsung lanjut kelas selanjutnya yaitu <a href="https://www.dicoding.com/academies/266">Architecting on AWS (Membangun Arsitektur AWS di Cloud)</a> atau <a href="https://www.dicoding.com/academies/271">Belajar Fundamental Aplikasi Back-End</a>.&nbsp;</p><p><strong>Ketiga</strong>, beberapa lulusan tidak tahu mereka memiliki akses kelas selamanya. Sebagai informasi kelas Dicoding selalu <em>update&nbsp;</em>sehingga memiliki perbedaan minimal 30% dari sejak kelas dirilis. Silakan mampir kembali untuk melihat materi saat kamu membutuhkan <em>update</em>.&nbsp;</p><p><strong>K</strong><strong>eempat</strong>, karena sudah praktik langsung maka kamu sudah menguasai ilmu kelas dasar ini antara 75-90%. Salah satu cara agar meningkatkan penguasaan ilmu agar bisa lebih maksimal (&gt;90%) adalah dengan memperbanyak latihan atau mengajarkan ilmu kepada orang lain.</p><p>Salah satu misi Dicoding adalah menyebarkan ilmu yang bermanfaat. Kami berusaha membangun kurikulum standar global dengan harapan agar developer Indonesia bisa menjadi jawara di negeri sendiri. Namun misi ini tidak akan tercapai tanpa kolaborasi dari kita semua.</p><hr><p>Supaya aplikasimu menjadi lebih baik lagi, berikut <em>beberapa</em> <em>catatan</em> terkait submission kamu:</p><ul>Selamat</ul><hr><p dir="ltr">Silakan berkunjung ke <a href="https://www.dicoding.com/academies/261/discussions" rel="noopener noreferrer" target="_blank">forum diskusi</a> untuk mengasah kembali penguasaan ilmu kamu dan membuat ilmu kamu bisa semakin bermanfaat dengan membantu developer yang lain.&nbsp;</p><p dir="ltr">Terima kasih telah membantu misi kami. Kesuksesan developer Indonesia adalah energi bagi kami. Jika memiliki pertanyaan terkait hasil submission, silakan mengikuti prosedur&nbsp;<a href="https://help.dicoding.com/academy-dicoding/prosedur-banding-hasil-review-submission-kelas" rel="noopener noreferrer" target="_blank">berikut</a>.</p><hr><p style="text-align: right;"><em>Salam</em></p><p style="text-align: right;"><span style="color: rgb(226, 80, 65);">Dicoding Reviewer</span></p>')
6059
});
60+
61+
describe('when student got reject', () => {
62+
// why null? because I expect grading mode is set in autograder runner level
63+
it('should set `is_draft` to null when rejected count below 3', () => {
64+
const projectTestPath = './test/student-project/rejection-bellow-3';
65+
const reportGenerator = new ReportGenerator(projectTestPath)
66+
67+
const submissionRequirement = getSubmissionRequirement()
68+
69+
submissionRequirement.api_can_delete_book.status = false
70+
submissionRequirement.api_can_update_book.status = false
71+
submissionRequirement.api_can_get_detail_book.status = false
72+
submissionRequirement.api_can_get_all_book.status = true
73+
submissionRequirement.api_can_insert_book.status = true
74+
submissionRequirement.project_have_correct_runner_script.status = true
75+
submissionRequirement.project_have_correct_port.status = true
76+
77+
78+
const reviewResult: ReviewResult = {
79+
rating: 0,
80+
status: ReviewResultStatus.Reject,
81+
checklist: submissionRequirement,
82+
message: 'Maaf',
83+
}
84+
85+
reportGenerator.generate(reviewResult, projectTestPath);
86+
87+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
88+
itShouldMeetAGRSReportSpec(result);
89+
expect(result.is_draft).toBeNull()
90+
});
91+
92+
it('should set `is_draft` to true when rejected count is 3 or above', () => {
93+
const projectTestPath = './test/student-project/rejection-is-3';
94+
const reportGenerator = new ReportGenerator(projectTestPath)
95+
96+
const submissionRequirement = getSubmissionRequirement()
97+
98+
submissionRequirement.api_can_delete_book.status = false
99+
submissionRequirement.api_can_update_book.status = false
100+
submissionRequirement.api_can_get_detail_book.status = false
101+
submissionRequirement.api_can_get_all_book.status = true
102+
submissionRequirement.api_can_insert_book.status = true
103+
submissionRequirement.project_have_correct_runner_script.status = true
104+
submissionRequirement.project_have_correct_port.status = true
105+
106+
107+
const reviewResult: ReviewResult = {
108+
rating: 5,
109+
status: ReviewResultStatus.Reject,
110+
checklist: submissionRequirement,
111+
message: 'Maaf',
112+
}
113+
114+
reportGenerator.generate(reviewResult, projectTestPath);
115+
116+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
117+
itShouldMeetAGRSReportSpec(result);
118+
expect(result.is_draft).toEqual(true);
119+
});
120+
121+
it('should set `is_draft` to true and set special message when rejected count is 5 or above', () => {
122+
const projectTestPath = './test/student-project/rejection-is-5';
123+
const reportGenerator = new ReportGenerator(projectTestPath)
124+
125+
const submissionRequirement = getSubmissionRequirement()
126+
127+
submissionRequirement.api_can_delete_book.status = false
128+
submissionRequirement.api_can_update_book.status = false
129+
submissionRequirement.api_can_get_detail_book.status = false
130+
submissionRequirement.api_can_get_all_book.status = true
131+
submissionRequirement.api_can_insert_book.status = true
132+
submissionRequirement.project_have_correct_runner_script.status = true
133+
submissionRequirement.project_have_correct_port.status = true
134+
135+
136+
const reviewResult: ReviewResult = {
137+
rating: 5,
138+
status: ReviewResultStatus.Reject,
139+
checklist: submissionRequirement,
140+
message: 'Maaf',
141+
}
142+
143+
144+
reportGenerator.generate(reviewResult, projectTestPath);
145+
146+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
147+
itShouldMeetAGRSReportSpec(result);
148+
expect(result.is_draft).toEqual(true);
149+
expect(result.message).toEqual('<p></p>');
150+
expect(result.note).toEqual('Dear reviewer, karena siswa sudah di-reject 5 kali atau lebih. Minta tolong review secara lebih intens ya! ^_^')
151+
})
152+
});
153+
154+
describe('when student got approve', () => {
155+
it('should set `is_draft` to null when rejected count below 3', () => {
156+
const projectTestPath = './test/student-project/rejection-bellow-3';
157+
const reportGenerator = new ReportGenerator(projectTestPath)
158+
159+
const submissionRequirement = getSubmissionRequirement()
160+
161+
submissionRequirement.api_can_delete_book.status = true
162+
submissionRequirement.api_can_update_book.status = true
163+
submissionRequirement.api_can_get_detail_book.status = true
164+
submissionRequirement.api_can_get_all_book.status = true
165+
submissionRequirement.api_can_insert_book.status = true
166+
submissionRequirement.project_have_correct_runner_script.status = true
167+
submissionRequirement.project_have_correct_port.status = true
168+
169+
170+
const reviewResult: ReviewResult = {
171+
rating: 5,
172+
status: ReviewResultStatus.Approve,
173+
checklist: submissionRequirement,
174+
message: 'Maaf',
175+
}
176+
177+
reportGenerator.generate(reviewResult, projectTestPath);
178+
179+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
180+
itShouldMeetAGRSReportSpec(result);
181+
expect(result.is_draft).toBeNull()
182+
});
183+
184+
it('should set `is_draft` to null when rejected count is 3 or above', () => {
185+
const projectTestPath = './test/student-project/rejection-is-3';
186+
const reportGenerator = new ReportGenerator(projectTestPath)
187+
188+
const submissionRequirement = getSubmissionRequirement()
189+
190+
submissionRequirement.api_can_delete_book.status = true
191+
submissionRequirement.api_can_update_book.status = true
192+
submissionRequirement.api_can_get_detail_book.status = true
193+
submissionRequirement.api_can_get_all_book.status = true
194+
submissionRequirement.api_can_insert_book.status = true
195+
submissionRequirement.project_have_correct_runner_script.status = true
196+
submissionRequirement.project_have_correct_port.status = true
197+
198+
199+
const reviewResult: ReviewResult = {
200+
rating: 5,
201+
status: ReviewResultStatus.Approve,
202+
checklist: submissionRequirement,
203+
message: 'Maaf',
204+
}
205+
206+
reportGenerator.generate(reviewResult, projectTestPath);
207+
208+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
209+
itShouldMeetAGRSReportSpec(result);
210+
expect(result.is_draft).toBeNull()
211+
});
212+
213+
it('should set `is_draft` to null when rejected count is 5 or above', () => {
214+
const projectTestPath = './test/student-project/rejection-is-5';
215+
const reportGenerator = new ReportGenerator(projectTestPath)
216+
217+
const submissionRequirement = getSubmissionRequirement()
218+
219+
submissionRequirement.api_can_delete_book.status = true
220+
submissionRequirement.api_can_update_book.status = true
221+
submissionRequirement.api_can_get_detail_book.status = true
222+
submissionRequirement.api_can_get_all_book.status = true
223+
submissionRequirement.api_can_insert_book.status = true
224+
submissionRequirement.project_have_correct_runner_script.status = true
225+
submissionRequirement.project_have_correct_port.status = true
226+
227+
228+
const reviewResult: ReviewResult = {
229+
rating: 5,
230+
status: ReviewResultStatus.Approve,
231+
checklist: submissionRequirement,
232+
message: 'Maaf',
233+
}
234+
235+
reportGenerator.generate(reviewResult, projectTestPath);
236+
237+
const result = JSON.parse(fs.readFileSync(`${projectTestPath}/report.json`).toString())[0]
238+
itShouldMeetAGRSReportSpec(result);
239+
expect(result.is_draft).toBeNull()
240+
});
241+
});
61242
})
62243

src/service/report-generator/report-generator.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@ class ReportGenerator {
1818

1919
const autoReviewConfig = this.getAutoReviewConfig(submissionPath)
2020

21+
const isMassiveRejection = autoReviewConfig.rejected_count >= 5
22+
23+
const isNeedSpecialAttention = isMassiveRejection && !isApproved;
24+
2125
const summary = {
2226
submission_id: autoReviewConfig?.id,
2327
review_id: Date.now(),
2428
is_approved: isApproved,
2529
rating: reviewResult.rating,
26-
message: this.getReviewMessageWithTemplate(reviewResult, autoReviewConfig),
30+
message: isNeedSpecialAttention ? '<p></p>' : this.getReviewMessageWithTemplate(reviewResult, autoReviewConfig),
31+
note: isNeedSpecialAttention ? 'Dear reviewer, karena siswa sudah di-reject 5 kali atau lebih. Minta tolong review secara lebih intens ya! ^_^' : undefined,
2732
submission_path: submissionPath,
2833
checklist: reviewResult.checklist,
2934
checklist_keys: this.getCompletedChecklist(reviewResult),
@@ -41,18 +46,18 @@ class ReportGenerator {
4146
raiseDomainEvent('report generated')
4247
}
4348

44-
private getDraftDecision(isApproved: boolean, autoReviewConfig: any): boolean {
45-
const allowedCoursesThatFullyGrading = [
46-
342, // Back-End Pemula with Google Cloud
47-
261, // Back-End Pemula with AWS
48-
]
49+
private getDraftDecision(isApproved: boolean, autoReviewConfig: any): boolean | null {
50+
if (isApproved) {
51+
return null;
52+
}
53+
54+
const rejectedCount = autoReviewConfig.rejected_count;
4955

50-
if (allowedCoursesThatFullyGrading.includes(autoReviewConfig.course_id)) {
51-
// set `draft` to false, if approved is true
52-
return !isApproved
56+
if (rejectedCount < 3) {
57+
return null;
5358
}
5459

55-
return true
60+
return true;
5661
}
5762

5863
private getCompletedChecklist(reviewResult: ReviewResult) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"id": 667273,
3+
"submitter_name": "Dimas Saputra",
4+
"submitter_username": "dimassaputra",
5+
"submitter_birthday": "2020-01-01 00:00:00",
6+
"quiz_id": 32712,
7+
"course_id": 610,
8+
"rejected_count": 2,
9+
"submission_link": "https://link-to-submission.com/"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"id": 667273,
3+
"submitter_name": "Dimas Saputra",
4+
"submitter_username": "dimassaputra",
5+
"submitter_birthday": "2020-01-01 00:00:00",
6+
"quiz_id": 32712,
7+
"course_id": 610,
8+
"rejected_count": 3,
9+
"submission_link": "https://link-to-submission.com/"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"id": 667273,
3+
"submitter_name": "Dimas Saputra",
4+
"submitter_username": "dimassaputra",
5+
"submitter_birthday": "2020-01-01 00:00:00",
6+
"quiz_id": 32712,
7+
"course_id": 610,
8+
"rejected_count": 5,
9+
"submission_link": "https://link-to-submission.com/"
10+
}

0 commit comments

Comments
 (0)