-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Refactor] useQuiz hook 구현 #170
Changes from all commits
55b3046
550388e
86f40c5
c680411
eb8643d
0c9b5c1
8433b26
828e732
78a49be
0b17f7a
5c79e38
15256f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/* eslint-disable @emotion/syntax-preference */ | ||
import styled from '@emotion/styled'; | ||
|
||
// TODO: 전역 스타일 컬러 적용 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/* eslint-disable @emotion/syntax-preference */ | ||
import styled from '@emotion/styled'; | ||
|
||
import { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as useQuiz } from './useQuiz'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { getPostsFromChannel, getPosts } from '@/api/QuizServices'; | ||
|
||
import type { PostAPI } from '@/interfaces/PostAPI'; | ||
import type { QuizContent } from '@/interfaces/Quiz'; | ||
|
||
export interface Quiz { | ||
_id: string; | ||
question: string; | ||
answerDescription: string; | ||
category: string; | ||
difficulty: number; | ||
importance: number; | ||
answerType: 'trueOrFalse' | 'multipleChoice' | 'shortAnswer'; | ||
answer: string; | ||
} | ||
|
||
/** | ||
* | ||
* @param array 기존 소스로 사용되는 배열 | ||
* @param count 섞은 뒤 반환할 개수 | ||
* @returns 섞인 count의 길이를 갖는 배열 | ||
*/ | ||
const shuffle = <T = unknown>(array: T[], count: number): T[] => { | ||
const ret = [...array]; | ||
|
||
for (let i = 0; i < array.length - 1; i += 1) { | ||
const j = Math.floor(Math.random() * (i + 1)); | ||
[ret[i], ret[j]] = [ret[j], ret[i]]; | ||
} | ||
|
||
return ret.slice(0, count < ret.length ? count : ret.length); | ||
}; | ||
|
||
export const calculateScore = (quizzes: Quiz[], userAnswers: string[]) => { | ||
// 전부 선택하지 않았거나 user가 임의로 조작했다면 0점을 부여한다. | ||
if (quizzes.length !== userAnswers.filter((answer) => answer).length) | ||
return 0; | ||
// filter corrected quizzes and add scores | ||
return quizzes | ||
.filter((quiz, index) => quiz.answer === userAnswers[index]) | ||
.reduce((acc, cur) => acc + cur.difficulty * 10, 0); | ||
}; | ||
|
||
/** | ||
* Quiz 인터페이스를 구현하는 팩토리 함수 | ||
*/ | ||
const createQuiz = (post: PostAPI): Quiz => { | ||
const quizContent = JSON.parse(post.title) as QuizContent; | ||
|
||
return { | ||
_id: post._id, | ||
question: quizContent.question, | ||
answerDescription: quizContent.answerDescription, | ||
answer: quizContent.answer, | ||
answerType: quizContent.answerType, | ||
category: quizContent.category, | ||
difficulty: quizContent.difficulty, | ||
importance: quizContent.importance, | ||
}; | ||
}; | ||
|
||
/** | ||
* QuizSolve에 사용되는 quiz use cases | ||
*/ | ||
class QuizService { | ||
static async getShuffledQuizzes(count: number) { | ||
try { | ||
const posts = await getPosts(); | ||
const quizzes = posts.map((post) => createQuiz(post)); | ||
|
||
return shuffle(quizzes, count); | ||
} catch (error) { | ||
throw new Error('error occurred at QuizService.getShuffledQuizzes.'); | ||
} | ||
} | ||
|
||
static async getQuizzesFromQuizSet(channelId: string) { | ||
try { | ||
const posts = await getPostsFromChannel(channelId); | ||
const quizzes = posts.map((post) => createQuiz(post)).reverse(); | ||
|
||
return quizzes; | ||
} catch (error) { | ||
throw new Error('error occurred at QuizService.getQuizzesFromQuizSet.'); | ||
} | ||
} | ||
} | ||
Comment on lines
+65
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분에 대한 질문 답변드리기 전에 질문이 이해가 안 가네요 ㅠ 질문과 별개로 리뷰를 드리자면 |
||
|
||
export default QuizService; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { useCallback, useState } from 'react'; | ||
|
||
import QuizServices from './useQuiz.helper'; | ||
|
||
import type { Quiz } from './useQuiz.helper'; | ||
|
||
type ReturnType = [ | ||
Quiz[], | ||
(count: number) => Promise<void>, | ||
(channelId: string) => Promise<void> | ||
]; | ||
Comment on lines
+7
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
const useQuiz = (): ReturnType => { | ||
const [quizzes, setQuizzes] = useState<Quiz[]>([]); | ||
|
||
const getRandomQuizzes = useCallback(async (count: number) => { | ||
try { | ||
const data = await QuizServices.getShuffledQuizzes(count); | ||
setQuizzes(data); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}, []); | ||
|
||
const getQuizzesFromQuizSet = useCallback(async (channelId: string) => { | ||
try { | ||
const data = await QuizServices.getQuizzesFromQuizSet(channelId); | ||
setQuizzes(data); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
}, []); | ||
|
||
return [quizzes, getRandomQuizzes, getQuizzesFromQuizSet]; | ||
}; | ||
|
||
export default useQuiz; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2
Quiz
를QuizType
으로 네이밍을 하신 이유가 궁금합니다