Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Token Counter Displayer in Repl #2775

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1f9c089
Create new InterpreterOutput type in repl for notifications
jayjay19630 Feb 3, 2024
7d1ae61
Add notification card in Repl component
jayjay19630 Feb 3, 2024
58ff3ad
Add style to notification ReplOutput
jayjay19630 Feb 3, 2024
8376a62
Add fields to workspace state for storing notification string
jayjay19630 Feb 3, 2024
9d4282d
Create logic for handling custom notifications and token counter string
jayjay19630 Feb 3, 2024
8b1137a
Create button in ground control enable/disable token counter
jayjay19630 Feb 3, 2024
b087c55
Edit upload assessment form data to include hasTokenCounter field
jayjay19630 Feb 3, 2024
63613e1
Add workspace actions to handle enabling token counter
jayjay19630 Feb 3, 2024
729d8ea
Revert "Edit upload assessment form data to include hasTokenCounter f…
jayjay19630 Feb 3, 2024
d064e89
Revert "Create button in ground control enable/disable token counter"
jayjay19630 Feb 3, 2024
6be90d1
Add hasTokenCount toggle button on assessment configuration panel
jayjay19630 Feb 3, 2024
d712142
Integrate token counter
jayjay19630 Feb 6, 2024
fdb74aa
Merge branch 'source-academy:master' into ReplNotificationDisplayer
jayjay19630 Feb 6, 2024
d22544b
Conditionally render token counter depending on assessment config
jayjay19630 Feb 6, 2024
98f9b5a
Merge branch 'ReplNotificationDisplayer' of github.com:jayjay19630/so…
jayjay19630 Feb 6, 2024
8835578
Remove console.log
jayjay19630 Feb 12, 2024
d17398b
Merge branch 'ReplNotificationDisplayer' of github.com:jayjay19630/so…
jayjay19630 Feb 12, 2024
8cde9b1
Merge branch 'source-academy:master' into ReplNotificationDisplayer
jayjay19630 Feb 12, 2024
76ee585
Merge branch 'ReplNotificationDisplayer' of github.com:jayjay19630/so…
jayjay19630 Feb 12, 2024
a0aa6fb
Fix bug where turning off token counter would not work in repl
jayjay19630 Feb 12, 2024
32d9e1d
Fix compile time errors
jayjay19630 Feb 12, 2024
0e0a04b
Merge branch 'master' into ReplNotificationDisplayer
jayjay19630 Feb 12, 2024
bd076a6
Make token count message more concise
jayjay19630 Feb 12, 2024
cf045be
Refactor code for readability and css best practices
jayjay19630 Feb 13, 2024
733e934
Merge branch 'master' into ReplNotificationDisplayer
jayjay19630 Feb 13, 2024
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
20 changes: 19 additions & 1 deletion src/commons/application/ApplicationTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,22 @@ export type ErrorOutput = {
consoleLogs: string[];
};

export type InterpreterOutput = RunningOutput | CodeOutput | ResultOutput | ErrorOutput;
/**
* An output which represents a message being displayed to the user. Not a true
* result from the program, but rather a customised notification meant to highlight
* events that occur outside execution of the program.
*/
export type NotificationOutput = {
type: 'notification';
consoleLog: string;
};

export type InterpreterOutput =
| RunningOutput
| CodeOutput
| ResultOutput
| ErrorOutput
| NotificationOutput;

