From a73515984903be4c8eb93970bd4683c44e49bf82 Mon Sep 17 00:00:00 2001 From: twells46 <173561638+twells46@users.noreply.github.com> Date: Tue, 9 Dec 2025 15:00:36 -0600 Subject: [PATCH] Update jbc9 --- .../challenges/jbc9-Cover-Your-Bases.ts | 83 ++++----- .../scenes/jbc9-Cover-Your-Bases.ts | 163 +++++------------- 2 files changed, 78 insertions(+), 168 deletions(-) diff --git a/src/simulator/definitions/challenges/jbc9-Cover-Your-Bases.ts b/src/simulator/definitions/challenges/jbc9-Cover-Your-Bases.ts index 3839d47f..0b7092d8 100644 --- a/src/simulator/definitions/challenges/jbc9-Cover-Your-Bases.ts +++ b/src/simulator/definitions/challenges/jbc9-Cover-Your-Bases.ts @@ -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'), @@ -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') }, diff --git a/src/simulator/definitions/scenes/jbc9-Cover-Your-Bases.ts b/src/simulator/definitions/scenes/jbc9-Cover-Your-Bases.ts index 4ed858c6..6c5686d2 100644 --- a/src/simulator/definitions/scenes/jbc9-Cover-Your-Bases.ts +++ b/src/simulator/definitions/scenes/jbc9-Cover-Your-Bases.ts @@ -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), }, }; @@ -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: {