Skip to content

Commit

Permalink
Merge pull request #485 from kipr/simChallenges
Browse files Browse the repository at this point in the history
Sim challenges
  • Loading branch information
tcorbly authored Sep 24, 2024
2 parents 0b93557 + 1770901 commit 464e7d8
Show file tree
Hide file tree
Showing 69 changed files with 10,964 additions and 283 deletions.
1,069 changes: 1,069 additions & 0 deletions i18n/i18n.json

Large diffs are not rendered by default.

Empty file added src/SceneBinding.ts
Empty file.
49 changes: 49 additions & 0 deletions src/ScriptManager/ScriptSceneBinding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Dict from '../util/objectOps/Dict';
import Camera from '../state/State/Scene/Camera';
import Geometry from '../state/State/Scene/Geometry';
import Node from '../state/State/Scene/Node';
import { Vector3wUnits } from '../util/math/unitMath';

export type Ids = string | string[] | Set<string>;

export namespace Ids {
export const toSet = (ids: Ids): Set<string> => {
if (typeof ids === 'string') return new Set([ids]);
if (Array.isArray(ids)) return new Set(ids);
return ids;
};
}

export interface ScriptSceneBinding {
readonly nodes: Dict<Node>;
addNode(node: Node, id?: string): string;
removeNode(id: string): void;
setNode(id: string, node: Node);

readonly geometry: Dict<Geometry>;
addGeometry(geometry: Geometry, id?: string): string;
removeGeometry(id: string): void;

gravity: Vector3wUnits;

camera: Camera;

selectedNodeId?: string;

readonly programStatus: 'running' | 'stopped';

addOnRenderListener(cb: () => void): string;
addOnCollisionListener(nodeId: string, cb: (otherNodeId: string, point: Vector3wUnits) => void, filterIds: Ids): string;
addOnIntersectionListener(nodeId: string, cb: (type: 'start' | 'end', otherNodeId: string) => void, filterIds: Ids): string;
addOnClickListener(filterIds: Ids, cb: (nodeId: string) => void): string;
removeListener(handle: string): void;

onBind?: (nodeId: string) => void;
onUnbind?: (nodeId: string) => void;
onDispose?: () => void;

// Used only for unit tests
postTestResult: (data: unknown) => void;

setChallengeEventValue: (eventId: string, value: boolean) => void;
}
24 changes: 18 additions & 6 deletions src/components/Challenge/ChallengeMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { Layout, LayoutPicker } from '../Layout';
import { SimulatorState } from './SimulatorState';
import { GREEN, RED, ThemeProps } from '../constants/theme';

import KIPR_LOGO_BLACK from '../../../static/assets/KIPR-Logo-Black-Text-Clear-Large.png';
import KIPR_LOGO_WHITE from '../../../static/assets/KIPR-Logo-White-Text-Clear-Large.png';
import { faBars, faFlagCheckered, faBook, faClone, faCogs, faCommentDots, faGlobeAmericas, faPlay, faQuestion, faSignOutAlt, faStop, faSync } from '@fortawesome/free-solid-svg-icons';
import SceneMenu from '../World/SceneMenu';
import ExtraMenu from './ExtraMenu';