export enum Role {
Student = 'student',
Expand Down Expand Up @@ -360,6 +375,9 @@ export const createDefaultWorkspace = (workspaceLocation: WorkspaceLocation): Wo
originalValue: ''
},
replValue: '',
hasTokenCounter: false,
tokenCount: 0,
customNotification: '',
sharedbConnected: false,
stepLimit: 1000,
globals: [],
Expand Down
9 changes: 9 additions & 0 deletions src/commons/application/actions/__tests__/SessionActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand All @@ -282,6 +283,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission2',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand All @@ -290,6 +292,7 @@ test('setAssessmentConfigurations generates correct action object', () => {
type: 'Mission3',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
Expand Down Expand Up @@ -640,6 +643,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand All @@ -648,6 +652,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Quests',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand All @@ -656,6 +661,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Paths',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand All @@ -664,6 +670,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Contests',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand All @@ -672,6 +679,7 @@ test('updateAssessmentTypes generates correct action object', () => {
type: 'Others',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
Expand All @@ -689,6 +697,7 @@ test('deleteAssessmentConfig generates correct action object', () => {
type: 'Mission1',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
};
Expand Down
2 changes: 2 additions & 0 deletions src/commons/assessment/AssessmentTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export type Assessment = {
type: AssessmentType;
globalDeployment?: Library; // For mission control
graderDeployment?: Library; // For mission control
hasTokenCounter?: boolean;
id: number;
longSummary: string;
missionPDF: string;
Expand All @@ -95,6 +96,7 @@ export type AssessmentConfiguration = {
displayInDashboard: boolean;
hoursBeforeEarlyXpDecay: number;
earlySubmissionXp: number;
hasTokenCounter: boolean;
};

export interface IProgrammingQuestion extends BaseQuestion {
Expand Down
1 change: 1 addition & 0 deletions src/commons/assessment/__tests__/Assessment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const mockAssessmentProps = assertType<AssessmentProps>()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
}
Expand Down
27 changes: 24 additions & 3 deletions src/commons/assessmentWorkspace/AssessmentWorkspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ import {
changeExecTime,
changeSideContentHeight,
clearReplOutput,
disableTokenCounter,
enableTokenCounter,
evalEditor,
evalRepl,
evalTestcase,
Expand Down Expand Up @@ -111,6 +113,7 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
const { isMobileBreakpoint } = useResponsive();

const assessment = useTypedSelector(state => state.session.assessments.get(props.assessmentId));

const [selectedTab, setSelectedTab] = useState(
assessment?.questions[props.questionId].grader !== undefined
? SideContentType.grading
Expand Down Expand Up @@ -149,7 +152,9 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
handleEditorUpdateBreakpoints,
handleReplEval,
handleSave,
handleUpdateHasUnsavedChanges
handleUpdateHasUnsavedChanges,
handleEnableTokenCounter,
handleDisableTokenCounter
} = useMemo(() => {
return {
handleTestcaseEval: (id: number) => dispatch(evalTestcase(workspaceLocation, id)),
Expand All @@ -173,7 +178,9 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
handleSave: (id: number, answer: number | string | ContestEntry[]) =>
dispatch(submitAnswer(id, answer)),
handleUpdateHasUnsavedChanges: (hasUnsavedChanges: boolean) =>
dispatch(updateHasUnsavedChanges(workspaceLocation, hasUnsavedChanges))
dispatch(updateHasUnsavedChanges(workspaceLocation, hasUnsavedChanges)),
handleEnableTokenCounter: () => dispatch(enableTokenCounter(workspaceLocation)),
handleDisableTokenCounter: () => dispatch(disableTokenCounter(workspaceLocation))
};
}, [dispatch]);

Expand Down Expand Up @@ -238,6 +245,21 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
checkWorkspaceReset();
});

/**
* Handles toggling enabling and disabling token counter depending on assessment properties
*/
useEffect(() => {
if (props.assessmentConfiguration.hasTokenCounter) {
handleEnableTokenCounter();
} else {
handleDisableTokenCounter();
}
}, [
props.assessmentConfiguration.hasTokenCounter,
handleEnableTokenCounter,
handleDisableTokenCounter
]);

/**
* Handles toggling of relevant SideContentTabs when mobile breakpoint it hit
*/
Expand Down Expand Up @@ -839,7 +861,6 @@ const AssessmentWorkspace: React.FC<AssessmentWorkspaceProps> = props => {
sideBarProps: sideBarProps,
mobileSideContentProps: mobileSideContentProps(questionId)
};

return (
<div className={classNames('WorkspaceParent', Classes.DARK)}>
{overlay}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const defaultProps = assertType<AssessmentWorkspaceProps>()({
type: 'Missions',
isManuallyGraded: true,
displayInDashboard: true,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 48,
earlySubmissionXp: 200
},
Expand Down
8 changes: 8 additions & 0 deletions src/commons/mocks/AssessmentMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -30,6 +31,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -38,6 +40,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -46,6 +49,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: true,
earlySubmissionXp: 200
},
{
Expand All @@ -54,6 +58,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
}
],
Expand All @@ -64,6 +69,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -72,6 +78,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -80,6 +87,7 @@ export const mockAssessmentConfigurations: AssessmentConfiguration[][] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
}
]
Expand Down
1 change: 1 addition & 0 deletions src/commons/profile/__tests__/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const assessmentConfigurations: AssessmentConfiguration[] = [
type: c,
isManuallyGraded: false,
displayInDashboard: false,
hasTokenCounter: false,
hoursBeforeEarlyXpDecay: 0,
earlySubmissionXp: 0
}));
Expand Down
6 changes: 6 additions & 0 deletions src/commons/repl/Repl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ export const Output: React.FC<OutputProps> = (props: OutputProps) => {
</Card>
);
}
case 'notification':
return (
<Card className="notification-output-container">
<Pre className="notification-output">{'💡 ' + props.output.consoleLog}</Pre>
</Card>
);
default:
return <Card>''</Card>;
}
Expand Down
2 changes: 1 addition & 1 deletion src/commons/sagas/BackendSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,6 @@ function* BackendSaga(): SagaIterator {
getAssessmentConfigs,
tokens
);

if (assessmentConfigs) {
yield put(actions.setAssessmentConfigurations(assessmentConfigs));
}
Expand Down Expand Up @@ -982,6 +981,7 @@ function* BackendSaga(): SagaIterator {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
hasTokenCounter: false,
earlySubmissionXp: 0
}
];
Expand Down
10 changes: 9 additions & 1 deletion src/commons/sagas/WorkspaceSaga.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { tokenizer } from 'acorn';
import { FSModule } from 'browserfs/dist/node/core/FS';
import {
Context,
Expand All @@ -9,7 +10,7 @@ import {
runFilesInContext,
runInContext
} from 'js-slang';
import { TRY_AGAIN } from 'js-slang/dist/constants';
import { ACORN_PARSE_OPTIONS, TRY_AGAIN } from 'js-slang/dist/constants';
import { defineSymbol } from 'js-slang/dist/createContext';
import { InterruptedError } from 'js-slang/dist/errors/errors';
import { parse } from 'js-slang/dist/parser/parser';
Expand Down Expand Up @@ -1256,6 +1257,13 @@ export function* evalCode(

yield* dumpDisplayBuffer(workspaceLocation, isStoriesBlock, storyEnv);

// Change token count if its assessment and EVAL_EDITOR
if (actionType === EVAL_EDITOR && workspaceLocation === 'assessment') {
const tokens = [...tokenizer(entrypointCode, ACORN_PARSE_OPTIONS)];
const tokenCounter = tokens.length;
yield put(actions.setTokenCount(workspaceLocation, tokenCounter));
}

// Do not write interpreter output to REPL, if executing chunks (e.g. prepend/postpend blocks)
if (actionType !== EVAL_SILENT) {
if (!isStoriesBlock) {
Expand Down
6 changes: 6 additions & 0 deletions src/commons/sagas/__tests__/BackendSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -226,6 +227,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -234,6 +236,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
},
{
Expand All @@ -242,6 +245,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: false,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: true,
earlySubmissionXp: 200
},
{
Expand All @@ -250,6 +254,7 @@ const mockAssessmentConfigurations: AssessmentConfiguration[] = [
isManuallyGraded: true,
displayInDashboard: false,
hoursBeforeEarlyXpDecay: 48,
hasTokenCounter: false,
earlySubmissionXp: 200
}
];
Expand Down Expand Up @@ -1002,6 +1007,7 @@ describe('Test CREATE_COURSE action', () => {
isManuallyGraded: true,
displayInDashboard: true,
hoursBeforeEarlyXpDecay: 0,
hasTokenCounter: false,
earlySubmissionXp: 0
}
];
Expand Down
Loading
Loading