diff --git a/frontend/game/package.json b/frontend/game/package.json
index e3809a5..749de2c 100644
--- a/frontend/game/package.json
+++ b/frontend/game/package.json
@@ -12,6 +12,8 @@
"react-redux": "^7.2.3",
"react-scripts": "4.0.3",
"redux": "^4.0.5",
+ "socket.io": "^4.1.2",
+ "socket.io-client": "^4.1.2",
"source-map-explorer": "^2.5.2",
"superagent": "^6.1.0",
"web-vitals": "^1.1.1"
@@ -52,6 +54,6 @@
]
},
"devDependencies": {
- "@web-lite/api-types": "1.1.1"
+ "@web-lite/api-types": "^1.1.1"
}
}
diff --git a/frontend/game/public/weblite.manifest.json b/frontend/game/public/weblite.manifest.json
index 91fd0ec..9c17329 100644
--- a/frontend/game/public/weblite.manifest.json
+++ b/frontend/game/public/weblite.manifest.json
@@ -3,12 +3,10 @@
"id": "5f945d356cb1bf0d609c860a",
"instantiable": true,
"searchable": true,
- "fullscreen": true,
"inline": false,
"notifMessage": "نقطه به نقطه انتظار برای دیدن تو",
"servIndexes": {
- "main": "index",
- "fullscreen": "index"
+ "main": "index"
},
"version": "1.11.15"
}
\ No newline at end of file
diff --git a/frontend/game/src/components/header/header.js b/frontend/game/src/components/header/header.js
index 89e01d1..6a62208 100644
--- a/frontend/game/src/components/header/header.js
+++ b/frontend/game/src/components/header/header.js
@@ -3,9 +3,12 @@ import * as React from 'react'
import useStyle from './header.style'
// localiztion
import t from './header.local'
+import { useSelector } from 'react-redux'
+import { roomIsWaitingView, statusView } from '../../scenes/_slice/game.slice'
export default function Header(props) {
const classes = useStyle()
+ const status = useSelector(statusView)
- return
- {createElements().map(({ i, j }) => {
- if ((i * j) % 2 === 1) return
- else if (i % 2 === 1 && j % 2 !== 1) return
- else if (i % 2 !== 1 && j % 2 === 1) return
- else return
+ {createElements(rowNumber, columnNumber).map(({ i, j }) => {
+ if ((i * j) % 2 === 1) return
+ else if (i % 2 === 1 && j % 2 !== 1)
+ return
+ else if (i % 2 !== 1 && j % 2 === 1)
+ return
+ else
+ return (
+
+ )
})}
)
diff --git a/frontend/game/src/components/rectangle/rectangle.js b/frontend/game/src/components/rectangle/rectangle.js
index 9a53320..b8079a0 100644
--- a/frontend/game/src/components/rectangle/rectangle.js
+++ b/frontend/game/src/components/rectangle/rectangle.js
@@ -3,17 +3,65 @@ import * as React from 'react'
import useStyle from './rectangle.style'
// localiztion
import t from './rectangle.local'
+import {
+ elementColorView,
+ getPlayerHasPermission,
+ playerColorView,
+} from '../../scenes/_slice/game.slice'
+import { useSelector } from 'react-redux'
+import { requestGift, sendBouns } from '../../services/backend/backend.service'
-export default function Rectangle({ i, j }) {
+export default function Rectangle({ i, j, lastMove }) {
const classes = useStyle()
+ let lastLineColor
+ const { i: lastI, j: lastJ, color: lastColor } = lastMove
+ //TODO check wether rectangle is colored
+ const playerHasPermission = useSelector(getPlayerHasPermission)
+ const playerColor = useSelector(playerColorView)
+ const topLineColor = useSelector(elementColorView(i - 1, j))
+ const rightLineColor = useSelector(elementColorView(i, j + 1))
+ const leftLineColor = useSelector(elementColorView(i, j - 1))
+ const downLineColor = useSelector(elementColorView(i + 1, j))
+ const background = useSelector(elementColorView(i, j))
+
+ if (i - 1 === lastI && j === lastJ) lastLineColor = topLineColor || ''
+ if (i + 1 === lastI && j === lastJ) lastLineColor = downLineColor || ''
+ if (i === lastI && j - 1 === lastJ) lastLineColor = leftLineColor || ''
+ if (i === lastI && j + 1 === lastJ) lastLineColor = rightLineColor || ''
+ // if (i === 2 && j === 10) console.log(lastLineColor)
+
+ const backgroundColor = background
+ ? `dark${background}`
+ : !!topLineColor && !!rightLineColor && !!leftLineColor && !!downLineColor
+ ? `dark${lastLineColor}`
+ : ''
+
+ if (
+ ((i - 1 === lastI && j === lastJ) ||
+ (i + 1 === lastI && j === lastJ) ||
+ (i === lastI && j - 1 === lastJ) ||
+ (i === lastI && j + 1 === lastJ)) &&
+ !background &&
+ !!topLineColor &&
+ !!rightLineColor &&
+ !!leftLineColor &&
+ !!downLineColor &&
+ playerColor === lastColor
+ ) {
+ // console.log({ playerColor, lastColor, lastLineColor })
+ sendBouns(i, j, playerColor)
+ }
return (
-
+
diff --git a/frontend/game/src/components/xline/xline.js b/frontend/game/src/components/xline/xline.js
index b6c064c..badc6e6 100644
--- a/frontend/game/src/components/xline/xline.js
+++ b/frontend/game/src/components/xline/xline.js
@@ -1,13 +1,30 @@
import * as React from 'react'
// style
import useStyle from './xline.style'
-import { useSelector } from 'react-redux'
-import { playerColorView } from '../../scenes/_slice/game.slice'
+import { useDispatch, useSelector } from 'react-redux'
+import {
+ addNewLine,
+ elementColorView,
+ getPlayerId,
+ playerColorView,
+ playerIdView,
+ roomHasPermissionView,
+ roomIsWaitingView,
+ setPlayerLastMove,
+ setRoomLastMove,
+} from '../../scenes/_slice/game.slice'
+import { sendNewLine } from '../../services/backend/backend.service'
export default function Xline({ i, j }) {
+ const dispatch = useDispatch()
+
const classes = useStyle()
+
+ const playerId = useSelector(playerIdView)
const playerColor = useSelector(playerColorView)
- const [backgroundColor, setBackgroundColor] = React.useState('')
+ const lineColor = useSelector(elementColorView(i, j))
+ const isWaiting = useSelector(roomIsWaitingView)
+ const hasPermission = useSelector(roomHasPermissionView)
return (
{
- setBackgroundColor(playerColor)
+ if (!isWaiting && hasPermission && !lineColor) {
+ sendNewLine(i, j, playerColor)
+ dispatch(addNewLine({ i, j, color: playerColor }))
+ dispatch(setPlayerLastMove({ i, j, color: playerColor }))
+ dispatch(setRoomLastMove({ i, j, color: playerColor }))
+ }
}}
>
)
diff --git a/frontend/game/src/components/yline/yline.js b/frontend/game/src/components/yline/yline.js
index 421d3ef..dd9b1d4 100644
--- a/frontend/game/src/components/yline/yline.js
+++ b/frontend/game/src/components/yline/yline.js
@@ -2,14 +2,29 @@ import * as React from 'react'
// style
import useStyle from './yline.style'
-import { useSelector } from 'react-redux'
-import { playerColorView } from '../../scenes/_slice/game.slice'
+import { useDispatch, useSelector } from 'react-redux'
+import {
+ addNewLine,
+ elementColorView,
+ playerColorView,
+ playerIdView,
+ roomHasPermissionView,
+ roomIsWaitingView,
+ setPlayerLastMove,
+ setRoomLastMove,
+} from '../../scenes/_slice/game.slice'
+import { sendNewLine } from '../../services/backend/backend.service'
export default function Yline({ i, j }) {
+ const dispatch = useDispatch()
+
const classes = useStyle()
- const playerColor = useSelector(playerColorView)
- const [backgroundColor, setBackgroundColor] = React.useState('')
+ const playerId = useSelector(playerIdView)
+ const playerColor = useSelector(playerColorView)
+ const lineColor = useSelector(elementColorView(i, j))
+ const isWaiting = useSelector(roomIsWaitingView)
+ const hasPermission = useSelector(roomHasPermissionView)
return (
{
- setBackgroundColor(playerColor)
+ if (!isWaiting && hasPermission && !lineColor) {
+ sendNewLine(i, j, playerColor)
+ dispatch(addNewLine({ i, j, color: playerColor }))
+ dispatch(setPlayerLastMove({ i, j, color: playerColor }))
+ dispatch(setRoomLastMove({ i, j, color: playerColor }))
+ }
}}
>
)
diff --git a/frontend/game/src/index.js b/frontend/game/src/index.js
index 2e9bce2..8a4230d 100644
--- a/frontend/game/src/index.js
+++ b/frontend/game/src/index.js
@@ -6,7 +6,7 @@ import './setup/wapp/initialize'
import ReduxProvider from './setup/store'
import ThemeProvider from './setup/theme'
-import App from './scenes/game'
+import App from './scenes'
ReactDOM.render(
diff --git a/frontend/game/src/scenes/_hook/index.js b/frontend/game/src/scenes/_hook/index.js
index 61396e2..9d61c44 100644
--- a/frontend/game/src/scenes/_hook/index.js
+++ b/frontend/game/src/scenes/_hook/index.js
@@ -1 +1 @@
-export * from './useColor'
\ No newline at end of file
+export * from './useInitializeData'
diff --git a/frontend/game/src/scenes/_hook/readme-first.txt b/frontend/game/src/scenes/_hook/readme-first.txt
deleted file mode 100644
index fe3d062..0000000
--- a/frontend/game/src/scenes/_hook/readme-first.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-- custom hooks which are used across scenes
-
-- you can also use custom-hooks packages such as `react-use`
\ No newline at end of file
diff --git a/frontend/game/src/scenes/_hook/useColor.js b/frontend/game/src/scenes/_hook/useColor.js
deleted file mode 100644
index 25487cb..0000000
--- a/frontend/game/src/scenes/_hook/useColor.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { useCallback } from 'react'
-import { useSelector, useDispatch } from 'react-redux'
-import { colorIdView, setColorId } from '../_slice/home.slice'
-
-export const useColor = () => {
- const dispatch = useDispatch()
- const colorId = useSelector(colorIdView)
-
- const changeColor = useCallback(() => {
- dispatch(setColorId(colorId + 1))
- // eslint-disable-next-line react-hooks/exhaustive-deps
- },[colorId])
-
- return [colorId, changeColor]
-}
\ No newline at end of file
diff --git a/frontend/game/src/scenes/_hook/useInitializeData.js b/frontend/game/src/scenes/_hook/useInitializeData.js
new file mode 100644
index 0000000..5ea07cd
--- /dev/null
+++ b/frontend/game/src/scenes/_hook/useInitializeData.js
@@ -0,0 +1,15 @@
+import { useEffect } from 'react'
+import { getCurrentUserId, getWisId } from '../../services/weblite/weblite.api'
+import { dispatchPlayerId, dispatchRoomId } from '../_slice/game.slice'
+
+export const useInitializeData = () => {
+ const userId = getCurrentUserId()
+ const roomId = getWisId()
+
+ useEffect(() => {
+ dispatchPlayerId(userId)
+ dispatchRoomId(roomId)
+ }, [userId, roomId])
+
+ // return [colorId, changeColor]
+}
diff --git a/frontend/game/src/scenes/_slice/game.slice.js b/frontend/game/src/scenes/_slice/game.slice.js
index a8f6c91..ed13e57 100644
--- a/frontend/game/src/scenes/_slice/game.slice.js
+++ b/frontend/game/src/scenes/_slice/game.slice.js
@@ -1,48 +1,187 @@
import { createSlice } from '@reduxjs/toolkit'
+import store from '../../setup/store/store'
const gameSlice = createSlice({
name: 'game',
initialState: {
- roomId: undefined,
paper: {
row: 6,
column: 6,
},
player: {
- userId: undefined,
- name: 'نامشخص',
- color: 'red',
+ id: undefined,
+ name: 'هوشنگ',
+ color: '',
score: 0,
+ letter: 'ه',
+ lastMove: {},
},
opponent: {
- userId: undefined,
- name: 'نامشخص',
- color: 'blue',
+ id: undefined,
+ name: 'بیژن',
+ color: '',
score: 0,
+ letter: 'ب',
+ lastMove: {},
},
- letter: undefined,
- role: undefined,
- end: false,
- permission: false,
- waiting: false,
- gift: false,
- language: 'persian',
- table: {
- lines: [],
- squares: [],
+ room: {
+ id: undefined,
+ role: undefined,
+ isWaiting: false,
+ hasPermission: false,
+ end: false,
+ gift: false,
+ history: {},
+ lastMove: {},
},
+ language: 'persian',
+ status: 'connecting',
},
reducers: {
- setData: (state, action) => {
- state.data = action.payload
+ setPlayerColor: (state, action) => {
+ const { color } = action.payload
+ state.player.color = color
+ },
+ setOpponentName: (state, action) => {
+ const { name } = action.payload
+ state.opponent.name = name
+ },
+ setOpponentId: (state, action) => {
+ const { id } = action.payload
+ state.opponent.id = id
+ },
+ setPlayerId: (state, action) => {
+ const { id } = action.payload
+ state.player.id = id
+ },
+ setRoomId: (state, action) => {
+ const { id } = action.payload
+ state.room.id = id
+ },
+ setIsWaiting: (state, action) => {
+ const { isWaiting } = action.payload
+ state.room.isWaiting = isWaiting
+ },
+ setHasPermission: (state, action) => {
+ const { hasPermission } = action.payload
+ state.room.hasPermission = hasPermission
+ },
+ addNewLine: (state, action) => {
+ const { i, j, color } = action.payload
+ state.room.history[i] = { ...state.room.history[i] }
+ state.room.history[i][j] = color
+ },
+ setPlayerLastMove: (state, action) => {
+ const { i, j, color } = action.payload
+ state.player.lastMove = { i, j, color }
+ },
+ setOpponentLastMove: (state, action) => {
+ const { i, j, color } = action.payload
+ state.opponent.lastMove = { i, j, color }
+ },
+ setRoomLastMove: (state, action) => {
+ const { i, j, color } = action.payload
+ state.room.lastMove = { i, j, color }
+ },
+ setStatus: (state, action) => {
+ const { status } = action.payload
+ state.status = status
+ },
+ setHistory: (state, action) => {
+ const { history } = action.payload
+ state.room.history = history
},
},
})
const { actions, reducer } = gameSlice
-export const { setData } = actions
+export const {
+ setPlayerColor,
+ setPlayerId,
+ setOpponentName,
+ setOpponentId,
+ setRoomId,
+ setIsWaiting,
+ setHasPermission,
+ addNewLine,
+ setStatus,
+ setHistory,
+ setPlayerLastMove,
+ setOpponentLastMove,
+ setRoomLastMove,
+} = actions
export default reducer
/* Views */
+export const statusView = state => state.game.status
+export const playerIdView = state => state.game.player.id
export const playerColorView = state => state.game.player.color
+export const playerNameView = state => state.game.player.name
+export const playerScoreView = state => state.game.player.score
+
+export const opponentIdView = state => state.game.opponent.id
export const opponentColorView = state => state.game.opponent.color
+export const opponentNameView = state => state.game.opponent.name
+export const opponentScoreView = state => state.game.opponent.score
+
+export const roomIsWaitingView = state => state.game.room.isWaiting
+export const roomHasPermissionView = state => state.game.room.hasPermission
+export const roomLastMoveView = state => state.game.room.lastMove
+
+export const paperRowNumberView = state => state.game.paper.row
+export const paperColumnNumberView = state => state.game.paper.column
+
+export const elementColorView = (i, j) => state =>
+ state.game.room.history[i] ? state.game.room.history[i][j] : ''
+
+/* Getters */
+export const getRoomId = state => (state ?? store.getState()).game.room.id
+export const getRoomHasPermission = state =>
+ (state ?? store.getState()).game.room.hasPermission
+export const getPlayerId = state => (state ?? store.getState()).game.player.id
+export const getPlayerName = state =>
+ (state ?? store.getState()).game.player.name
+export const getPlayerColor = state =>
+ (state ?? store.getState()).game.player.color
+export const getOpponentName = state =>
+ (state ?? store.getState()).game.opponent.name
+export const getPlayerHasPermission = state =>
+ (state ?? store.getState()).game.room.hasPermission
+
+export const getLineView = (i, j) => state =>
+ (state ?? store.getState()).game.room.history[i][j] || {}
+
+/* Dispatches */
+export const dispatchPlayerColor = color =>
+ store.dispatch(setPlayerColor({ color }))
+export const dispatchPlayerId = id => store.dispatch(setPlayerId({ id }))
+
+export const dispatchOpponentName = name =>
+ store.dispatch(setOpponentName({ name }))
+
+export const dispatchOpponentId = id => store.dispatch(setOpponentId({ id }))
+
+export const dispatchRoomId = id => store.dispatch(setRoomId({ id }))
+
+export const dispatchIsWaiting = isWaiting =>
+ store.dispatch(setIsWaiting({ isWaiting }))
+
+export const dispatchHasPermission = hasPermission =>
+ store.dispatch(setHasPermission({ hasPermission }))
+
+export const dispatchAddNewLine = (i, j, color) =>
+ store.dispatch(addNewLine({ i, j, color }))
+
+export const dispatchSetPlayerLastMove = (i, j, color) =>
+ store.dispatch(setPlayerLastMove({ i, j, color }))
+
+export const dispatchSetOpponentLastMove = (i, j, color) =>
+ store.dispatch(setOpponentLastMove({ i, j, color }))
+
+export const dispatchSetRoomLastMove = (i, j, color) =>
+ store.dispatch(setRoomLastMove({ i, j, color }))
+
+export const dispatchSetStatus = status => store.dispatch(setStatus({ status }))
+
+export const dispatchSetHistory = history =>
+ store.dispatch(setHistory({ history }))
diff --git a/frontend/game/src/scenes/game/game.js b/frontend/game/src/scenes/game/game.js
index ef29f2a..3998fe4 100644
--- a/frontend/game/src/scenes/game/game.js
+++ b/frontend/game/src/scenes/game/game.js
@@ -10,6 +10,9 @@ import Paper from '../../components/paper/paper'
import SendField from '../../components/send-field'
import Information from '../../components/information'
+import '../../services/backend/backend.service'
+import ScoreBoard from '../../components/score-board/score-board'
+
export default function GamePresentational(props) {
const classes = useStyle()
@@ -19,6 +22,7 @@ export default function GamePresentational(props) {
+
diff --git a/frontend/game/src/scenes/game/index.js b/frontend/game/src/scenes/game/index.js
index 7791d19..630456e 100644
--- a/frontend/game/src/scenes/game/index.js
+++ b/frontend/game/src/scenes/game/index.js
@@ -1,12 +1,7 @@
import * as React from 'react'
// view
-import /* selectorView */ /* actionCreators */ '../_slice/game.slice'
import GamePresentational from './game'
-export default function Game(props) {
- // const state = useSelcetor(selectorView)
- // const dispatch = useDispatch()
- // const onClick = () => dispatch(actionCreators('payload'))
-
+export default function Game() {
return
}
diff --git a/frontend/game/src/scenes/index.js b/frontend/game/src/scenes/index.js
new file mode 100644
index 0000000..1467a8c
--- /dev/null
+++ b/frontend/game/src/scenes/index.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import Game from './game'
+import { useInitializeData } from './_hook/useInitializeData'
+
+export default function Root() {
+ useInitializeData()
+ return
+}
diff --git a/frontend/game/src/services/backend/backend.api.js b/frontend/game/src/services/backend/backend.api.js
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/game/src/services/backend/backend.service.js b/frontend/game/src/services/backend/backend.service.js
new file mode 100644
index 0000000..ac2cd83
--- /dev/null
+++ b/frontend/game/src/services/backend/backend.service.js
@@ -0,0 +1,172 @@
+// import { axios } from 'axios'
+import { io } from 'socket.io-client'
+import {
+ dispatchAddNewLine,
+ dispatchHasPermission,
+ dispatchIsWaiting,
+ dispatchOpponentId,
+ dispatchPlayerColor,
+ dispatchSetHistory,
+ dispatchSetOpponentLastMove,
+ dispatchSetRoomLastMove,
+ dispatchSetStatus,
+ getPlayerColor,
+ getPlayerHasPermission,
+ getPlayerId,
+ getPlayerName,
+ getRoomId,
+} from '../../scenes/_slice/game.slice'
+
+import { HTTP_BACKEND } from '../../setup/api'
+import { dispatch } from '../../setup/store/store'
+import { getCurrentUserId, getWisId } from '../weblite/weblite.api'
+// /**
+// * @param {Object} params - your passed data
+// * @return {Promise
}
+// */
+// export const getBackend = params =>
+// axios.get('api-path', { params }).then(res => res.data)
+const socket = io(HTTP_BACKEND)
+
+const roomId = getRoomId()
+const playerId = getPlayerId()
+const playerName = getPlayerName()
+const playerColor = getPlayerColor()
+
+socket.on('connect', () => {
+ console.log('connected')
+ dispatchSetStatus('connected')
+})
+
+socket.on('handshake', () => {
+ console.log('handshaking...')
+
+ socket.emit('handshake', { roomId: getWisId(), userId: getCurrentUserId() })
+})
+
+socket.on('color', color => {
+ console.log('getting color...', color)
+ dispatchPlayerColor(color)
+})
+
+socket.on('mustWait', type => {
+ console.log('waiting...')
+ console.log(type)
+ // W.messages.sendMessageToCurrentChat('text', 'نقطه بازی کنیم؟')
+ dispatchIsWaiting(type)
+ type ? dispatchSetStatus('waiting') : dispatchSetStatus('connected')
+})
+
+socket.on('watch', history => {
+ console.log('wathcing history...')
+ console.log(history)
+ dispatchSetHistory(history)
+ // if (history.length > 0) {
+ // for (let i = 0; i < history.length; i++) {
+ // recieve(history[i], history[i].color)
+ // }
+ // }
+})
+
+socket.on('introduce', () => {
+ console.log('introducing...')
+ socket.emit('introduce', playerId, roomId)
+})
+
+socket.on('name', opponentId => {
+ console.log('getting opponent name')
+ dispatchOpponentId(opponentId)
+})
+
+socket.on('role', (role, color) => {
+ console.log('getting role')
+ if (color === playerColor) dispatchHasPermission(true)
+ else dispatchHasPermission(false)
+ // set('role', role)
+ // showMessage('subscriber')
+ socket.emit('getname', roomId)
+})
+
+socket.on('getname', (redName, blueName) => {
+ console.log('getting name...')
+ // if (get('role') === 'subscriber') {
+ // set('name', redName)
+ // set('opponentName', blueName)
+ // }
+})
+
+let timeout
+
+socket.on('message', message => {
+ clearTimeout(timeout)
+ const opponentMessage = document.getElementsByClassName('opponent-message')[0]
+ console.log(opponentMessage)
+ opponentMessage.style.display = 'block'
+ opponentMessage.innerHTML = message
+ const sendAudio = new Audio('./assets/what-302.mp3')
+ sendAudio.play()
+ timeout = setTimeout(() => (opponentMessage.style.display = 'none'), 20000)
+})
+
+socket.on('change', (line, color) => {
+ // if (get('role') === 'subscriber') {
+ // set('opponentColor', turn)
+ // if (turn === 'red') set('color', 'blue')
+ // else set('color', 'red')
+ // }
+ console.log(color)
+ if (playerColor !== color) {
+ const { i, j } = line
+ dispatchSetRoomLastMove(i, j, color)
+ dispatchSetOpponentLastMove(i, j, color)
+ dispatchAddNewLine(i, j, color)
+ dispatchHasPermission(true)
+ } else {
+ console.log('else')
+ console.log(line, color)
+ }
+})
+
+socket.on('gift', userId => {
+ const playerId = getPlayerId()
+ console.log(`permission changed to ${playerId === userId}`)
+ dispatchHasPermission(playerId === userId)
+})
+
+socket.on('resign', () => {
+ // showEnd(get('color'))
+ // socket.emit('disconnect', get('userId'), get('roomId'))
+})
+socket.on('hasPermission', permission => {
+ dispatchHasPermission(permission)
+})
+
+socket.on('warning', warning => {
+ console.log(warning)
+})
+
+socket.on('disconnect', () => dispatchSetStatus('connecting'))
+
+export const sendNewLine = (i, j, color) => {
+ const roomId = getRoomId()
+ const playerId = getPlayerId()
+ const message = { i, j, color }
+ socket.emit('change', playerId, roomId, message)
+ dispatchHasPermission(false)
+}
+
+export const sendBouns = (i, j, color) => {
+ const roomId = getRoomId()
+ const userId = getPlayerId()
+ const bouns = { i, j, color }
+ socket.emit('bouns', roomId, userId, bouns)
+}
+
+export const sendMessage = message => {
+ // socket.emit('message', get('roomId'), message)
+}
+
+export const resign = () => {
+ // showEnd(get('opponentColor'))
+ // socket.emit('resign', get('userId'), get('roomId'))
+}
diff --git a/frontend/game/src/services/backend/index.js b/frontend/game/src/services/backend/index.js
new file mode 100644
index 0000000..9f1c2d2
--- /dev/null
+++ b/frontend/game/src/services/backend/index.js
@@ -0,0 +1 @@
+export * from './backend.service'
diff --git a/frontend/game/src/services/weblite/weblite.api.js b/frontend/game/src/services/weblite/weblite.api.js
index d27af78..04f7444 100644
--- a/frontend/game/src/services/weblite/weblite.api.js
+++ b/frontend/game/src/services/weblite/weblite.api.js
@@ -1,9 +1,35 @@
-///
+///
const { W } = window
-export const getCurrentUserId = W.user.getId
+export const getCurrentUserId = () => prompt('user id')
export const openImageInModal = src => W.images.openModal({ src })
export const getUsersEducationalProfile = () => W.user.getProfile('school')
+
+// export const fetchUserEducationalProfile = () => W.user.getProfile('school')
+
+// TODO: Add getUsersById for more performant version
+// export const fetchUserById = userId =>
+// W.users.getById([userId]).then(usersInfo => usersInfo[userId] || {})
+
+// export const openImageInModal = src => W.images.openModal({ src })
+
+// export const upload = (...args) => W.fileSystem.upload(...args)
+
+// export const sendToUsers = ({
+// title,
+// body,
+// type = ['push'],
+// data = {},
+// userIds = [],
+// }) => W.notifications.sendToUsers(title, body, type, data, userIds)
+
+// export const openProfile = userId => W.users.openProfile(userId)
+export const sendAnalytics = ({ type, ...args }) => W.analytics(type, args)
+
+export const doneDrawer = output => W.wapp.doneDrawer(output)
+
+export const getWisId = () =>
+ 'lswea13zenV34ed5m361sskh91s1d0n4LnK383kJHiHgF8Nlj23esosdm1f45AXQwl4dsw'
diff --git a/frontend/game/src/setup/api/constant.js b/frontend/game/src/setup/api/constant.js
new file mode 100644
index 0000000..abdfc73
--- /dev/null
+++ b/frontend/game/src/setup/api/constant.js
@@ -0,0 +1,5 @@
+export const HTTP_BACKEND =
+ process.env.NODE_ENV === 'development'
+ ? 'http://localhost:13797'
+ : // 'https://noghteh-bazi.wapp.weblite.me/'
+ 'https://noghteh-bazi.wapp.weblite.me/'
diff --git a/frontend/game/src/setup/api/index.js b/frontend/game/src/setup/api/index.js
new file mode 100644
index 0000000..63e4607
--- /dev/null
+++ b/frontend/game/src/setup/api/index.js
@@ -0,0 +1 @@
+export * from './constant'
diff --git a/frontend/game/src/setup/api/request.js b/frontend/game/src/setup/api/request.js
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/game/yarn.lock b/frontend/game/yarn.lock
index 9362e38..dd5184e 100644
--- a/frontend/game/yarn.lock
+++ b/frontend/game/yarn.lock
@@ -1714,6 +1714,21 @@
dependencies:
"@babel/types" "^7.3.0"
+"@types/component-emitter@^1.2.10":
+ version "1.2.10"
+ resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.10.tgz#ef5b1589b9f16544642e473db5ea5639107ef3ea"
+ integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==
+
+"@types/cookie@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108"
+ integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==
+
+"@types/cors@^2.8.8":
+ version "2.8.10"
+ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.10.tgz#61cc8469849e5bcdd0c7044122265c39cec10cf4"
+ integrity sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==
+
"@types/eslint@^7.2.6":
version "7.2.6"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.6.tgz#5e9aff555a975596c03a98b59ecd103decc70c3c"
@@ -1799,6 +1814,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
integrity sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==
+"@types/node@>=10.0.0":
+ version "15.6.0"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-15.6.0.tgz#f0ddca5a61e52627c9dcb771a6039d44694597bc"
+ integrity sha512-gCYSfQpy+LYhOFTKAeE8BkyGqaxmlFxe+n4DKM6DR0wzw/HISUE/hAmkC/KT8Sw5PCJblqg062b3z9gucv3k0A==
+
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
@@ -2024,7 +2044,7 @@
"@typescript-eslint/types" "4.15.2"
eslint-visitor-keys "^2.0.0"
-"@web-lite/api-types@1.1.1":
+"@web-lite/api-types@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@web-lite/api-types/-/api-types-1.1.1.tgz#8908d3b7a37e901421687dde7883dea6f8faadb4"
integrity sha512-pkKuZflguiVRDvNuKPOXChB0SrCD3B5+/x/fneK468fWpg2l7lN5mAkJviAWje+Iqz3g3AojcwPXzWBSyKdN8Q==
@@ -2739,16 +2759,31 @@ babylon@^6.18.0:
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
+backo2@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+ integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
+
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+base64-arraybuffer@0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812"
+ integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=
+
base64-js@^1.0.2:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+base64id@2.0.0, base64id@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
+ integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
+
base@^0.11.1:
version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@@ -3431,7 +3466,7 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
-component-emitter@^1.2.1, component-emitter@^1.3.0:
+component-emitter@^1.2.1, component-emitter@^1.3.0, component-emitter@~1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
@@ -3537,6 +3572,11 @@ cookie@0.4.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
+cookie@~0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
+ integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
+
cookiejar@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
@@ -3587,6 +3627,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+cors@~2.8.5:
+ version "2.8.5"
+ resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
+ integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
+ dependencies:
+ object-assign "^4"
+ vary "^1"
+
cosmiconfig@^5.0.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
@@ -3964,7 +4012,7 @@ debug@^3.1.1, debug@^3.2.6:
dependencies:
ms "^2.1.1"
-debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
+debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
@@ -4352,6 +4400,41 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
+engine.io-client@~5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-5.1.1.tgz#f5c3aaaef1bdc9443aac6ffde48b3b2fb2dc56fc"
+ integrity sha512-jPFpw2HLL0lhZ2KY0BpZhIJdleQcUO9W1xkIpo0h3d6s+5D6+EV/xgQw9qWOmymszv2WXef/6KUUehyxEKomlQ==
+ dependencies:
+ base64-arraybuffer "0.1.4"
+ component-emitter "~1.3.0"
+ debug "~4.3.1"
+ engine.io-parser "~4.0.1"
+ has-cors "1.1.0"
+ parseqs "0.0.6"
+ parseuri "0.0.6"
+ ws "~7.4.2"
+ yeast "0.1.2"
+
+engine.io-parser@~4.0.0, engine.io-parser@~4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-4.0.2.tgz#e41d0b3fb66f7bf4a3671d2038a154024edb501e"
+ integrity sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==
+ dependencies:
+ base64-arraybuffer "0.1.4"
+
+engine.io@~5.1.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-5.1.1.tgz#a1f97e51ddf10cbd4db8b5ff4b165aad3760cdd3"
+ integrity sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==
+ dependencies:
+ accepts "~1.3.4"
+ base64id "2.0.0"
+ cookie "~0.4.1"
+ cors "~2.8.5"
+ debug "~4.3.1"
+ engine.io-parser "~4.0.0"
+ ws "~7.4.2"
+
enhanced-resolve@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
@@ -5454,6 +5537,11 @@ harmony-reflect@^1.4.6:
resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9"
integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA==
+has-cors@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
+ integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
+
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
@@ -7720,7 +7808,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -8056,6 +8144,16 @@ parse5@5.1.1:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178"
integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==
+parseqs@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5"
+ integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==
+
+parseuri@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a"
+ integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==
+
parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -10121,6 +10219,48 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
+socket.io-adapter@~2.3.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz#a442720cb09a4823cfb81287dda1f9b52d4ccdb2"
+ integrity sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw==
+
+socket.io-client@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.1.2.tgz#95ad7113318ea01fba0860237b96d71e1b1fd2eb"
+ integrity sha512-RDpWJP4DQT1XeexmeDyDkm0vrFc0+bUsHDKiVGaNISJvJonhQQOMqV9Vwfg0ZpPJ27LCdan7iqTI92FRSOkFWQ==
+ dependencies:
+ "@types/component-emitter" "^1.2.10"
+ backo2 "~1.0.2"
+ component-emitter "~1.3.0"
+ debug "~4.3.1"
+ engine.io-client "~5.1.1"
+ parseuri "0.0.6"
+ socket.io-parser "~4.0.4"
+
+socket.io-parser@~4.0.3, socket.io-parser@~4.0.4:
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.0.4.tgz#9ea21b0d61508d18196ef04a2c6b9ab630f4c2b0"
+ integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==
+ dependencies:
+ "@types/component-emitter" "^1.2.10"
+ component-emitter "~1.3.0"
+ debug "~4.3.1"
+
+socket.io@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.1.2.tgz#f90f9002a8d550efe2aa1d320deebb9a45b83233"
+ integrity sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==
+ dependencies:
+ "@types/cookie" "^0.4.0"
+ "@types/cors" "^2.8.8"
+ "@types/node" ">=10.0.0"
+ accepts "~1.3.4"
+ base64id "~2.0.0"
+ debug "~4.3.1"
+ engine.io "~5.1.0"
+ socket.io-adapter "~2.3.0"
+ socket.io-parser "~4.0.3"
+
sockjs-client@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add"
@@ -11183,7 +11323,7 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
-vary@~1.1.2:
+vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
@@ -11658,6 +11798,11 @@ ws@^7.2.3:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd"
integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==
+ws@~7.4.2:
+ version "7.4.5"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1"
+ integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==
+
xml-name-validator@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
@@ -11765,6 +11910,11 @@ yargs@^16.2.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
+yeast@0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
+ integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
+
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"