namespace SubMenu {
export enum Type {
None,
Expand Down Expand Up @@ -60,6 +66,7 @@ export interface MenuProps extends StyleProps, ThemeProps {
onDashboardClick: () => void;
onLogoutClick: () => void;

onEndChallengeClick: () => void;
simulatorState: SimulatorState;
}

Expand All @@ -70,12 +77,6 @@ interface MenuState {
type Props = MenuProps;
type State = MenuState;

import KIPR_LOGO_BLACK from '../../../static/assets/KIPR-Logo-Black-Text-Clear-Large.png';
import KIPR_LOGO_WHITE from '../../../static/assets/KIPR-Logo-White-Text-Clear-Large.png';
import { faBars, faBook, faClone, faCogs, faCommentDots, faGlobeAmericas, faPlay, faQuestion, faSignOutAlt, faStop, faSync } from '@fortawesome/free-solid-svg-icons';
import SceneMenu from '../World/SceneMenu';
import ExtraMenu from './ExtraMenu';

const Container = styled('div', (props: ThemeProps) => ({
backgroundColor: props.theme.backgroundColor,
color: props.theme.color,
Expand Down Expand Up @@ -226,6 +227,7 @@ class ChallengeMenu extends React.PureComponent<Props, State> {
onDocumentationClick,
onDashboardClick,
onLogoutClick,
onEndChallengeClick,
simulatorState
} = props;

Expand Down Expand Up @@ -263,6 +265,16 @@ class ChallengeMenu extends React.PureComponent<Props, State> {

<Spacer style={{ borderRight: `1px solid ${theme.borderColor}` }} />

<Item theme={theme} onClick={onEndChallengeClick} style={{ position: 'relative' }}>
<ItemIcon icon={faFlagCheckered} /> End Challenge

</Item>

<Item theme={theme} onClick={onEndChallengeClick} style={{ position: 'relative' }}>
<ItemIcon icon={faFlagCheckered} /> End Challenge

</Item>

<Item theme={theme} onClick={this.onLayoutClick_} style={{ position: 'relative' }}>
<ItemIcon icon={faClone} /> Layout
{subMenu.type === SubMenu.Type.LayoutPicker ? (
Expand Down
3 changes: 0 additions & 3 deletions src/components/Challenge/SimMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,6 @@ interface MenuState {
type Props = MenuPublicProps & MenuPrivateProps;
type State = MenuState;




const Container = styled('div', (props: ThemeProps) => ({
backgroundColor: props.theme.backgroundColor,
color: props.theme.color,
Expand Down
5 changes: 5 additions & 0 deletions src/pages/ChallengeRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,10 @@ class Root extends React.Component<Props, State> {
});
};

private onEndChallengeClick_ = () => {
window.location.href = `/scene/${this.props.match.params.challengeId}`;
};

private onResetCode_ = () => {
this.setState({
modal: Modal.RESET_CODE
Expand Down Expand Up @@ -873,6 +877,7 @@ class Root extends React.Component<Props, State> {
onDocumentationClick={onDocumentationClick}
onDashboardClick={this.onDashboardClick}
onLogoutClick={this.onLogoutClick}
onEndChallengeClick={this.onEndChallengeClick_}
simulatorState={simulatorState}
/>
{impl}
Expand Down
2 changes: 1 addition & 1 deletion src/programming/SharedRegistersRobot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { clamp } from '../util/math/math';
import RegisterState from './registers/RegisterState';
import SharedRegisters from './registers/SharedRegisters';

class SharedRegistersRobot implements AbstractRobot {
export class SharedRegistersRobot implements AbstractRobot {
private sharedResisters_: SharedRegisters;

private static readonly POSITION_GOAL_SCALING = 250;
Expand Down
15 changes: 13 additions & 2 deletions src/simulator/ScriptManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { v4 as uuid } from 'uuid';
import construct from '../util/redux/construct';
import { RawAxisAngle, RawQuaternion, RawReferenceFrame, RawVector3 } from '../util/math/math';
import { Angle, Mass, Distance } from '../util/math/Value';
import { SharedRegistersRobot } from '../programming/SharedRegistersRobot';


export type Ids = string | string[] | Set<string>;
Expand Down Expand Up @@ -57,7 +58,6 @@ export interface ScriptSceneBinding {
setChallengeEventValue: (eventId: string, value: boolean) => void;
}


class ScriptManager {
private scene_: Scene;

Expand All @@ -76,7 +76,7 @@ class ScriptManager {
onSelectedNodeIdChange?: (id: string) => void;

onChallengeSetEventValue?: (eventId: string, value: boolean) => void;

onChallengeGetEventValue?: (eventId: string, value: boolean) => boolean;
private programStatus_: 'running' | 'stopped' = 'stopped';
get programStatus() { return this.programStatus_; }
set programStatus(status: 'running' | 'stopped') {
Expand Down Expand Up @@ -584,8 +584,19 @@ namespace ScriptManager {
setChallengeEventValue(eventId: string, value: boolean) {
if (!this.manager_.onChallengeSetEventValue) return;
this.manager_.onChallengeSetEventValue(eventId, value);
this.getChallengeEventValue(eventId,value);
}

getChallengeEventValue(eventId: string, value: boolean) {
if (!this.manager_.onChallengeGetEventValue) return;
return value;
this.getChallengeEventValue(eventId,value);
}
}




}

export default ScriptManager;
105 changes: 105 additions & 0 deletions src/simulator/definitions/challenges/jbc1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import Author from "../../../db/Author";
import Challenge from "../../../state/State/Challenge";
import Expr from "../../../state/State/Challenge/Expr";
import LocalizedString from "../../../util/LocalizedString";
import ProgrammingLanguage from "../../../programming/compiler/ProgrammingLanguage";

export default {
name: { [LocalizedString.EN_US]: 'JBC Challenge 1' },
description: { [LocalizedString.EN_US]: `Junior Botball Challenge 1: Tag, You're it!` },
author: {
type: Author.Type.Organization,
id: 'kipr'
},
code: {
'c': ProgrammingLanguage.DEFAULT_CODE.c,
'cpp': ProgrammingLanguage.DEFAULT_CODE.cpp,
'python': ProgrammingLanguage.DEFAULT_CODE.python,
},
defaultLanguage: 'c',
events: {
can9Touched: {
name: { [LocalizedString.EN_US]: 'Can A Touched' },
description: { [LocalizedString.EN_US]: 'Can A touched' },
},
canAIntersects: {
name: { [LocalizedString.EN_US]: 'Can A Intersects' },
description: { [LocalizedString.EN_US]: 'Can A intersects circle 9' },
},

canAUpright: {
name: { [LocalizedString.EN_US]: 'Can A Upright' },
description: { [LocalizedString.EN_US]: 'Can A upright on circle 9' },
},

leaveStartBox: {
name: { [LocalizedString.EN_US]: 'Robot Left Start' },
description: { [LocalizedString.EN_US]: 'Robot left starting box' },
},
returnStartBox: {
name: { [LocalizedString.EN_US]: 'Robot Rentered Start' },
description: { [LocalizedString.EN_US]: 'Robot reentered starting box' },
},
},
success: {
exprs: {
// Touch Events
can9Touched: {
type: Expr.Type.Event,
eventId: 'can9Touched',
},

// Intersects Events
canAIntersects: {
type: Expr.Type.Event,
eventId: 'canAIntersects',
},

// Upright Events
canAUpright: {
type: Expr.Type.Event,
eventId: 'canAUpright',
},

// Start Box Events
leaveStartBox: {
type: Expr.Type.Event,
eventId: 'leaveStartBox',
},
leaveStartBoxOnce: {
type: Expr.Type.Once,
argId: 'leaveStartBox',
},

returnStartBox: {
type: Expr.Type.Event,
eventId: 'returnStartBox',
},
returnStartBoxOnce: {
type: Expr.Type.Once,
argId: 'returnStartBox',
},



startingBox:{
type:Expr.Type.And,
argIds:['leaveStartBoxOnce', 'returnStartBoxOnce'],
},

// Intersects and upright logic
aIntersectsUpright: {
type: Expr.Type.And,
argIds: ['canAIntersects', 'canAUpright'],
},

// Success Logic = Can A upright, intersects and touched
completion: {
type: Expr.Type.And,
argIds: ['can9Touched', 'aIntersectsUpright', 'startingBox'],
},
},
rootId: 'completion',
},
sceneId: 'jbc1',
} as Challenge;
89 changes: 89 additions & 0 deletions src/simulator/definitions/challenges/jbc10.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import Author from '../../../db/Author';
import Challenge from '../../../state/State/Challenge';
import Expr from '../../../state/State/Challenge/Expr';
import LocalizedString from '../../../util/LocalizedString';
import ProgrammingLanguage from "../../../programming/compiler/ProgrammingLanguage";

export default {
name: { [LocalizedString.EN_US]: 'JBC Challenge 10' },
description: {
[LocalizedString.EN_US]: `Junior Botball Challenge 10: Solo Joust`,
},
author: {
type: Author.Type.Organization,
id: 'kipr',
},
code: {
'c': ProgrammingLanguage.DEFAULT_CODE.c,
'cpp': ProgrammingLanguage.DEFAULT_CODE.cpp,
'python': ProgrammingLanguage.DEFAULT_CODE.python,
},
defaultLanguage: 'c',
events: {

can1Upright: {
name: { [LocalizedString.EN_US]: 'Can A Upright' },
description: {
[LocalizedString.EN_US]: 'Can A upright in a circle',
},
},
leaveStartBox: {
name: { [LocalizedString.EN_US]: 'Robot Left Start' },
description: { [LocalizedString.EN_US]: 'Robot left starting box' },
},
robotTouchingLine: {
name: { [LocalizedString.EN_US]: 'Robot Touching Line B' },
description: { [LocalizedString.EN_US]: 'Robot is touching line B' },
},

},
success: {
exprs: {


// Upright Events
can1Upright: {
type: Expr.Type.Event,
eventId: 'can1Upright',
},
can1NotUpright: {
type: Expr.Type.Not,
argId: 'can1Upright',
},

// Line B Event
robotTouchingLine: {
type: Expr.Type.Event,
eventId: 'robotTouchingLine',
},
robotNotTouchingLine: {
type: Expr.Type.Not,
argId: 'robotTouchingLine',
},

// Can 1 Not Upright and Robot Not Touching Line B
NotUprightNotTouching: {
type: Expr.Type.And,
argIds: ['can1NotUpright', 'robotNotTouchingLine'],
},

// Start Box Events
leaveStartBox: {
type: Expr.Type.Event,
eventId: 'leaveStartBox',
},
leaveStartBoxOnce: {
type: Expr.Type.Once,
argId: 'leaveStartBox',
},


completion: {
type: Expr.Type.And,
argIds: ['leaveStartBoxOnce', 'NotUprightNotTouching'],
},
},
rootId: 'completion',
},
sceneId: 'jbc10',
} as Challenge;
Loading

0 comments on commit 464e7d8

Please sign in to comment.