Last active
February 13, 2020 09:40
-
-
Save amogower/063bbf3c30dc84358e8ce8df6e90e3ef 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
| const singleBetMachine = Machine({ | |
| id: 'singleBet', | |
| initial: 'default', | |
| context: { | |
| isEachWay: false, | |
| stake: '', | |
| }, | |
| states: { | |
| default: { | |
| on: { | |
| CHANGE_STAKE: { | |
| actions: 'setStake', | |
| }, | |
| TOGGLE_EACH_WAY: { | |
| actions: 'toggleEachWay', | |
| }, | |
| }, | |
| }, | |
| error: { | |
| on: { | |
| CHANGE_STAKE: { | |
| actions: 'setStake', | |
| target: 'default', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }); | |
| const multipleBetMachine = Machine({ | |
| id: 'multipleBet', | |
| initial: 'default', | |
| context: { | |
| isEachWay: false, | |
| stake: '', | |
| }, | |
| states: { | |
| default: { | |
| on: { | |
| CHANGE_STAKE: { | |
| actions: 'setStake', | |
| }, | |
| TOGGLE_EACH_WAY: { | |
| actions: 'toggleEachWay', | |
| }, | |
| }, | |
| }, | |
| error: { | |
| on: { | |
| CHANGE_STAKE: { | |
| actions: 'setStake', | |
| target: 'default', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }); | |
| const pollingMachine = Machine({ | |
| initial: 'polling', | |
| states: { | |
| polling: { | |
| invoke: { | |
| src: 'buildBetslip', | |
| onError: 'failure', | |
| onDone: 'success', | |
| }, | |
| after: { TIMEOUT: 'fetching' }, | |
| }, | |
| failure: { | |
| after: { | |
| INTERVAL: 'fetching', | |
| }, | |
| }, | |
| success: {}, | |
| }, | |
| }, { | |
| delays: { INTERVAL: 5000, TIMEOUT: 10000 } | |
| }); | |
| const betslipMachine = Machine({ | |
| id: 'ocBetslip', | |
| initial: 'hidden', | |
| context: { | |
| bookie: null, | |
| bookieList: [], | |
| credentials: { | |
| password: '', | |
| username: '', | |
| }, | |
| errors: { | |
| global: [], | |
| multiple: [], | |
| single: [], | |
| total: 0, | |
| }, | |
| freeBets: [], | |
| multiples: [], | |
| market: {}, | |
| receiptNo: '', | |
| selectedBets: {}, | |
| singles: [], | |
| totalStake: 0, | |
| totalReturns: 0, | |
| userSelectedBookie: false, | |
| }, | |
| states: { | |
| hidden: { | |
| id: 'hidden', | |
| on: { | |
| ADD_BET: { | |
| actions: 'addBet', | |
| target: 'visible', | |
| }, | |
| SHOW_BETSLIP: { | |
| target: 'visible', | |
| }, | |
| }, | |
| }, | |
| visible: { | |
| id: 'visible', | |
| initial: 'initializing', | |
| on: { | |
| HIDE_BETSLIP: { | |
| actions: 'hideBetslip', | |
| target: 'hidden', | |
| }, | |
| }, | |
| states: { | |
| initializing: { | |
| on: { | |
| '': [ | |
| { | |
| cond: 'hasNoBets', | |
| target: 'empty', | |
| }, | |
| { | |
| target: 'fetchingBookmakerData', | |
| }, | |
| ] | |
| }, | |
| }, | |
| empty: { | |
| on: { | |
| ADD_BET: { | |
| actions: 'addBet', | |
| target: 'initializing', | |
| }, | |
| }, | |
| }, | |
| fetchingBookmakerData: { | |
| invoke: { | |
| src: 'fetchBookmakerData', | |
| onDone: { | |
| target: 'fetchingBetData', | |
| }, | |
| onError: { | |
| target: 'error.global', | |
| }, | |
| } | |
| }, | |
| fetchingBetData: { | |
| invoke: { | |
| src: 'fetchSingleBetData', | |
| onDone: { | |
| actions: 'addBets', | |
| target: 'initialized', | |
| }, | |
| onError: { | |
| target: 'error.global', | |
| }, | |
| }, | |
| }, | |
| initialized: { | |
| on: { | |
| '': [ | |
| { | |
| cond: 'noBookieSelected', | |
| target: 'bookieList', | |
| }, | |
| { | |
| target: 'betslip', | |
| }, | |
| ], | |
| }, | |
| }, | |
| bookieList: { | |
| on: { | |
| CLOSE_BOOKIE_LIST: { | |
| target: 'initialized', | |
| }, | |
| SELECT_BOOKIE: { | |
| actions: 'selectBookie', | |
| target: 'initialized', | |
| }, | |
| }, | |
| }, | |
| betslip: { | |
| id: 'betslip', | |
| initial: 'betting', | |
| states: { | |
| betting: { | |
| initial: 'loggedOut', | |
| states: { | |
| loggedOut: { | |
| on: { | |
| '': [ | |
| { | |
| cond: 'bookieLoggedIn', | |
| target: 'loggedIn' | |
| }, | |
| ], | |
| LOG_IN: { | |
| target: '#login', | |
| }, | |
| }, | |
| }, | |
| loggedIn: { | |
| on: { | |
| '': [ | |
| { | |
| cond: 'bookieLoggedOut', | |
| target: 'loggedOut' | |
| }, | |
| ], | |
| LOG_OUT: { | |
| actions: 'bookmakerLogout', | |
| target: 'loggedOut', | |
| }, | |
| }, | |
| }, | |
| }, | |
| on: { | |
| ADD_BET: { | |
| actions: 'addBet', | |
| target: '#visible.fetchingBetData', | |
| }, | |
| OPEN_BOOKIE_LIST: { | |
| target: '#visible.bookieList', | |
| }, | |
| PLACE_BETSLIP: [ | |
| { | |
| cond: 'bookieLoggedOut', | |
| target: '#login', | |
| }, | |
| { | |
| cond: 'hasInsufficientFunds', | |
| target: '#visible.error.global', | |
| }, | |
| { | |
| target: 'placingBetslip', | |
| }, | |
| ], | |
| REMOVE_BET: { | |
| actions: 'removeBet', | |
| }, | |
| }, | |
| }, | |
| placingBetslip: { | |
| invoke: { | |
| src: 'placeBetslip', | |
| onDone: { | |
| actions: 'cacheReceiptNo', | |
| target: 'receipt', | |
| }, | |
| onError: [ | |
| { | |
| target: 'error.global', | |
| }, | |
| ], | |
| }, | |
| }, | |
| receipt: { | |
| on: { | |
| DONE: { | |
| target: 'done', | |
| }, | |
| REUSE_SELECTIONS: { | |
| target: '#betslip.betting.loggedIn', | |
| }, | |
| }, | |
| }, | |
| done: { | |
| type: 'final', | |
| }, | |
| error: { | |
| initial: 'single', | |
| states: { | |
| global: { | |
| on: { | |
| CLOSE_MODAL: { | |
| actions: 'clearGlobalErrors', | |
| target: '#betslip.betting.loggedIn', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| login: { | |
| id: 'login', | |
| initial: 'loginOauth', | |
| states: { | |
| loginApi: { | |
| on: { | |
| '': { | |
| cond: 'bookieNotOauth', | |
| target: 'loginApi', | |
| }, | |
| CHANGE_USERNAME: { | |
| actions: 'changeUsername', | |
| }, | |
| CHANGE_PASSWORD: { | |
| actions: 'changePassword', | |
| }, | |
| LOGIN: [ | |
| { | |
| cond: 'noUsername', | |
| target: 'error.username', | |
| }, | |
| { | |
| cond: 'noPassword', | |
| target: 'error.password', | |
| }, | |
| { | |
| target: 'loggingIn', | |
| }, | |
| ], | |
| }, | |
| }, | |
| loginOauth: { | |
| on: { | |
| LOGIN_SUCCESS: { | |
| target: '#betslip.polling', | |
| }, | |
| }, | |
| }, | |
| loggingIn: { | |
| invoke: { | |
| src: 'bookmakerLogin', | |
| onDone: { | |
| actions: 'bookmakerLoginSuccess', | |
| target: '#betslip.polling', | |
| }, | |
| onError: { | |
| target: 'error.global', | |
| }, | |
| }, | |
| }, | |
| error: { | |
| states: { | |
| global: { | |
| on: { | |
| CLOSE_MODAL: { | |
| actions: 'clearGlobalErrors', | |
| target: '#login', | |
| }, | |
| }, | |
| }, | |
| password: { | |
| on: { | |
| CHANGE_PASSWORD: { | |
| actions: 'changePassword', | |
| target: '#login.loginApi', | |
| }, | |
| }, | |
| }, | |
| username: { | |
| on: { | |
| CHANGE_USERNAME: { | |
| actions: 'changeUsername', | |
| target: '#login.loginApi', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| error: { | |
| initial: 'global', | |
| states: { | |
| global: { | |
| on: { | |
| CLOSE_MODAL: { | |
| actions: 'clearGlobalErrors', | |
| target: '#visible', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| onDone: { | |
| actions: 'hideBetslip', | |
| }, | |
| }, { | |
| actions: { | |
| addBet: assign({ | |
| selectedBets: (ctx, evt) => ({ | |
| ...ctx.selectedBets, | |
| ['1234']: { betId: '1234' }, | |
| }), | |
| }), | |
| addBets: assign({ | |
| multiples: (ctx, evt) => evt.data.multiples, | |
| singles: (ctx, evt) => evt.data.singles, | |
| }), | |
| bookmakerLoginSuccess: assign({ | |
| bookie: (ctx) => ({ | |
| ...ctx.bookie, | |
| loggedIn: true, | |
| }), | |
| }), | |
| cacheReceiptNo: assign({ | |
| receiptNo: (ctx, evt) => evt.receiptNo, | |
| }), | |
| changePassword: assign({ | |
| credentials: (ctx, evt) => ({ | |
| ...ctx.credentials, | |
| password: evt.target.value, | |
| }), | |
| }), | |
| changeUsername: assign({ | |
| credentials: (ctx, evt) => ({ | |
| ...ctx.credentials, | |
| username: evt.target.value, | |
| }), | |
| }), | |
| clearGlobalError: assign({ | |
| errors: (ctx) => ({ | |
| ...ctx.errors, | |
| global: ctx.errors.global.slice(1, ctx.errors.global.length), | |
| }), | |
| }), | |
| clearMultipleError: assign({ | |
| errors: (ctx, evt) => ({ | |
| ...ctx.errors, | |
| multiple: ctx.errors.single.filter(error => error.id === evt.currentTarget.dataset.betType), | |
| }), | |
| }), | |
| clearSingleErrors: assign({ | |
| errors: (ctx, evt) => ({ | |
| ...ctx.errors, | |
| single: ctx.errors.single.filter(error => error.id === evt.currentTarget.dataset.betId), | |
| }), | |
| }), | |
| hideBetslip: assign({ | |
| betslipVisible: false, | |
| }), | |
| removeBet: assign({ | |
| selectedBets: (ctx, evt) => ctx.selectedBets.filter((bet) => bet.betId !== evt.betId), | |
| singles: (ctx, evt) => ctx.singles.filter((single) => single.betId !== evt.betId), | |
| }), | |
| selectBookie: assign({ | |
| bookie: (ctx, evt) => { | |
| // return evt.bookie; | |
| return { | |
| bookieCode: 'B3', | |
| loggedIn: false, | |
| }; | |
| }, | |
| userSelectedBookie: (ctx, evt) => !!evt.bookie, | |
| }), | |
| setStake: assign({ | |
| singles: (ctx, evt) => ctx.singles.map((single) => { | |
| if (single.betId !== evt.betId) return single; | |
| return Object.assign({}, single, { | |
| stake: evt.value, | |
| }); | |
| }), | |
| }), | |
| showBetslip: assign({ | |
| betslipVisible: true, | |
| }), | |
| toggleEachWay: assign((ctx, evt) => { | |
| let key = 'singles'; | |
| let attrCheck = 'betId'; | |
| if (evt.betType !== 'Single') { | |
| key = 'multiples'; | |
| attrCheck = 'betType'; | |
| } | |
| return { | |
| [key]: ctx[key].map((bet) => { | |
| if (bet[attrCheck] !== evt[attrCheck]) return bet; | |
| return Object.assign({}, bet, { | |
| eachWay: !ctx.eachWay, | |
| }); | |
| }), | |
| }; | |
| }), | |
| }, | |
| guards: { | |
| bookieLoggedIn: (ctx) => ctx.bookie && ctx.bookie.loggedIn, | |
| bookieLoggedOut: (ctx) => !ctx.bookie || (ctx.bookie && !ctx.bookie.loggedIn), | |
| bookieNotOauth: (ctx) => ctx.bookie && ctx.bookie.loginType !== 'oauth', | |
| hasInsufficientFunds: (ctx) => { | |
| if (!ctx.bookie) return false; | |
| const hasFunds = | |
| Number(ctx.bookie.balance) >= Number(ctx.totalStake) || | |
| ctx.singles[0].freeBet; | |
| return !hasFunds; | |
| }, | |
| hasMultipleError: (ctx) => ctx.errors.multiple.length > 0, | |
| hasNoBets: (ctx) => Object.keys(ctx.selectedBets).length === 0, | |
| hasSingleError: (ctx) => ctx.errors.single.length > 0, | |
| noBookieSelected: (ctx) => !ctx.bookie && !ctx.userSelectedBookie, | |
| noPassword: (ctx) => !ctx.credentials.password, | |
| noUsername: (ctx) => !ctx.credentials.username, | |
| }, | |
| services: { | |
| buildBetslip: () => new Promise((resolve) => { | |
| setTimeout(() => { | |
| resolve(); | |
| }, 1500); | |
| }), | |
| fetchBookmakerData: () => new Promise((resolve) => { | |
| setTimeout(() => { | |
| resolve({ | |
| bookieList: [ | |
| { bookieCode: 'B3' } | |
| ], | |
| }); | |
| }, 1500); | |
| }), | |
| fetchSingleBetData: () => new Promise((resolve) => { | |
| setTimeout(() => { | |
| resolve({ | |
| multiples: [], | |
| singles: [ | |
| { betId: '2345', eachWay: false }, | |
| { betId: '3456', eachWay: true }, | |
| ], | |
| }); | |
| }, 1500); | |
| }), | |
| getCachedBets: () => new Promise((resolve) => { | |
| setTimeout(() => { | |
| resolve([1, 2]); | |
| }, 1500); | |
| }), | |
| }, | |
| }); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment