지난번 포스트에서 테스트 질문에 대한 점수를 누적해서 결과를 보여주는 페이지를 작업했었으니,
이번엔 MBTI처럼 특정 성향에 맞는 답변을 노출할 수 있는 페이지를 만들어보자.
🤗 이번 포스트로 이런게 만들어집니다. 🤗
- 총 문항 :
- 소요시간 :
우선 생각해봐야 할게, MBTI를 보면 E와 I와 S, F와 T, P와 J로 나뉘고
각각의 성향에 대한 질문을 총 합하여 조금 더 높은 쪽으로 보여준다.
즉 EI, SN, FT, PJ 에대한 각각의 질문들을 받아 총계를 내서 높은 쪽으로 내주는데..
이때 문제는 문제가 짝수일때 딱 50:50으로 나뉘었을 때 무엇을 표시해 줄지를 결정해야 할 것 같다.
문제가 홀수가 아닌게 제일 베스트긴 하겠지만..
기본적으로는 앞의 성향이 체크되면 좋을 것 같다.
우선 AB, CD 2가지 경우의 수로 작업을 해볼 건데
가짓수가 많아질수록 답변의 가짓수가 많아지니 적당한 숫자로 타협하는 게 좋을 것 같다.
1 성향 - 2가지 답변
2 성향 - 4가지
3 성향 - 8가지
4 성향 - 16가지
...
지금은 테스트 결과를 8개 16개 만들기엔 너무 힘드니까 우선 2 성향 정도로만 작업해 보자.
JSON
우선 지난번에 만들었단 type: "point"의 자료 형태를 조금 바꿔보자.
{
"title": "나와 닮은 동물 찾기",
"description": "🐱🦁🐯🦒🦊🦝🐮🐷🐗🐭🐰🐻",
"type": "indicator",
"startButtonText": "닮은 동물 찾아보기",
"data": [
{
"question": "당신은 어떤 음식을 선호하시나요?",
"type": "AB",
"imageUrl": "",
"answerList": [
{
"answer": "🥗 신선한 채소와 새콤한 과일",
"indicator": "A"
},{
"answer": "🍖 품질좋은 고기",
"indicator": "B"
}
]
},{
"question": "만약 당신이 동물이라면 어디에 살고 있나요?",
"type": "AB",
"imageUrl": "",
"answerList": [
{
"answer": "🌱 푸르른 초원",
"indicator": "A"
},{
"answer": "🌳 울창한 숲",
"indicator": "B"
}
]
},{
"question": "사람들과 어울리는 것을 좋아하나요?",
"type": "CD",
"imageUrl": "",
"answerList": [
{
"answer": "😀 네, 좋아해요!",
"indicator": "C"
},{
"answer": "😐 별로 좋아하지 않아요.",
"indicator": "D"
}
]
},{
"question": "새로운 사람들과 친해지는 것을 좋아하나요?",
"type": "CD",
"imageUrl": "",
"answerList": [
{
"answer": "😘 아주 좋아해요!",
"indicator": "C"
},{
"answer": "😑 별로 좋아하지 않아요.",
"indicator": "D"
}
]
}
],
"result": [
{
"title": "🐶 강아지",
"description": "당신은 강아지와 닮았네요.",
"imageUrl": "",
"indicator": "AC",
"relation": {
"good": "AD",
"bad": "BC"
}
},{
"title": "😺 고양이",
"description": "당신은 고양이와 닮았네요.",
"imageUrl": "",
"indicator": "AD",
"relation": {
"good": "BC",
"bad": "AC"
}
},{
"title": "🦁 사자",
"description": "당신은 사자와 닮았네요.",
"imageUrl": "",
"indicator": "BC",
"relation": {
"good": "AC",
"bad": "AD"
}
},{
"title": "🐯 호랑이",
"description": "당신은 호랑이와 닮았네요.",
"imageUrl": "",
"indicator": "BD",
"relation": {
"good": "AD",
"bad": "BC"
}
}
]
}
질문마다 답변에 기존 point 대신 indicator를 추가해서 각각 어떤 성향인지 문자열로 받기로 했다.
result는 조합된 문자열을 기준으로 결과를 표시해 줄 거고 relation은 흔히 보는 당신과 어울리는 유형 /
당신과 어울리지 않는 유형을 위해 임시로 표시했다.
+ 각각의 질문마다 type으로 AB인지 CD인지 타입을 추가해 주었다.
항상 생각하는 거지만 이런 건 코딩하는 거보다 콘텐츠 생각하고 만드는 게 대단한 듯..
다음은 html은 건드릴 필요 없을 것 같고, js에서 기존에 if(type === "point")일 때인 것만 수정해 주면 될 것 같다.
point가 들어가는 부분만 체크해서 indicator일 때를 추가해 주면 될 것 같다.
JS - Case : type: "indicator"
class TestPage {
constructor(data) {
...
if(data.type === 'point'){
this.point = 0;
this.type = data.type;
}
if(data.type === 'indicator'){
this.indicator = {};
this.indicatorType = Object.values(this.question).map(({type}) => type).filter((el, idx, arr) => arr.indexOf(el) === idx);
this.type = data.type;
}
this.init();
}
init() {
...
}
start() {
...
}
next() {
...
}
renderQuestion() {
...
for(let i = 0; i < this.question[this.current].answerList.length; i++){
...
button.addEventListener('click', () => {
if(this.type === "point") this.point += this.question[this.current].answerList[i].point;
if(this.type === "indicator"){
this.indicator[this.question[this.current].answerList[i].indicator]
? this.indicator[this.question[this.current].answerList[i].indicator] += 1
: this.indicator[this.question[this.current].answerList[i].indicator] = 1;
}
this.next()
});
document.querySelector('.button_wrap').appendChild(button);
}
}
getResult() {
if(this.type === "point"){
...
}
if(this.type === "indicator" && this.current === this.testLength - 1){
this.userResult = "";
this.indicatorType.forEach(type => {
const [type1, type2] = type.split("");
this.indicator[type1] === undefined ? this.indicator[type1] = 0 : this.indicator[type1];
this.indicator[type2] === undefined ? this.indicator[type2] = 0 : this.indicator[type2];
if(this.indicator[type1] >= this.indicator[type2]){
this.userResult += type1;
}else if(this.indicator[type1] < this.indicator[type2]){
this.userResult += type2;
}
});
this.userResult = this.result.filter(({indicator}) => {
return indicator === this.userResult;
})[0];
}
...
}
restart() {
this.current = 0;
this.point = 0;
this.indicator = {};
this.init();
}
}
간단히 추가된 부분만을 설명해 보면,
우선 constructor 부분에서 type이 "indocator"이라면, this.indicator를 {}로 초기화시켜주고,
this.indicatorType에 this.question의 type들을 중복 없이 넣어주었다.
renderQuestion에서는 this.type이 indicator일 경우 기존 point처럼 point를 넣어주는 게 아니라,
this.indicator 객체에 선택된 답변의 indicator 값이 없을 경우엔 1로,
있을 경우엔 +1을 해주는 식으로 최종적으로
{A: 2. B: 1, C: 1, D: 1}의 형태로 각각 몇 개가 선택되었는지를 확인할 수 있는 객체로 만들어 주었다.
getResult에서는 this.type이 indicator의 경우에 userResult값에 indicatorType에 있는 문자열을 잘라
더 높은 쪽의 문자만 userResult에 넣어준 뒤, this.result에서 최종 문자열과 맞는 원소를 리턴해주게 하였다.
마지막으로 restart()에서는 this.indicator를 {}로 다시 초기화해주었다.
여러 가지로 테스트를 안 해봤기 때문에 아직 어떤 문제가 생길진 모르지만
예상한 대로 코드가 동작하는 것을 확인할 수 있다.