Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Commit

Permalink
fix: Filter badges by worksheet (#1673)
Browse files Browse the repository at this point in the history
* fix: an attempt

* fix: filter badges by worksheet and add test

* Fix test

* add comment
  • Loading branch information
faucomte97 committed Jun 8, 2022
1 parent b335d8d commit c4820ba
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 19 deletions.
30 changes: 29 additions & 1 deletion game_frontend/src/pyodide/badges.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-env jest */
import { checkIfBadgeEarned } from './badges'
import { checkIfBadgeEarned, filterByWorksheet } from './badges'
jest.mock('threads/worker')

describe('Badges check', () => {
Expand Down Expand Up @@ -121,4 +121,32 @@ def next_turn(world_state, avatar_state):

expect(result).toBe(expected)
})

it('filters badges', () => {
const badges = '1:1,1:2,1:3,2:1,2:2,3:1'

let gameState = {worksheetID: 1}

let result = filterByWorksheet(badges, gameState)

let expected = "1:1,1:2,1:3"

expect(result).toBe(expected)

gameState = {worksheetID: 2}

result = filterByWorksheet(badges, gameState)

expected = "2:1,2:2"

expect(result).toBe(expected)

gameState = {worksheetID: 3}

result = filterByWorksheet(badges, gameState)

expected = "3:1"

expect(result).toBe(expected)
})
})
13 changes: 13 additions & 0 deletions game_frontend/src/pyodide/badges.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
/* eslint-env worker */
import ComputedTurnResult from './computedTurnResult'

export function filterByWorksheet(badges: any, gameState: any): string {
const worksheetID = gameState.worksheetID
let badgesArr = badges.split(',')

badgesArr = badgesArr.filter((s) => s) // remove empty element
// remove any badge that's not relevant to the current worksheet
badgesArr = badgesArr.filter((b) => {
return b.startsWith(worksheetID + ':')
})

return badgesArr.join(',')
}

