Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 36 additions & 47 deletions src/simulator/definitions/challenges/jbc9-Cover-Your-Bases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,25 @@ export default {
name: tr('Robot not in Start Box'),
description: tr('Robot not in start box'),
},
canAUpright: {
name: tr('Can A Upright'),
description: tr('Can A upright in a circle'),
canANotUpright: {
name: tr('Can A Not Upright'),
description: tr('Can A not upright in a circle'),
},
canBUpright: {
name: tr('Can B Upright'),
description: tr('Can B upright in a circle'),
canBNotUpright: {
name: tr('Can B Not Upright'),
description: tr('Can B not upright in a circle'),
},
canCUpright: {
name: tr('Can C Upright'),
description: tr('Can C upright in a circle'),
canCNotUpright: {
name: tr('Can C Not Upright'),
description: tr('Can C not upright in a circle'),
},
canDUpright: {
name: tr('Can D Upright'),
description: tr('Can D upright in a circle'),
canDNotUpright: {
name: tr('Can D Not Upright'),
description: tr('Can D not upright in a circle'),
},
canEUpright: {
name: tr('Can E Upright'),
description: tr('Can E upright in a circle'),
canENotUpright: {
name: tr('Can E Not Upright'),
description: tr('Can E not upright in a circle'),
},
baseACovered: {
name: tr('Base A Covered'),
Expand Down Expand Up @@ -105,59 +105,48 @@ export default {
argIds: ['baseACovered', 'baseBCovered', 'baseCCovered', 'baseDCovered', 'baseECovered'],
},

// Upright Events
canAUpright: {
type: Expr.Type.Event,
eventId: 'canAUpright',
// Success logic: stared in start box and five bases covered
completion: {
type: Expr.Type.And,
argIds: ['inStartBoxOnce', 'allBasesCovered'],
},
},
rootId: 'completion',
},
failure: {
exprs: {
canANotUpright: {
type: Expr.Type.Not,
argId: 'canAUpright',
},
canBUpright: {
type: Expr.Type.Event,
eventId: 'canBUpright',
eventId: 'canANotUpright',
},
canBNotUpright: {
type: Expr.Type.Not,
argId: 'canBUpright',
},
canCUpright: {
type: Expr.Type.Event,
eventId: 'canCUpright',
eventId: 'canBNotUpright',
},
canCNotUpright: {
type: Expr.Type.Not,
argId: 'canCUpright',
},
canDUpright: {
type: Expr.Type.Event,
eventId: 'canDUpright',
eventId: 'canCNotUpright',
},
canDNotUpright: {
type: Expr.Type.Not,
argId: 'canDUpright',
},
canEUpright: {
type: Expr.Type.Event,
eventId: 'canEUpright',
eventId: 'canDNotUpright',
},
canENotUpright: {
type: Expr.Type.Not,
argId: 'canEUpright',
type: Expr.Type.Event,
eventId: 'canENotUpright',
},
allCansUpright: {
allCansNotUpright: {
type: Expr.Type.And,
argIds: ['canAUpright', 'canBUpright', 'canCUpright', 'canDUpright', 'canEUpright'],
argIds: ['canANotUpright', 'canBNotUpright', 'canCNotUpright', 'canDNotUpright', 'canENotUpright'],
},

// Success Logic = Can A upright, intersects and touched
completion: {
// Failure logic based on can uprightness thresholds
failure: {
type: Expr.Type.And,
argIds: ['inStartBoxOnce', 'allBasesCovered', 'allCansUpright'],
argIds: ['canANotUpright', 'canBNotUpright', 'canCNotUpright', 'canDNotUpright', 'canENotUpright'],
},
},
rootId: 'completion',
rootId: 'failure',
},
successGoals: [
{ exprId: 'inStartBoxOnce', name: tr('Start in the Start Box') },
Expand Down
163 changes: 42 additions & 121 deletions src/simulator/definitions/scenes/jbc9-Cover-Your-Bases.ts
Original file line number Diff line number Diff line change
@@ -1,118 +1,65 @@
import Scene from '../../../state/State/Scene';
import { ReferenceFramewUnits } from '../../../util/math/unitMath';
import { Distance } from '../../../util';
import LocalizedString from '../../../util/LocalizedString';
import Script from '../../../state/State/Scene/Script';
import { createBaseSceneSurfaceA, createCanNode, createCircleNode } from './jbcBase';
import { Color } from '../../../state/State/Scene/Color';
import tr from '@i18n';
import { matAStartGeoms, matAStartNodes, nodeUpright, setNodeVisible, notInStartBox } from './jbcCommonComponents';

const baseScene = createBaseSceneSurfaceA();

const notInStartBox = `
scene.addOnIntersectionListener('robot', (type, otherNodeId) => {
// console.log('Robot not started in start box!', type, otherNodeId);
if(scene.programStatus === 'running'){
scene.setChallengeEventValue('notInStartBox', type === 'start');
}
}, 'notStartBox');
`;

const circleIntersectsUpright = `
const setNodeVisible = (nodeId, visible) => scene.setNode(nodeId, {
...scene.nodes[nodeId],
visible
});

const EULER_IDENTITY = RotationwUnits.EulerwUnits.identity();
const yAngle = (nodeId) => 180 / Math.PI * -1 * Math.asin(Vector3wUnits.dot(Vector3wUnits.applyQuaternion(Vector3wUnits.Y, RotationwUnits.toRawQuaternion(scene.nodes[nodeId].origin.orientation || EULER_IDENTITY)), Vector3wUnits.Y));

const cans = ['can1', 'can2', 'can3', 'can4', 'can5', 'can6', 'can7'];
let circles = [false, false, false, false, false, false, false];
let uprights = [true, true, true, true, true, true, true];

${setNodeVisible}
${nodeUpright}
const cans = new Map([
['can1', false],
['can2', false],
['can3', false],
['can4', false],
['can5', false],
['can6', false],
['can7', false],
]);

// Rules for jbc9 are updated:
// There may be more that one circle on a can.
scene.addOnRenderListener(() => {
let circleCount = 0;
let uprightCount = 0;

for (const circle of circles) {
if (circle) {
circleCount++;
}
if(scene.programStatus === 'running'){
const covered = new Map(cans.entries().filter((c) => c[1]));
scene.setChallengeEventValue('baseACovered', covered.size > 0);
scene.setChallengeEventValue('baseBCovered', covered.size > 1);
scene.setChallengeEventValue('baseCCovered', covered.size > 2);
scene.setChallengeEventValue('baseDCovered', covered.size > 3);
scene.setChallengeEventValue('baseECovered', covered.size > 4);
const notUpright = covered.keys().reduce((count, k) => !nodeUpright(k) ? ++count : count, 0);
scene.setChallengeEventValue('canANotUpright', notUpright > 0);
scene.setChallengeEventValue('canBNotUpright', notUpright > 1);
scene.setChallengeEventValue('canCNotUpright', notUpright > 2);
scene.setChallengeEventValue('canDNotUpright', notUpright > 3);
scene.setChallengeEventValue('canENotUpright', notUpright > 4);
}
scene.setChallengeEventValue('baseACovered', circleCount > 0);
scene.setChallengeEventValue('baseBCovered', circleCount > 1);
scene.setChallengeEventValue('baseCCovered', circleCount > 2);
scene.setChallengeEventValue('baseDCovered', circleCount > 3);
scene.setChallengeEventValue('baseECovered', circleCount > 4);

for (const upright of uprights) {
if (upright) {
uprightCount++;
// Users must complete challenge in one run
else {
for (const k of cans.keys()) {
cans.set(k, false);
}
}
scene.setChallengeEventValue('canAUpright', uprightCount > 0);
scene.setChallengeEventValue('canBUpright', uprightCount > 1);
scene.setChallengeEventValue('canCUpright', uprightCount > 2);
scene.setChallengeEventValue('canDUpright', uprightCount > 3);
scene.setChallengeEventValue('canEUpright', uprightCount > 4);
});

scene.addOnIntersectionListener('circle1', (type, otherNodeId) => {
const visible = type === 'start';
circles[0] = visible;
setNodeVisible('circle1', visible);
uprights[0] = yAngle(otherNodeId) > 5;
}, [...cans]);

scene.addOnIntersectionListener('circle2', (type, otherNodeId) => {
const visible = type === 'start';
circles[1] = visible;
setNodeVisible('circle2', visible);
uprights[1] = yAngle(otherNodeId) > 5;
}, [...cans]);

scene.addOnIntersectionListener('circle3', (type, otherNodeId) => {
const visible = type === 'start';
circles[2] = visible;
setNodeVisible('circle3', visible);
uprights[2] = yAngle(otherNodeId) > 5;
}, [...cans]);

scene.addOnIntersectionListener('circle4', (type, otherNodeId) => {
const visible = type === 'start';
circles[3] = visible;
setNodeVisible('circle4', visible);
uprights[3] = yAngle(otherNodeId) > 5;
}, [...cans]);

scene.addOnIntersectionListener('circle5', (type, otherNodeId) => {
const visible = type === 'start';
circles[4] = visible;
setNodeVisible('circle5', visible);
uprights[4] = yAngle(otherNodeId) > 5;
}, [...cans]);

scene.addOnIntersectionListener('circle6', (type, otherNodeId) => {
const visible = type === 'start';
circles[5] = visible;
setNodeVisible('circle6', visible);
uprights[5] = yAngle(otherNodeId) > 5;
}, [...cans]);

scene.addOnIntersectionListener('circle7', (type, otherNodeId) => {
const visible = type === 'start';
circles[6] = visible;
setNodeVisible('circle7', visible);
uprights[6] = yAngle(otherNodeId) > 5;
}, [...cans]);
for (let i = 0; i < cans.size; i++) {
const circleName = 'circle' + (i + 1);
scene.addOnIntersectionListener(circleName, (type, otherNodeId) => {
cans.set(otherNodeId, type === 'start');
//console.log(circleName, otherNodeId, type, cans);
}, cans.keys().toArray());
}
`;

const ROBOT_ORIGIN: ReferenceFramewUnits = {
...baseScene.nodes['robot'].origin,
position: {
...baseScene.nodes['robot'].origin.position,
z: Distance.centimeters(-8),
z: Distance.centimeters(-10),
},
};

Expand All @@ -126,37 +73,11 @@ export const JBC_9: Scene = {
},
geometry: {
...baseScene.geometry,
notStartBox_geom: {
type: 'box',
size: {
x: Distance.meters(3.54),
y: Distance.centimeters(10),
z: Distance.meters(2.14),
},
},
...matAStartGeoms
},
nodes: {
...baseScene.nodes,
notStartBox: {
type: 'object',
geometryId: 'notStartBox_geom',
name: tr('Not Start Box'),
visible: false,
origin: {
position: {
x: Distance.centimeters(0),
y: Distance.centimeters(-1.9),
z: Distance.meters(1.188),
},
},
material: {
type: 'basic',
color: {
type: 'color3',
color: Color.rgb(255, 0, 0),
},
},
},
...matAStartNodes,
// The normal starting position of the robot covers the tape
// Start the robot back a bit so that a can fits on the tape in front of the robot
robot: {
Expand Down