Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab2129a965 | ||
|
|
d8ef029bef | ||
|
|
995e69e302 | ||
|
|
698bb0e99f | ||
|
|
3c0455bff7 | ||
|
|
ed109df111 | ||
|
|
e8de49732b | ||
|
|
123261aad3 | ||
|
|
1ed458a9c1 | ||
|
|
3da5840e8b | ||
|
|
ed30cf85dc |
No files matched your search
@@ -2,6 +2,7 @@ package com.example.questionbank.repository;
|
|||||||
|
|
||||||
import com.example.questionbank.domain.ExamAttempt;
|
import com.example.questionbank.domain.ExamAttempt;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -14,6 +15,8 @@ import org.springframework.stereotype.Repository;
|
|||||||
*/
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
public interface ExamAttemptRepository extends JpaRepository<ExamAttempt, Long> {
|
public interface ExamAttemptRepository extends JpaRepository<ExamAttempt, Long> {
|
||||||
|
List<ExamAttempt> findAllByUserLogin(String login);
|
||||||
|
|
||||||
@Query("select examAttempt from ExamAttempt examAttempt where examAttempt.user.login = ?#{authentication.name}")
|
@Query("select examAttempt from ExamAttempt examAttempt where examAttempt.user.login = ?#{authentication.name}")
|
||||||
List<ExamAttempt> findByUserIsCurrentUser();
|
List<ExamAttempt> findByUserIsCurrentUser();
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.example.questionbank.repository;
|
|||||||
|
|
||||||
import com.example.questionbank.domain.Question;
|
import com.example.questionbank.domain.Question;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -14,6 +15,8 @@ import org.springframework.stereotype.Repository;
|
|||||||
*/
|
*/
|
||||||
@Repository
|
@Repository
|
||||||
public interface QuestionRepository extends JpaRepository<Question, Long> {
|
public interface QuestionRepository extends JpaRepository<Question, Long> {
|
||||||
|
List<Question> findAllBySubjectIdAndActiveTrue(Long subjectId);
|
||||||
|
|
||||||
default Optional<Question> findOneWithEagerRelationships(Long id) {
|
default Optional<Question> findOneWithEagerRelationships(Long id) {
|
||||||
return this.findOneWithToOneRelationships(id);
|
return this.findOneWithToOneRelationships(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.example.questionbank.service.quiz;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.enumeration.OptionKey;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ExamScoringService {
|
||||||
|
|
||||||
|
public ScoringResult score(OptionKey correctOption, OptionKey selectedOption) {
|
||||||
|
boolean correct = selectedOption != null && selectedOption == correctOption;
|
||||||
|
return new ScoringResult(correct, correct ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record ScoringResult(boolean correct, int awardedPoints) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.enumeration.OptionKey;
|
||||||
|
|
||||||
|
public record AnswerResult(
|
||||||
|
Long questionId,
|
||||||
|
String questionText,
|
||||||
|
OptionKey selectedOption,
|
||||||
|
String selectedContent,
|
||||||
|
boolean correct,
|
||||||
|
int awardedPoints,
|
||||||
|
String explanation
|
||||||
|
) {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.enumeration.OptionKey;
|
||||||
|
|
||||||
|
public record ChoiceView(OptionKey optionKey, String content, Integer displayOrder) {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public record ExamAttemptStartResult(Long attemptId, Instant startedAt) {}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.enumeration.AttemptStatus;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
public record ExamAttemptSummary(
|
||||||
|
Long attemptId,
|
||||||
|
Long subjectId,
|
||||||
|
String subjectName,
|
||||||
|
Instant startedAt,
|
||||||
|
Instant submittedAt,
|
||||||
|
AttemptStatus status,
|
||||||
|
Integer score
|
||||||
|
) {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ExamQuestionView(Long questionId, String prompt, List<ChoiceView> choices) {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record ExamResult(Long attemptId, int totalScore, Instant submittedAt, List<AnswerResult> answers) {}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public record StartExamRequest(@NotNull Long subjectId) {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.enumeration.OptionKey;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public record SubmitAnswerRequest(@NotNull Long questionId, OptionKey selectedOption) {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.example.questionbank.web.rest.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public record SubmitExamRequest(@NotEmpty List<@Valid SubmitAnswerRequest> answers) {}
|
||||||
@@ -48,7 +48,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
const initRelationships = () => {
|
const initRelationships = () => {
|
||||||
questionService()
|
questionService()
|
||||||
.retrieve()
|
.retrieve({ page: 0, size: 100 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
questions.value = res.data;
|
questions.value = res.data;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
const initRelationships = () => {
|
const initRelationships = () => {
|
||||||
subjectService()
|
subjectService()
|
||||||
.retrieve()
|
.retrieve({ page: 0, size: 100 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
subjects.value = res.data;
|
subjects.value = res.data;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,7 +70,14 @@ export default defineComponent({
|
|||||||
created(): void {},
|
created(): void {},
|
||||||
methods: {
|
methods: {
|
||||||
save(): void {
|
save(): void {
|
||||||
|
const message = this.subject.id ? '이 과목의 수정 내용을 저장하시겠습니까?' : '새 과목을 등록하시겠습니까?';
|
||||||
|
|
||||||
|
if (!window.confirm(message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
|
|
||||||
if (this.subject.id) {
|
if (this.subject.id) {
|
||||||
this.subjectService()
|
this.subjectService()
|
||||||
.update(this.subject)
|
.update(this.subject)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export default defineComponent({
|
|||||||
const subjectService = inject('subjectService', () => new SubjectService());
|
const subjectService = inject('subjectService', () => new SubjectService());
|
||||||
const alertService = inject('alertService', () => useAlertService(), true);
|
const alertService = inject('alertService', () => useAlertService(), true);
|
||||||
|
|
||||||
const itemsPerPage = ref(20);
|
const itemsPerPage = ref(10);
|
||||||
const queryCount: Ref<number> = ref(null);
|
const queryCount: Ref<number> = ref(null);
|
||||||
const page: Ref<number> = ref(1);
|
const page: Ref<number> = ref(1);
|
||||||
const propOrder = ref('id');
|
const propOrder = ref('id');
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<router-link :to="{ name: 'SubjectView', params: { subjectId: subject.id } }">{{ subject.id }}</router-link>
|
<router-link :to="{ name: 'SubjectView', params: { subjectId: subject.id } }">{{ subject.id }}</router-link>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ subject.name }}</td>
|
<td>📘{{ subject.name }}</td>
|
||||||
<td>{{ subject.description }}</td>
|
<td>{{ subject.description }}</td>
|
||||||
<td>{{ subject.active }}</td>
|
<td>{{ subject.active }}</td>
|
||||||
<td class="text-end">
|
<td class="text-end">
|
||||||
@@ -106,7 +106,11 @@
|
|||||||
<jhi-item-count :page="page" :total="queryCount" :items-per-page="itemsPerPage"></jhi-item-count>
|
<jhi-item-count :page="page" :total="queryCount" :items-per-page="itemsPerPage"></jhi-item-count>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-center">
|
<div class="d-flex justify-content-center">
|
||||||
<b-pagination size="md" :total-rows="totalItems" v-model="page" :per-page="itemsPerPage"></b-pagination>
|
<p>전체 과목 수: {{ totalItems }}개</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
<b-pagination :total-rows="totalItems" v-model="page" :per-page="itemsPerPage"></b-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.example.questionbank.service.quiz;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import com.example.questionbank.domain.enumeration.OptionKey;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ExamScoringServiceTest {
|
||||||
|
|
||||||
|
private final ExamScoringService service = new ExamScoringService();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void correctAnswerGetsOnePoint() {
|
||||||
|
var result = service.score(OptionKey.A, OptionKey.A);
|
||||||
|
|
||||||
|
assertTrue(result.correct());
|
||||||
|
assertEquals(1, result.awardedPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void wrongAnswerGetsZeroPoints() {
|
||||||
|
var result = service.score(OptionKey.A, OptionKey.D);
|
||||||
|
|
||||||
|
assertFalse(result.correct());
|
||||||
|
assertEquals(0, result.awardedPoints());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void unansweredQuestionGetsZeroPoints() {
|
||||||
|
var result = service.score(OptionKey.A, null);
|
||||||
|
|
||||||
|
assertFalse(result.correct());
|
||||||
|
assertEquals(0, result.awardedPoints());
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user