export function checkIfBadgeEarned(
badges: string,
result: ComputedTurnResult,
Expand Down
18 changes: 11 additions & 7 deletions game_frontend/src/pyodide/pyodideRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ import { PyodideWorker } from './webWorker'
let worker: ModuleThread<PyodideWorker>
let workerReady = false

export async function initializePyodide () {
export async function initializePyodide() {
await initializePyodideWorker()
workerReady = true
}

async function initializePyodideWorker () {
async function initializePyodideWorker() {
worker = await spawn<PyodideWorker>(new Worker('./webWorker.ts'))
await worker.initializePyodide()
}

export async function checkIfBadgeEarned (
export async function filterByWorksheet(badges: string, gameState: any): Promise<string> {
return worker.filterByWorksheet(badges, gameState)
}

export async function checkIfBadgeEarned(
badges: string,
result: ComputedTurnResult,
userCode: string,
Expand All @@ -26,7 +30,7 @@ export async function checkIfBadgeEarned (
return worker.checkIfBadgeEarned(badges, result, userCode, gameState, playerAvatarId)
}

export async function updateAvatarCode (
export async function updateAvatarCode(
userCode: string,
gameState: any,
playerAvatarID: number = 0
Expand All @@ -38,15 +42,15 @@ export async function updateAvatarCode (
)
}

export async function resetWorker (userCode: string, playerAvatarID: number) {
export async function resetWorker(userCode: string, playerAvatarID: number) {
workerReady = false
await Thread.terminate(worker)
await initializePyodideWorker()
await worker.updateAvatarCode(userCode, null, playerAvatarID)
workerReady = true
}

async function runIfWorkerReady (
async function runIfWorkerReady(
func: () => Promise<ComputedTurnResult>,
turnCount: number
): Promise<ComputedTurnResult> {
Expand All @@ -56,7 +60,7 @@ async function runIfWorkerReady (
return Promise.resolve({
action: { action: { action_type: 'wait' } },
log: '',
turnCount: turnCount + 1
turnCount: turnCount + 1,
})
}
}
Expand Down
5 changes: 3 additions & 2 deletions game_frontend/src/pyodide/webWorker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-env worker */
import { expose } from 'threads/worker'
import { checkIfBadgeEarned } from "./badges";
import { checkIfBadgeEarned, filterByWorksheet } from './badges'
import ComputedTurnResult from './computedTurnResult'

let pyodide: Pyodide
Expand Down Expand Up @@ -131,7 +131,8 @@ const pyodideWorker = {
initializePyodide,
computeNextAction,
updateAvatarCode,
checkIfBadgeEarned
checkIfBadgeEarned,
filterByWorksheet,
}

export type PyodideWorker = typeof pyodideWorker
Expand Down
6 changes: 6 additions & 0 deletions game_frontend/src/redux/features/AvatarWorker/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const getBadgesRequest = () => ({
type: types.GET_BADGES_REQUEST,
})

const filterBadges = (badges) => ({
type: types.FILTER_BADGES,
payload: badges,
})

const getBadgesReceived = (badges) => ({
type: types.GET_BADGES_SUCCESS,
payload: badges,
Expand Down Expand Up @@ -56,6 +61,7 @@ export default {
avatarCodeUpdated,
avatarsNextActionComputed,
badgesEarned,
filterBadges,
getBadgesRequest,
getBadgesReceived,
checkBadgesReceived,
Expand Down
44 changes: 35 additions & 9 deletions game_frontend/src/redux/features/AvatarWorker/epics.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,45 @@ const computeNextActionEpic = (
const getBadgesEpic = (action$, state$, { api }) =>
action$.pipe(
ofType(types.GET_BADGES_REQUEST),
mergeMap((action) =>
api.get(`badges/${state$.value.game.connectionParameters.game_id}/`).pipe(
map((response) => actions.getBadgesReceived(response.badges)),
catchError((error) =>
of({
type: types.GET_BADGES_FAILURE,
payload: error.xhr.response,
error: true,
})
switchMap(() =>
action$.pipe(
ofType(types.PYODIDE_INITIALIZED),
mergeMap((action) =>
api.get(`badges/${state$.value.game.connectionParameters.game_id}/`).pipe(
map((response) => actions.filterBadges(response.badges)),
catchError((error) =>
of({
type: types.GET_BADGES_FAILURE,
payload: error.xhr.response,
error: true,
})
)
)
)
)
)
)

/**
* Filter the badges to return those that are from the game's worksheet.
* @returns a redux action that contains a string storing the user's earned badges of that worksheet.
*/
const filterBadgesEpic = (action$, state$, { pyodideRunner: { filterByWorksheet } }) =>
action$.pipe(
ofType(types.FILTER_BADGES),
switchMap(({ payload: badges }) =>
from(filterByWorksheet(badges, state$.value.game.gameState))
),
map((badges) => actions.getBadgesReceived(badges)),
catchError((error) =>
of({
type: types.BADGES_CHECKED_FAILURE,
payload: error,
error: true,
})
)
)

/**
* Whenever the avatar's code is updated, get the user's badges information.
* @returns a redux action that contains a string storing the user's earned badges information.
Expand Down Expand Up @@ -189,4 +214,5 @@ export default {
checkBadgesEpic,
postBadgesEpic,
checkBadgesEarnedEpic,
filterBadgesEpic,
}
2 changes: 2 additions & 0 deletions game_frontend/src/redux/features/AvatarWorker/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const AVATARS_NEXT_ACTION_COMPUTED = 'features/AvatarWorker/AVATARS_NEXT_ACTION_
const BADGES_EARNED = 'features/AvatarWorker/BADGES_EARNED'
const BADGES_CHECKED_FAILURE = 'features/AvatarWorker/BADGES_CHECKED_FAILURE'
const BADGES_CHECKED_SUCCESS = 'features/AvatarWorker/BADGES_CHECKED_SUCCESS'
const FILTER_BADGES = 'features/AvatarWorker/FILTER_BADGES'
const GET_BADGES_REQUEST = 'features/AvatarWorker/GET_CODE_REQUEST'
const GET_BADGES_SUCCESS = 'features/AvatarWorker/GET_CODE_SUCCESS'
const GET_BADGES_FAILURE = 'features/AvatarWorker/GET_CODE_FAILURE'
Expand All @@ -23,6 +24,7 @@ export default {
BADGES_EARNED,
BADGES_CHECKED_FAILURE,
BADGES_CHECKED_SUCCESS,
FILTER_BADGES,
GET_BADGES_REQUEST,
GET_BADGES_SUCCESS,
GET_BADGES_FAILURE,
Expand Down

0 comments on commit c4820ba

Please sign in to comment.