Last active
January 21, 2022 19:56
-
-
Save Krutie/a25bcf359a239bffbf403ec10679d906 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Validate answer | |
* @param ctx | |
* @param evt | |
*/ | |
const validateAnswer = (ctx, evt) => | |
new Promise((resolve, reject) => { | |
if (evt.type === "ANSWER" && evt.answer?.selectedOption !== undefined) { | |
resolve(evt.answer); | |
} else { | |
reject(new Error("Please select answer.")); | |
} | |
}); | |
/* NEXT_QUESTION transition object */ | |
const NEXT_Q = [ | |
{ | |
target: "answering", | |
cond: "canGoToNextQuestion", | |
actions: "goToNextQuestion", | |
}, | |
{ target: "finish" }, | |
]; | |
/* CHECK_ANSWER transition object */ | |
const CHECK_ANSWER = { | |
exit: ["clearErrorMessage"], | |
on: { | |
ANSWER: { | |
target: "submitting", | |
}, | |
}, | |
}; | |
const QuizMachine = Machine( | |
{ | |
id: "quiz", | |
initial: "initial", | |
context: { | |
currentQuestion: 0, | |
correct: 0, | |
incorrect: 0, | |
errorMessage: "", | |
answer: undefined, | |
totalQuestions: 0, | |
}, | |
states: { | |
initial: { | |
on: { | |
START: { | |
cond: "newTotalQuestionsIsValidValue", | |
actions: "assignTotalQuestionsToContext", | |
target: "answering", | |
}, | |
}, | |
}, | |
answering: { | |
initial: "idle", | |
id: "answering-id", | |
onDone: { | |
target: "checking", | |
}, | |
states: { | |
idle: CHECK_ANSWER, | |
submitting: { | |
invoke: { | |
src: validateAnswer, | |
id: "validateAnswer", | |
onDone: { | |
target: "complete", | |
actions: assign({ | |
answer: (context, event) => event.data, | |
}), | |
}, | |
onError: { | |
target: "invalid", | |
actions: assign( | |
(context, event) => { | |
return { | |
errorMessage: event.data.message, | |
}; | |
} | |
), | |
}, | |
}, | |
}, | |
invalid: CHECK_ANSWER, | |
complete: { | |
type: "final", | |
}, | |
}, | |
}, | |
checking: { | |
always: [ | |
{ | |
target: "correct", | |
cond: "isCorrect", | |
actions: assign((context) => { | |
return { | |
correct: context.correct + 1, | |
}; | |
}), | |
}, | |
{ | |
target: "incorrect", | |
cond: "isIncorrect", | |
actions: assign((context) => { | |
return { | |
incorrect: context.incorrect + 1, | |
}; | |
}), | |
}, | |
], | |
}, | |
correct: { | |
on: { | |
NEXT_QUESTION: NEXT_Q, | |
}, | |
}, | |
incorrect: { | |
on: { | |
NEXT_QUESTION: NEXT_Q, | |
}, | |
}, | |
finish: { | |
type: "final", | |
}, | |
}, | |
}, | |
{ | |
guards: { | |
newTotalQuestionsIsValidValue: ( | |
context, | |
event | |
) => { | |
if (event.type !== "START") return false; | |
// return context.totalQuestions > 0; | |
return true | |
}, | |
canGoToNextQuestion: (context) => { | |
return context.currentQuestion < context.totalQuestions; | |
}, | |
isCorrect: (ctx) => { | |
return ctx.answer?.selectedOption === ctx.answer?.value; | |
}, | |
isIncorrect: (ctx) => { | |
return ctx.answer?.selectedOption !== ctx.answer?.value; | |
}, | |
}, | |
actions: { | |
clearErrorMessage: assign((context) => { | |
return { errorMessage: undefined }; | |
}), | |
goToNextQuestion: assign((context) => { | |
return { currentQuestion: context.currentQuestion + 1 }; | |
}), | |
assignTotalQuestionsToContext: assign( | |
(context, event) => { | |
// questions array starts from index 0 | |
// reduce one from the total length of questions array | |
if (event.type !== "START") return {}; | |
return { | |
totalQuestions: 10, | |
}; | |
} | |
), | |
}, | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment