Skip to content

Instantly share code, notes, and snippets.

@stephenparish

stephenparish/machine.js

Last active Oct 17, 2019
Embed
What would you like to do?
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
function getClosest(isUp, floor) {
const outsideQueue = isUp ? ctx.upRequests : ctx.downRequests
const requests = { ...ctx.floorRequests, ...outsideQueue }
const closestFloor = Object.keys(requests)
.map(floor => parseInt(floor, 10))
.filter(v => requests[v])
.sort((a, b) => (isUp ? a - b : b - a))
.find(r => (isUp ? floor <= r : floor >= r))
return closestFloor
}
const elevatorMachine = Machine({
id: 'elevator',
initial: 'idle',
context: {
currentFloor: 0,
maxFloor: 10,
floorRequests: {},
upRequests: {},
downRequests: {}
},
on: {
FLOOR: {
actions: assign({ floorRequests: (ctx, ev) => ({ ...ctx.floorRequests, [ev.number]: true }) })
},
UP: {
actions: assign({ upRequests: (ctx, ev) => ({ ...ctx.upRequests, [ev.number]: true }) })
},
DOWN: {
actions: assign({ downRequests: (ctx, ev) => ({ ...ctx.downRequests, [ev.number]: true }) })
}
},
states: {
idle: {
on: {
'': [
{
target: 'moving_up',
cond: 'hasUpRequests'
},
{
target: 'moving_down',
cond: 'hasDownRequests'
}
]
}
},
moving_up: {
entry: [
assign({
currentFloor: 0
})
],
invoke: {
id: 'moving_up',
src: (context, event) => (callback, onEvent) => {
// This will send the 'MOVED_UP' event to the parent every second
const id = setInterval(() => callback('MOVED_UP'), 1000)
// Perform cleanup
return () => clearInterval(id)
}
},
on: {
MOVED_UP: {
actions: [
assign({ currentFloor: (ctx) => ctx.currentFloor + 1 }),
assign({
upRequests: (ctx) => {
const reqs = {
...ctx.upRequests
};
delete reqs[ctx.currentFloor];
return reqs;
}
}),
assign({
floorRequests: (ctx) => {
const reqs = {
...ctx.floorRequests
};
delete reqs[ctx.currentFloor];
return reqs;
}
})
]
},
'': [
{ target: 'moving_down', cond: (ctx) => ctx.currentFloor === ctx.maxFloor }
]
}
},
moving_down: {
entry: [
assign({
currentFloor: (ctx) => ctx.maxFloor
})
],
invoke: {
id: 'moving_down',
src: (context, event) => (callback, onEvent) => {
// This will send the 'MOVED_UP' event to the parent every second
const id = setInterval(() => callback('MOVED_DOWN'), 1000)
// Perform cleanup
return () => clearInterval(id)
}
},
on: {
MOVED_DOWN: {
actions: [
assign({ currentFloor: (ctx) => ctx.currentFloor - 1 }),
assign({
downRequests: (ctx) => {
const reqs = {
...ctx.downRequests
};
delete reqs[ctx.currentFloor];
return reqs;
}
}),
assign({
floorRequests: (ctx) => {
const reqs = {
...ctx.floorRequests
};
delete reqs[ctx.currentFloor];
return reqs;
}
})
]
},
'': [
{ target: 'idle', cond: (ctx) => ctx.currentFloor === 0 }
]
}
}
}
}, {
guards: {
hasDownRequests: (ctx) => !!Object.keys(ctx.downRequests).length,
hasUpRequests: (ctx) => !!Object.keys(ctx.upRequests).length,
noRequests: (ctx) => !Object.keys(ctx.downRequests)
}
});
// IUR - inside up request
// IDR - inside down request
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.