diff --git a/src/editor/commands/index.ts b/src/editor/commands/index.ts index 226785ae..6cd66a59 100644 --- a/src/editor/commands/index.ts +++ b/src/editor/commands/index.ts @@ -73,7 +73,7 @@ export const createCommands = ({ context, machine, storage, git, position }: Cre console.log('save document', document) if (languageIds.includes(document.languageId) && document.uri.scheme === 'file') { // do work - vscode.commands.executeCommand('coderoad.run_test') + machine.send('TEST_RUN') } }) }, @@ -104,6 +104,9 @@ export const createCommands = ({ context, machine, storage, git, position }: Cre machine.send(action) }, [COMMANDS.RUN_TEST]: () => { - runTest() + runTest({ + onSuccess: () => machine.send('TEST_PASS'), + onFail: () => machine.send('TEST_FAIL') + }) } }) \ No newline at end of file diff --git a/src/editor/commands/runTest.ts b/src/editor/commands/runTest.ts index 5a1a8b5e..1d592bd0 100644 --- a/src/editor/commands/runTest.ts +++ b/src/editor/commands/runTest.ts @@ -1,7 +1,6 @@ import * as vscode from 'vscode' import { exec } from '../../services/node' import * as storage from '../../services/storage' -import * as testResult from '../../services/testResult' // ensure only latest run_test action is taken let currentId = 0 @@ -21,7 +20,12 @@ const getOutputChannel = (name: string): vscode.OutputChannel => { return _channel } -export default async function runTest(): Promise { +interface Props { + onSuccess(): void, + onFail(): void +} + +export default async function runTest({ onSuccess, onFail }: Props): Promise { // increment process id let processId = ++currentId @@ -73,8 +77,8 @@ export default async function runTest(): Promise { // exit early return } - // @ts-ignore - testResult.onSuccess(position) + console.log('call onSuccess') + onSuccess() } else { console.log('NOT SUCCESS?') } @@ -118,7 +122,8 @@ export default async function runTest(): Promise { return } console.log('ERROR', firstError.message) - testResult.onFailure() + console.log('call onFail') + onFail() } else { console.error('NOTE: PARSER DID NOT WORK FOR ', line) } diff --git a/src/services/storage.ts b/src/services/storage.ts index 397833bf..3fa378df 100644 --- a/src/services/storage.ts +++ b/src/services/storage.ts @@ -52,7 +52,7 @@ interface ProgressUpdate { } } -export async function updateProgress(record: ProgressUpdate): Promise { +export async function setProgress(record: ProgressUpdate): Promise { const progress = await getProgress() if (record.levels) { progress.levels = { diff --git a/src/services/testResult.ts b/src/services/testResult.ts index 056646d1..470fe50e 100644 --- a/src/services/testResult.ts +++ b/src/services/testResult.ts @@ -1,53 +1,53 @@ -import * as CR from 'typings' -import * as vscode from 'vscode' -import * as storage from './storage' - -export async function onSuccess(position: CR.Position) { - console.log('onSuccess', position) - vscode.window.showInformationMessage('SUCCESS') - - // calculate progress changes - const [progress, tutorial] = await Promise.all([storage.getProgress(), storage.getTutorial()]) - - if (!tutorial) { - throw new Error('No tutorial found') - } - - if (!position.stepId) { - throw new Error('No step position found') - } - - const { data } = tutorial - - // step complete - const nextProgress = progress - nextProgress.steps[position.stepId] = true - - // is stage complete - const steps = data.stages[position.stageId].stepList - const isStageComplete = progress.stages[position.stageId] || steps[steps.length - 1] === position.stepId - nextProgress.stages[position.stageId] = isStageComplete - - // is level complete - if (isStageComplete) { - const stages = data.levels[position.levelId].stageList - const isLevelComplete = progress.levels[position.levelId] || stages[stages.length - 1] === position.stageId - nextProgress.levels[position.levelId] = isLevelComplete - - if (isLevelComplete) { - const levels = data.summary.levelList - const isTutorialComplete = progress.complete || levels[levels.length - 1] === position.levelId - nextProgress.complete = isTutorialComplete - } - } - console.log('nextProgress', nextProgress) - - // update ls progress - storage.updateProgress(nextProgress) - // send({ type: 'STEP_COMPLETE', payload: { progress: nextProgress } }) -} - -export async function onFailure() { - // TODO: capture analytics on stepId - vscode.window.showWarningMessage('FAIL') -} +// import * as CR from 'typings' +// import * as vscode from 'vscode' +// import * as storage from './storage' + +// export async function onSuccess(position: CR.Position) { +// console.log('onSuccess', position) +// vscode.window.showInformationMessage('SUCCESS') + +// // calculate progress changes +// const [progress, tutorial] = await Promise.all([storage.getProgress(), storage.getTutorial()]) + +// if (!tutorial) { +// throw new Error('No tutorial found') +// } + +// if (!position.stepId) { +// throw new Error('No step position found') +// } + +// const { data } = tutorial + +// // step complete +// const nextProgress = progress +// nextProgress.steps[position.stepId] = true + +// // is stage complete +// const steps = data.stages[position.stageId].stepList +// const isStageComplete = progress.stages[position.stageId] || steps[steps.length - 1] === position.stepId +// nextProgress.stages[position.stageId] = isStageComplete + +// // is level complete +// if (isStageComplete) { +// const stages = data.levels[position.levelId].stageList +// const isLevelComplete = progress.levels[position.levelId] || stages[stages.length - 1] === position.stageId +// nextProgress.levels[position.levelId] = isLevelComplete + +// if (isLevelComplete) { +// const levels = data.summary.levelList +// const isTutorialComplete = progress.complete || levels[levels.length - 1] === position.levelId +// nextProgress.complete = isTutorialComplete +// } +// } +// console.log('nextProgress', nextProgress) + +// // update ls progress +// storage.updateProgress(nextProgress) +// // send({ type: 'STEP_COMPLETE', payload: { progress: nextProgress } }) +// } + +// export async function onFailure() { +// // TODO: capture analytics on stepId +// vscode.window.showWarningMessage('FAIL') +// } diff --git a/src/state/actions/index.ts b/src/state/actions/index.ts index 7cd47503..05e1e09c 100644 --- a/src/state/actions/index.ts +++ b/src/state/actions/index.ts @@ -84,5 +84,71 @@ export default { }), tutorialLoadNext() { machine.send('LOAD_NEXT') + }, + testStart() { + vscode.commands.executeCommand('coderoad.run_test') + }, + testPass() { + vscode.window.showInformationMessage('PASS') + }, + testFail() { + vscode.window.showWarningMessage('FAIL') + }, + // @ts-ignore + stepComplete: assign({ + progress: (context: CR.MachineContext): CR.Progress => { + const nextProgress = { + ...context.progress, + steps: { + ...context.progress.steps, + [context.position.stepId]: true, + } + } + storage.setProgress(nextProgress) + return nextProgress + } + }), + // @ts-ignore + stageComplete: assign({ + progress: (context: CR.MachineContext): CR.Progress => { + const nextProgress = { + ...context.progress, + stages: { + ...context.progress.stages, + [context.position.stageId]: true, + } + } + storage.setProgress(nextProgress) + return nextProgress + } + }), + // @ts-ignore + levelComplete: assign({ + progress: (context: CR.MachineContext): CR.Progress => { + const nextProgress = { + ...context.progress, + levels: { + ...context.progress.levels, + [context.position.levelId]: true, + } + } + storage.setProgress(nextProgress) + return nextProgress + + } + }), + // @ts-ignore + tutorialComplete: assign({ + progress: (context: CR.MachineContext): CR.Progress => { + const nextProgress = { + ...context.progress, + complete: true, + } + storage.setProgress(nextProgress) + return nextProgress + } + }), + stepLoadNext() { + console.log("LOAD NEXT STEP") } } \ No newline at end of file diff --git a/src/state/guards/index.ts b/src/state/guards/index.ts index 563fac43..c270d0db 100644 --- a/src/state/guards/index.ts +++ b/src/state/guards/index.ts @@ -6,4 +6,29 @@ export default { console.log('GUARD: hasNoNextLevelProgress') return false }, + tasksComplete: (context: CR.MachineContext): boolean => { + console.log('GUARD: tasksComplete') + return false + }, + hasNextStep: (context: CR.MachineContext): boolean => { + console.log('GUARD: hasNextStep') + const { data, position, progress } = context + const steps = data.stages[position.stageId].stepList + const isStageComplete = progress.stages[position.stageId] || steps[steps.length - 1] === position.stepId + return !isStageComplete + }, + hasNextStage: (context: CR.MachineContext): boolean => { + console.log('GUARD: hasNextStage') + const { data, position, progress } = context + const stages = data.levels[position.levelId].stageList + const isLevelComplete = progress.levels[position.levelId] || stages[stages.length - 1] === position.stageId + return !isLevelComplete + }, + hasNextLevel: (context: CR.MachineContext): boolean => { + console.log('GUARD: hasNextLevel') + const { data, position, progress } = context + const levels = data.summary.levelList + const isTutorialComplete = progress.complete || levels[levels.length - 1] === position.levelId + return !isTutorialComplete + }, } diff --git a/src/state/machine.ts b/src/state/machine.ts index 44f51fce..46ba8b6f 100644 --- a/src/state/machine.ts +++ b/src/state/machine.ts @@ -21,7 +21,7 @@ export const machine = Machine< states: { Initial: { after: { - 1000: 'Startup' + 2000: 'Startup' } }, Startup: { @@ -50,7 +50,7 @@ export const machine = Machine< ContinueTutorial: { onEntry: ['tutorialContinue'], on: { - TUTORIAL_START: '#tutorial-load-next' + TUTORIAL_START: '#tutorial-load-next-stage' } }, } @@ -60,8 +60,8 @@ export const machine = Machine< initial: 'Summary', onEntry: ['tutorialSetup'], states: { - LoadNext: { - id: 'tutorial-load-next', + LoadNextStage: { + id: 'tutorial-load-next-stage', onEntry: ['tutorialLoadNext'], on: { LOAD_NEXT: [ @@ -101,8 +101,9 @@ export const machine = Machine< }, }, TestRunning: { + onEntry: ['testStart'], on: { - TEST_SUCCESS: [ + TEST_PASS: [ { target: 'StageComplete', cond: 'tasksComplete', @@ -111,29 +112,35 @@ export const machine = Machine< target: 'TestPass', }, ], - TEST_FAILURE: 'TestFail', + TEST_FAIL: 'TestFail', }, }, TestPass: { - onEntry: ['stepComplete'], + onEntry: ['testPass', 'stepComplete'], + after: { + 0: { + target: 'StepNext', + cond: 'hasNextStep', + } + }, on: { - NEXT: [ - { - target: 'StageNormal', - cond: 'hasNextStep', - }, - { - target: 'StageComplete', - }, - ], + NEXT: 'StageComplete', }, }, TestFail: { - on: { - RETURN: 'StageNormal', + onEntry: ['testFail'], + after: { + 0: 'StageNormal' }, }, + StepNext: { + onEntry: ['stepLoadNext'], + after: { + 0: 'StageNormal' + } + }, StageComplete: { + onEntry: 'stageComplete', on: { NEXT: [ { diff --git a/typings/index.d.ts b/typings/index.d.ts index f5771d1a..8606044d 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -146,7 +146,7 @@ export interface MachineStateSchema { } Tutorial: { states: { - LoadNext: {} + LoadNextStage: {} Summary: {} Level: {} Stage: { @@ -155,6 +155,7 @@ export interface MachineStateSchema { TestRunning: {} TestPass: {} TestFail: {} + StepNext: {} StageComplete: {} } }