Created
January 19, 2021 19:06
-
-
Save amogower/a86ecebaef1e53440d4daa13f2f8fdee 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: 'fetching', | |
| states: { | |
| fetching: { | |
| invoke: { | |
| src: 'buildBetslip', | |
| onError: 'failure', | |
| onDone: { | |
| target: 'success', | |
| actions: sendParent('BETSLIP_BUILT'), | |
| }, | |
| }, | |
| 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: null, | |
| username: null, | |
| }, | |
| errors: { | |
| global: [], | |
| multiple: [], | |
| single: [], | |
| total: 0, | |
| }, | |
| freeBets: [], | |
| multiples: [], | |
| market: {}, | |
| receiptNo: null, | |
| selectedBets: {}, | |
| singles: [], | |
| totalStake: 10, | |
| totalReturns: 0, | |
| userSelectedBookie: false, | |
| }, | |
| states: { | |
| hidden: { | |
| id: 'hidden', | |
| on: { | |
| ADD_BET: { | |
| actions: 'addBet', | |
| target: 'visible', | |
| }, | |
| SHOW_BETSLIP: { | |
| target: 'visible', | |
| }, | |
| }, | |
| }, | |
| visible: { | |
| id: 'visible', | |
| initial: 'betslip', | |
| on: { | |
| HIDE_BETSLIP: { | |
| actions: 'hideBetslip', | |
| target: 'hidden', | |
| }, | |
| }, | |
| states: { | |
| bookieList: { | |
| on: { | |
| CLOSE_BOOKIE_LIST: { | |
| actions: 'selectBookie', | |
| target: '#betslip.initialized', | |
| }, | |
| SELECT_BOOKIE: { | |
| actions: 'selectBookie', | |
| target: '#betslip.initialized', | |
| }, | |
| }, | |
| }, | |
| betslip: { | |
| id: 'betslip', | |
| initial: 'initializing', | |
| 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', | |
| }, | |
| } | |
| }, | |
| fetchingBetData: { | |
| invoke: { | |
| src: 'fetchSingleBetData', | |
| onDone: { | |
| actions: 'addBets', | |
| target: 'initialized', | |
| }, | |
| onError: { | |
| target: '#error', | |
| }, | |
| }, | |
| }, | |
| initialized: { | |
| on: { | |
| '': [ | |
| { | |
| cond: 'noBookieSelected', | |
| target: '#visible.bookieList', | |
| }, | |
| { | |
| target: 'betting', | |
| }, | |
| ], | |
| }, | |
| }, | |
| betting: { | |
| initial: 'loggedOut', | |
| states: { | |
| loggedOut: { | |
| id: 'loggedOut', | |
| on: { | |
| '': [ | |
| { | |
| cond: 'bookieLoggedIn', | |
| target: 'loggedIn' | |
| }, | |
| ], | |
| LOG_IN: { | |
| target: '#login', | |
| }, | |
| PLACE_BETSLIP: { | |
| target: '#betslip.placeBetslip', | |
| }, | |
| }, | |
| }, | |
| loggedIn: { | |
| id: 'loggedIn', | |
| invoke: { | |
| id: 'polling', | |
| src: pollingMachine, | |
| }, | |
| on: { | |
| '': [ | |
| { | |
| cond: 'bookieLoggedOut', | |
| target: 'loggedOut' | |
| }, | |
| ], | |
| BETSLIP_BUILT: { | |
| actions: 'betslipBuilt', | |
| }, | |
| LOG_OUT: { | |
| actions: 'bookmakerLogout', | |
| target: 'loggedOut', | |
| }, | |
| PLACE_BETSLIP: [ | |
| { | |
| cond: 'hasInsufficientFunds', | |
| target: '#visible.error', | |
| }, | |
| { | |
| target: '#betslip.placeBetslip', | |
| }, | |
| ], | |
| }, | |
| }, | |
| }, | |
| on: { | |
| ADD_BET: { | |
| actions: 'addBet', | |
| target: '#betslip.fetchingBetData', | |
| }, | |
| OPEN_BOOKIE_LIST: { | |
| target: '#visible.bookieList', | |
| }, | |
| REMOVE_BET: { | |
| actions: 'removeBet', | |
| target: '#betslip.initializing', | |
| }, | |
| }, | |
| }, | |
| placeBetslip: { | |
| on: { | |
| '': [ | |
| { | |
| cond: 'bookieLoggedOut', | |
| target: '#login', | |
| }, | |
| { | |
| cond: 'hasInsufficientFunds', | |
| target: '#visible.error', | |
| }, | |
| { | |
| target: 'placingBetslip', | |
| }, | |
| ], | |
| }, | |
| }, | |
| placingBetslip: { | |
| invoke: { | |
| src: 'placeBetslip', | |
| onDone: { | |
| actions: 'cacheReceiptNo', | |
| target: 'receipt', | |
| }, | |
| onError: [ | |
| { | |
| target: '#error', | |
| }, | |
| ], | |
| }, | |
| }, | |
| receipt: { | |
| on: { | |
| DONE: { | |
| target: 'done', | |
| }, | |
| REUSE_SELECTIONS: { | |
| target: '#betslip.betting.loggedIn', | |
| }, | |
| }, | |
| }, | |
| done: { | |
| type: 'final', | |
| }, | |
| error: { | |
| initial: 'single', | |
| states: { | |
| single: {}, | |
| multiple: {}, | |
| }, | |
| }, | |
| hist: { | |
| type: 'history', | |
| }, | |
| }, | |
| }, | |
| 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: { | |
| actions: 'bookmakerLoginSuccess', | |
| target: '#betslip.hist', | |
| }, | |
| LOGIN_FAILURE: { | |
| target: '#error', | |
| }, | |
| }, | |
| }, | |
| loggingIn: { | |
| invoke: { | |
| src: 'bookmakerLogin', | |
| onDone: { | |
| actions: 'bookmakerLoginSuccess', | |
| target: '#betslip.hist', | |
| }, | |
| onError: { | |
| target: '#error', | |
| }, | |
| }, | |
| }, | |
| error: { | |
| states: { | |
| password: { | |
| on: { | |
| CHANGE_PASSWORD: { | |
| actions: 'changePassword', | |
| target: '#login.loginApi', | |
| }, | |
| }, | |
| }, | |
| username: { | |
| on: { | |
| CHANGE_USERNAME: { | |
| actions: 'changeUsername', | |
| target: '#login.loginApi', | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| }, | |
| error: { | |
| id: 'error', | |
| on: { | |
| CLOSE_MODAL: { | |
| actions: 'clearGlobalErrors', | |
| target: 'hist', | |
| }, | |
| }, | |
| }, | |
| hist: { | |
| type: 'history', | |
| history: 'deep', | |
| }, | |
| }, | |
| }, | |
| }, | |
| onDone: { | |
| actions: 'hideBetslip', | |
| }, | |
| }, { | |
| actions: { | |
| addBet: assign({ | |
| bookie: ({ bookie, bookieList }, event) => | |
| event.bookie ? bookieList.find(b => b.code === event.bookie) : bookie, | |
| selectedBets: ({ selectedBets }, { data }) => ({ | |
| ...selectedBets, | |
| ['1234']: { betId: '1234' }, | |
| }), | |
| userSelectedBookie: ({ userSelectedBookie }, event) => | |
| event.bookie ? true : userSelectedBookie, | |
| }), | |
| addBets: assign({ | |
| multiples: ({ multiples }, { data }) => data ? data.multiples : multiples, | |
| singles: ({ singles }, { data }) => data ? data.singles : singles, | |
| }), | |
| betslipBuilt: assign({ | |
| freeBets: ({ freeBets }, { data }) => data ? data.ocBetslip.freeBets : freeBets, | |
| multiples: ({ multiples }, { data }) => data ? data.ocBetslip.multiples : multiples, | |
| singles: ({ singles }, { data }) => data ? data.ocBetslip.singles : singles, | |
| }), | |
| bookmakerLoginSuccess: assign({ | |
| bookie: ({ bookie }) => ({ | |
| ...bookie, | |
| balance: 250, | |
| loggedIn: true, | |
| }), | |
| }), | |
| bookmakerLogout: assign({ | |
| bookie: () => null, | |
| }), | |
| cacheReceiptNo: assign({ | |
| receiptNo: (_, { receiptNo }) => receiptNo ? receiptNo : null, | |
| }), | |
| changePassword: assign({ | |
| credentials: ({ credentials }, { target }) => ({ | |
| ...credentials, | |
| password: target.value, | |
| }), | |
| }), | |
| changeUsername: assign({ | |
| credentials: ({ credentials }, { target }) => ({ | |
| ...credentials, | |
| username: target.value, | |
| }), | |
| }), | |
| clearGlobalError: assign({ | |
| errors: ({ errors }) => ({ | |
| ...errors, | |
| global: errors.global.slice(1, errors.global.length), | |
| }), | |
| }), | |
| clearMultipleError: assign({ | |
| errors: ({ errors }, { currentTarget }) => ({ | |
| ...errors, | |
| multiple: errors.single.filter(error => error.id === currentTarget.dataset.betType), | |
| }), | |
| }), | |
| clearSingleErrors: assign({ | |
| errors: ({ errors }, { currentTarget }) => ({ | |
| ...errors, | |
| single: errors.single.filter(error => error.id === currentTarget.dataset.betId), | |
| }), | |
| }), | |
| hideBetslip: assign({ | |
| betslipVisible: false, | |
| }), | |
| removeBet: assign({ | |
| selectedBets: ({ selectedBets }, { betId }) => ({ ...selectedBets, [betId]: undefined }), | |
| singles: ({ singles }, { betId }) => singles.filter((single) => single.betId !== betId), | |
| }), | |
| selectBookie: assign({ | |
| bookie: (ctx, { bookie }) => { | |
| // return bookie ? bookie : ctx.bookie; | |
| return { | |
| bookieCode: 'B3', | |
| loggedIn: false, | |
| }; | |
| }, | |
| userSelectedBookie: (_, { bookie }) => !!bookie, | |
| }), | |
| setStake: assign({ | |
| singles: ({ singles }, { betId, value }) => singles.map(single => { | |
| if (single.betId !== betId) return single; | |
| return Object.assign({}, single, { | |
| stake: 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: ({ bookie }) => bookie && bookie.loggedIn, | |
| bookieLoggedOut: ({ bookie }) => !bookie || (bookie && !bookie.loggedIn), | |
| bookieNotOauth: ({ bookie }) => bookie && bookie.loginType !== 'oauth', | |
| hasFetchedBookies: ({ bookieList }) => bookieList.length > 0, | |
| hasInsufficientFunds: ({ bookie, singles, totalStake }) => { | |
| if (!bookie) return false; | |
| const hasFunds = | |
| Number(bookie.balance) >= Number(totalStake) || | |
| singles[0].freeBet; | |
| return !hasFunds; | |
| }, | |
| hasMultipleError: ({ errors }) => errors.multiple.length > 0, | |
| hasNoBets: ({ selectedBets }) => Object.keys(selectedBets).length === 0, | |
| hasSingleError: ({ errors }) => errors.single.length > 0, | |
| noBookieSelected: ({ bookie, userSelectedBookie }) => !bookie && !userSelectedBookie, | |
| noPassword: ({ credentials }) => !credentials.password, | |
| noUsername: ({ credentials }) => !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