-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
238 additions
and
41 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* eslint-env jest */ | ||
import { checkIfBadgeEarned } from './badges' | ||
jest.mock('threads/worker') | ||
|
||
describe('Badges check', () => { | ||
it('awards badge 1 if the right conditions are met', () => { | ||
const badges = '' | ||
const turnResult = { | ||
action: { | ||
action_type: 'move', | ||
options: { | ||
direction: { x: 0, y: -1 }, | ||
}, | ||
}, | ||
log: '', | ||
turnCount: 1, | ||
} | ||
const userCode = '' | ||
const gameState = { worksheetID: 1 } | ||
const playerAvatarId = 1 | ||
|
||
const result = checkIfBadgeEarned(badges, turnResult, userCode, gameState, playerAvatarId) | ||
|
||
const expected = '1:1,' | ||
|
||
expect(result).toBe(expected) | ||
}) | ||
|
||
it('awards badges 1 and 2 if the right conditions are met', () => { | ||
const badges = '' | ||
const turnResult = { | ||
action: { | ||
action_type: 'move', | ||
options: { | ||
direction: { x: 0, y: -1 }, | ||
}, | ||
}, | ||
log: '', | ||
turnCount: 1, | ||
} | ||
const userCode = ` | ||
import random | ||
def next_turn(world_state, avatar_state): | ||
number = random.randint(1,4) | ||
if number == 1: | ||
new_dir = direction.NORTH | ||
elif number == 2: | ||
new_dir = direction.EAST | ||
elif number == 3: | ||
new_dir = direction.SOUTH | ||
else: | ||
new_dir = direction.WEST | ||
action = MoveAction(new_dir) | ||
return action | ||
` | ||
const gameState = { worksheetID: 1 } | ||
const playerAvatarId = 1 | ||
|
||
const result = checkIfBadgeEarned(badges, turnResult, userCode, gameState, playerAvatarId) | ||
|
||
const expected = '1:1,1:2,' | ||
|
||
expect(result).toBe(expected) | ||
}) | ||
|
||
it('awards badges 1, 2 and 3 if the right conditions are met', () => { | ||
const badges = '' | ||
const turnResult = { | ||
action: { | ||
action_type: 'move', | ||
options: { | ||
direction: { x: 0, y: -1 }, | ||
}, | ||
}, | ||
log: '', | ||
turnCount: 1, | ||
} | ||
const userCode = ` | ||
import random | ||
def next_turn(world_state, avatar_state): | ||
number = random.randint(1,4) | ||
if number == 1: | ||
new_dir = direction.NORTH | ||
elif number == 2: | ||
new_dir = direction.EAST | ||
elif number == 3: | ||
new_dir = direction.SOUTH | ||
else: | ||
new_dir = direction.WEST | ||
next_location = avatar_state.location + new_dir | ||
print("The co-ordinates of the next cell are", next_location) | ||
if world_state.can_move_to(next_location): | ||
print("Yes, I can move") | ||
else: | ||
print("I can't move there!") | ||
action = MoveAction(new_dir) | ||
return action | ||
` | ||
const gameState = { | ||
worksheetID: 1, | ||
players: [ | ||
{ | ||
id: 1, | ||
location: { x: 10, y: 10 }, | ||
}, | ||
], | ||
obstacles: [], | ||
} | ||
const playerAvatarId = 1 | ||
|
||
const result = checkIfBadgeEarned(badges, turnResult, userCode, gameState, playerAvatarId) | ||
|
||
const expected = '1:1,1:2,1:3,' | ||
|
||
expect(result).toBe(expected) | ||
}) | ||
}) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,121 @@ | ||
// /* eslint-env worker */ | ||
// import ComputedTurnResult from './computedTurnResult' | ||
// import fetch from 'node-fetch' | ||
|
||
// interface TestReport { | ||
// task_id: number // eslint-disable-line | ||
// } | ||
|
||
// export async function checkIfBadgeEarned( | ||
// badges: string, | ||
// result: ComputedTurnResult, | ||
// userCode: string, | ||
// gameState: any, | ||
// currentAvatarID: number | ||
// ): Promise<string> { | ||
// // TODO: fix loading of environment variables. | ||
// let serviceUrl = process.env.REACT_APP_KURONO_BADGES_URL; | ||
// if (serviceUrl === undefined) { | ||
// serviceUrl = "https://production-kurono-badges-dot-decent-digit-629.appspot.com" | ||
// } | ||
|
||
// const response = await fetch(serviceUrl, { | ||
// method: "POST", | ||
// headers: { | ||
// "Content-Type": "application/json" | ||
// }, | ||
// body: JSON.stringify({ | ||
// source: { code: userCode }, | ||
// current_avatar_id: currentAvatarID, | ||
// game_state: gameState | ||
// }) | ||
// }); | ||
|
||
// const responseJson: { | ||
// passed: TestReport[] | ||
// failed: TestReport[] | ||
// xfailed: TestReport[] | ||
// skipped: TestReport[] | ||
// } = await response.json(); | ||
|
||
// for (let i = 0; i < responseJson.passed.length; i++) { | ||
// const badgeWorksheetPair = `${gameState.worksheetID}:${responseJson.passed[i].task_id}`; | ||
// if (!badges.includes(badgeWorksheetPair)) { | ||
// badges += `${badgeWorksheetPair},` | ||
// } | ||
// } | ||
|
||
// return badges; | ||
// } | ||
|
||
/* eslint-env worker */ | ||
import ComputedTurnResult from './computedTurnResult' | ||
import fetch from 'node-fetch' | ||
|
||
interface TestReport { | ||
task_id: number // eslint-disable-line | ||
} | ||
|
||
export async function checkIfBadgeEarned( | ||
export function checkIfBadgeEarned( | ||
badges: string, | ||
result: ComputedTurnResult, | ||
userCode: string, | ||
gameState: any, | ||
currentAvatarID: number | ||
): Promise<string> { | ||
// TODO: fix loading of environment variables. | ||
let serviceUrl = process.env.REACT_APP_KURONO_BADGES_URL; | ||
if (serviceUrl === undefined) { | ||
serviceUrl = "https://production-kurono-badges-dot-decent-digit-629.appspot.com" | ||
} | ||
|
||
const response = await fetch(serviceUrl, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json" | ||
gameState: any | ||
): string { | ||
const userPythonCode = userCode.replace(/\s*#.*/gm, '') // Remove all comment lines from the user's code | ||
const badgesPerWorksheet = [ | ||
{ id: 1, worksheetID: 1, trigger: badge1Trigger(result) }, | ||
{ id: 2, worksheetID: 1, trigger: badge2Trigger(result, userPythonCode) }, | ||
{ | ||
id: 3, | ||
worksheetID: 1, | ||
trigger: badge3Trigger(result, userPythonCode), | ||
}, | ||
body: JSON.stringify({ | ||
source: { code: userCode }, | ||
current_avatar_id: currentAvatarID, | ||
game_state: gameState | ||
}) | ||
}); | ||
|
||
const responseJson: { | ||
passed: TestReport[] | ||
failed: TestReport[] | ||
xfailed: TestReport[] | ||
skipped: TestReport[] | ||
} = await response.json(); | ||
|
||
for (let i = 0; i < responseJson.passed.length; i++) { | ||
const badgeWorksheetPair = `${gameState.worksheetID}:${responseJson.passed[i].task_id}`; | ||
if (!badges.includes(badgeWorksheetPair)) { | ||
] | ||
|
||
for (const badge of badgesPerWorksheet) { | ||
const badgeWorksheetPair = `${badge.worksheetID}:${badge.id}` | ||
if ( | ||
!badges.includes(badgeWorksheetPair) && | ||
badge.worksheetID === gameState.worksheetID && | ||
badge.trigger | ||
) { | ||
// Here is when a new badge is earned | ||
// TODO on worksheet 2: This might have to order the badges, in case user does not do the worksheet in order | ||
badges += `${badgeWorksheetPair},` | ||
} | ||
} | ||
return badges | ||
} | ||
|
||
function badge1Trigger(result: any): boolean { | ||
// Check the code returns a move action other than NORTH | ||
return ( | ||
result.action.action_type === 'move' && | ||
JSON.stringify(result.action.options.direction) !== JSON.stringify({ x: 0, y: 1 }) | ||
) | ||
} | ||
|
||
function badge2Trigger(result: any, userPythonCode: string): boolean { | ||
// Check code contains keywords to move in random directions | ||
const substrings = [ | ||
'import random', | ||
'randint(', | ||
'direction.NORTH', | ||
'direction.EAST', | ||
'direction.SOUTH', | ||
'direction.WEST', | ||
'if ', | ||
'elif ', | ||
'else:', | ||
] | ||
// Check the code contains certain keywords about moving in a random direction | ||
const codeContainsKeywords = substrings.every((substring) => userPythonCode.includes(substring)) | ||
|
||
// And check it returns a move action | ||
return result.action.action_type === 'move' && codeContainsKeywords | ||
} | ||
|
||
function badge3Trigger(result: any, userPythonCode: string): boolean { | ||
// Check the code contains certain keywords about moving to a cell | ||
const substrings = ['world_state.can_move_to(', 'print(', 'if '] | ||
const codeContainsKeywords = substrings.every((substring) => userPythonCode.includes(substring)) | ||
|
||
return badges; | ||
// And check it returns a move action | ||
return result.action.action_type === 'move' && codeContainsKeywords | ||
} |
This file contains 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
This file contains 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