Skip to content

Instantly share code, notes, and snippets.

@MichielDeMey
Last active March 5, 2021 11:01
Show Gist options
  • Save MichielDeMey/57edf2cf39e7aab404e4c21e4bca2a4d to your computer and use it in GitHub Desktop.
Save MichielDeMey/57edf2cf39e7aab404e4c21e4bca2a4d to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
const dialTimeout = 7000;
const answerTimeout = 7000;
const externalActions = {
notify: () => {
window.alert('Notified care circle');
}
}
const dialActor = (timeout = 5000) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, timeout)
})
}
const guards = {
shouldContactCaree: (ctx, event) => {
return ctx.shouldContactCaree
},
maxAttemptsReached: (ctx, event, { cond }) => {
return ctx[cond.actor].attempts >= cond.numAttempts && !ctx[cond.actor].success
},
maxAttempsCurrentCarerReached: (ctx, event, { cond }) => {
return ctx.carers[ctx.currentCarerIndex].attempts >= cond.numAttempts && !ctx.carers[ctx.currentCarerIndex].success
},
couldNotContactCarers: (ctx, event, { cond }) => {
return ctx.carers.every((carer, i) => !carer.success && carer.attempts === ctx.numCarerAttempts);
}
}
const emergencyMachine = Machine({
id: 'emergency',
context: {
shouldContactCaree: true,
currentCarerIndex: 0,
numCarerAttempts: 1,
caree: {
attempts: 0,
success: false,
firstName: 'John',
lastName: 'Doe',
phone: '+32411111111'
},
carers: [{
attempts: 0,
success: false,
firstName: 'Michiel',
lastName: 'De Mey',
phone: '+32411118b61111'
}, {
attempts: 0,
success: false,
firstName: 'Niels',
lastName: 'Peetermans',
phone: '+32411111111'
}, {
attempts: 0,
success: false,
firstName: 'Jane',
lastName: 'Doe',
phone: '+32411111111'
}]
},
initial: 'idle',
states: {
idle: {
on: {
INCOMING_EMERGENCY: [{
target: 'contactingCaree',
cond: {
type: 'shouldContactCaree'
}
}, {
target: 'contactingCarers',
}]
}
},
contactingCaree: {
initial: 'check',
states: {
check: {
on: {
'': [{
target: '#emergency.contactingCarers',
cond: {
type: 'maxAttemptsReached',
actor: 'caree',
numAttempts: 1
}
}, { target: 'queue' }]
}
},
queue: {
exit: ['increaseCareeAttempt'],
invoke: {
id: 'dialCaree',
src: () => dialActor(),
onDone: {
target: 'dialing',
},
onError: {
target: '#emergency.contactingCaree'
}
}
},
dialing: {
on: {
ANSWER: {
target: 'answer'
},
NO_ANSWER: [{
target: '#emergency.contactingCaree',
}]
},
after: {
[dialTimeout]: '#emergency.contactingCaree'
}
},
answer: {
on: {
REAL_EMERGENCY: {
target: '#emergency.contactingCarers',
actions: ['successfulCareeAttempt']
},
FALSE_ALARM: {
target: '#emergency.end',
actions: ['successfulCareeAttempt']
},
HANGUP: '#emergency.contactingCaree'
},
after: {
[dialTimeout]: '#emergency.contactingCaree'
}
}
},
},
contactingCarers: {
initial: 'check',
states: {
check: {
entry: ['attemptCarer'],
on: {
'': [{
target: '#emergency.notify',
cond: 'couldNotContactCarers'
}, { target: 'queue' }]
}
},
queue: {
exit: ['increaseCarersAttempt'],
invoke: {
id: 'dialCarer',
src: () => dialActor(),
onDone: {
target: 'dialing',
},
onError: {
target: '#emergency.contactingCarers',
}
}
},
dialing: {
on: {
ANSWER: {
target: 'answer'
},
NO_ANSWER: [{
target: '#emergency.contactingCarers'
}]
},
after: {
[dialTimeout]: '#emergency.contactingCarers'
}
},
answer: {
on: {
CONFIRM: {
target: '#emergency.end',
actions: ['successfulCarerAttempt']
},
HANGUP: '#emergency.contactingCarers'
},
after: {
[answerTimeout]: '#emergency.contactingCarers'
}
}
}
},
notify: {
entry: ['notify'],
on: {
'': 'end'
}
},
end: {
type: 'final'
}
}
}, {
actions: {
...externalActions,
increaseCareeAttempt: assign({
caree: (ctx, event) => {
return {
...ctx.caree,
attempts: ctx.caree.attempts + 1
}
}
}),
successfulCareeAttempt: assign({
caree: (ctx, event) => {
return {
...ctx.caree,
success: true
}
}
}),
increaseCarersAttempt: assign({
carers: (ctx, event) => {
const carerArr = [ ...ctx.carers ]
const currentAttempts = carerArr[ctx.currentCarerIndex].attempts;
carerArr[ctx.currentCarerIndex] = {
...ctx.carers[ctx.currentCarerIndex],
attempts: currentAttempts + 1
}
return carerArr
}
}),
attemptCarer: assign({
currentCarerIndex: (ctx, event) => {
if (ctx.carers[ctx.currentCarerIndex].attempts < ctx.numCarerAttempts) return ctx.currentCarerIndex;
return ctx.currentCarerIndex + 1
}
}),
successfulCarerAttempt: assign({
carers: (ctx, event) => {
const carerArr = [ ...ctx.carers ]
carerArr[ctx.currentCarerIndex] = {
...carerArr[ctx.currentCarerIndex],
success: true
}
return carerArr
}
})
},
guards
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment