Skip to content

Instantly share code, notes, and snippets.

@bfunc
Last active April 14, 2021 22:00
Show Gist options
  • Save bfunc/db49b12e967c5aa753819104b64a3460 to your computer and use it in GitHub Desktop.
Save bfunc/db49b12e967c5aa753819104b64a3460 to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const wait = ms => new Promise(r => setTimeout(() => r(), ms))
const fetchResource = async ({ url, fakeDelayMs = 0 }) => {
await wait(fakeDelayMs)
return fetch(url).then(res => res.json())
}
const constants = {
MAX_QUESTION_SCORE: 3,
MAX_RETRIES: 15,
FAILURE_DELAY: 2000,
SUCCESS_DELAY: 2500,
FAKE_WAIT_DELAY: 0,
GAME_URL_TEST: 'https://jsonplaceholder.typicode.com/posts/',
GAME_URL: 'https://service.edu-com.co.il/api/games/607761b9ab4cca737ed05017/',
}
const fetchQuestion = async ({ q: num }) =>
await fetchResource({
url: constants.GAME_URL + num,
fakeDelayMs: constants.FAKE_WAIT_DELAY,
})
const getScoresDelta = retries => {
const delta = constants.MAX_QUESTION_SCORE - retries
return delta > 0 ? delta : 0
}
const fetchNextQuestion = async function (context) {
const startMs = Date.now()
const result = fetchQuestion(context)
const elapsedMs = Date.now() - startMs
const stillNeedToWaitMs = constants.SUCCESS_DELAY - elapsedMs
// success message screen should be on screen at least specified amount of time
if (stillNeedToWaitMs > 0) {
await wait(stillNeedToWaitMs)
}
return result
}
Machine({
id: 'QuestionsGame',
initial: 'initialLoad',
context: {
retries: 0,
scores: 0,
q: 0,
question: null,
},
states: {
initialLoad: {
invoke: {
src: fetchQuestion,
onDone: {
target: 'game',
actions: assign({
question: (ctx, event) => event.data,
}),
},
},
},
game: {
on: {
ANSWER_RIGHT: {
target: 'success',
actions: assign({
q: ctx => ctx.q + 1,
retries: 0,
scores: ctx => ctx.scores + getScoresDelta(ctx.retries),
}),
},
ANSWER_WRONG: [
{
target: 'failure',
cond: ctx => ctx.retries < constants.MAX_RETRIES,
},
{
target: 'skip',
cond: ctx => ctx.retries >= constants.MAX_RETRIES,
},
],
},
},
loadNext: {
invoke: {
id: 'fetchQuestionOnSuccess',
src: fetchNextQuestion,
onDone: {
target: 'game',
actions: assign({
question: (ctx, event) => event.data,
}),
},
},
},
success: {
invoke: {
id: 'fetchQuestionOnSuccess',
src: fetchNextQuestion,
onDone: {
target: 'game',
actions: assign({
question: (ctx, event) => event.data,
}),
},
},
/* after: { [constants.SUCCESS_DELAY]: { target: 'loadNext', }, }, */
},
skip: {
entry: assign({
q: ctx => ctx.q + 1,
retries: 0,
}),
after: {
[constants.FAILURE_DELAY]: {
target: 'loadNext',
},
},
},
failure: {
entry: [
assign({
retries: ctx => ctx.retries + 1,
}),
],
after: {
[constants.FAILURE_DELAY]: {
target: 'game',
},
},
},
},
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment