From cb89b11a0df33ac550871cab9a67791cfe3303c6 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Wed, 3 Jan 2024 09:34:05 -0800 Subject: [PATCH 1/4] Add pxtarget.json options for tuning time machine intervals (#9786) * Add pxtarget.json options for tuning time machine intervals * Update history.ts --- localtypings/pxtarget.d.ts | 2 ++ pxteditor/history.ts | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/localtypings/pxtarget.d.ts b/localtypings/pxtarget.d.ts index ee4495e1a508..ce1888bcde92 100644 --- a/localtypings/pxtarget.d.ts +++ b/localtypings/pxtarget.d.ts @@ -494,6 +494,8 @@ declare namespace pxt { timeMachine?: boolean; // Save/restore old versions of a project experiment blocklySoundVolume?: number; // A number between 0 and 1 that sets the volume for blockly sounds (e.g. connect, disconnect, click) timeMachineQueryParams?: string[]; // An array of query params to pass to timemachine iframe embed + timeMachineDiffInterval?: number; // An interval in milliseconds at which to take diffs to store in project history. Defaults to 5 minutes + timeMachineSnapshotInterval?: number; // An interval in milliseconds at which to take full project snapshots in project history. Defaults to 15 minutes } interface DownloadDialogTheme { diff --git a/pxteditor/history.ts b/pxteditor/history.ts index e51f2df77a73..1f1e9fd0e70b 100644 --- a/pxteditor/history.ts +++ b/pxteditor/history.ts @@ -50,11 +50,11 @@ namespace pxt.workspace { maxTime?: number; } - // 5 minutes - const DIFF_HISTORY_INTERVAL = 1000 * 60 * 5; + // 5 minutes. This is overridden in pxtarget.json + const DEFAULT_DIFF_HISTORY_INTERVAL = 1000 * 60 * 5; - // 15 minutes - const SNAPSHOT_HISTORY_INTERVAL = 1000 * 60 * 15; + // 15 minutes. This is overridden in pxtarget.json + const DEFAULT_SNAPSHOT_HISTORY_INTERVAL = 1000 * 60 * 15; const ONE_DAY = 1000 * 60 * 60 * 24; @@ -324,7 +324,7 @@ namespace pxt.workspace { const topTime = history.entries[history.entries.length - 1].timestamp; const prevTime = history.entries[history.entries.length - 2].timestamp; - if (currentTime - topTime < DIFF_HISTORY_INTERVAL && topTime - prevTime < DIFF_HISTORY_INTERVAL) { + if (currentTime - topTime < diffInterval() && topTime - prevTime < diffInterval()) { shouldCombine = true; } } @@ -352,7 +352,7 @@ namespace pxt.workspace { if (history.snapshots.length == 0) { history.snapshots.push(takeSnapshot(previousText, currentTime - 1)); } - else if (currentTime - history.snapshots[history.snapshots.length - 1].timestamp >= SNAPSHOT_HISTORY_INTERVAL) { + else if (currentTime - history.snapshots[history.snapshots.length - 1].timestamp >= snapshotInterval()) { history.snapshots.push(takeSnapshot(previousText, currentTime)); const trimmed: pxt.workspace.SnapshotEntry[] = []; @@ -441,4 +441,20 @@ namespace pxt.workspace { return true; } -} \ No newline at end of file + + function diffInterval() { + if (pxt.appTarget?.appTheme?.timeMachineDiffInterval != undefined) { + return pxt.appTarget.appTheme.timeMachineDiffInterval; + } + + return DEFAULT_DIFF_HISTORY_INTERVAL; + } + + function snapshotInterval() { + if (pxt.appTarget?.appTheme?.timeMachineSnapshotInterval != undefined) { + return pxt.appTarget.appTheme.timeMachineSnapshotInterval; + } + + return DEFAULT_SNAPSHOT_HISTORY_INTERVAL; + } +} From d836236328f94ffc26c012361123c06c1d426df2 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Wed, 3 Jan 2024 09:37:07 -0800 Subject: [PATCH 2/4] 9.3.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 80e7aee7151b..5595810206b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pxt-core", - "version": "9.3.9", + "version": "9.3.10", "description": "Microsoft MakeCode provides Blocks / JavaScript / Python tools and editors", "keywords": [ "TypeScript", From e622f92eec53c385489de446c6d171813f014632 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Wed, 3 Jan 2024 15:39:38 -0800 Subject: [PATCH 3/4] Move npm prepare commands to a script (#9809) --- package.json | 2 +- scripts/npm-prepare.sh | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 scripts/npm-prepare.sh diff --git a/package.json b/package.json index 5595810206b0..b75d4916c98c 100644 --- a/package.json +++ b/package.json @@ -166,6 +166,6 @@ "test:lang": "gulp testlang", "update": "gulp update", "watch-streamer": "cd docs/static/streamer && tsc -t es6 --watch", - "prepare": "cd skillmap && npm install && cd .. && cd authcode && npm install && cd .. && cd multiplayer && npm install && cd .. && cd kiosk && npm install && cd .. && cd teachertool && npm install && cd .." + "prepare": "bash scripts/npm-prepare.sh" } } diff --git a/scripts/npm-prepare.sh b/scripts/npm-prepare.sh new file mode 100644 index 000000000000..0c957fde1f66 --- /dev/null +++ b/scripts/npm-prepare.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +cd skillmap && npm install --no-update-notifier && cd .. +cd authcode && npm install --no-update-notifier && cd .. +cd multiplayer && npm install --no-update-notifier && cd .. +cd kiosk && npm install --no-update-notifier && cd .. +cd teachertool && npm install --no-update-notifier && cd .. From 289de62637c22893f76c568967a8c12a32e2468a Mon Sep 17 00:00:00 2001 From: Kim Ying <15070078+kimprice@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:32:41 -0800 Subject: [PATCH 4/4] Teacher Tool: initial rubric, rubricCriteria classes and parsing (#9807) * initial rubric, rubricCriteria classes and parsing * rename friendlyText -> displayText, criteriaID -> criteriaId * move runEvaluate into a transform * async await * rename file runEvaluate -> runEvaluateAsync --- pxtblocks/code-validation/rubric.ts | 30 ++++++++++ pxtblocks/code-validation/rubricCriteria.ts | 56 +++++++++++++++++++ teachertool/public/index.html | 2 + teachertool/src/components/DebugInput.tsx | 20 ++----- .../src/transforms/runEvaluateAsync.ts | 17 ++++++ 5 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 pxtblocks/code-validation/rubric.ts create mode 100644 pxtblocks/code-validation/rubricCriteria.ts create mode 100644 teachertool/src/transforms/runEvaluateAsync.ts diff --git a/pxtblocks/code-validation/rubric.ts b/pxtblocks/code-validation/rubric.ts new file mode 100644 index 000000000000..0d7f6d10acb5 --- /dev/null +++ b/pxtblocks/code-validation/rubric.ts @@ -0,0 +1,30 @@ +namespace pxt.blocks { + export class Rubric { + criteria: RubricCriteria[]; + + constructor(criteria: RubricCriteria[]) { + this.criteria = criteria; + } + } + + export function parseRubric(rubric: string): Rubric { + let rubricObj; + try { + rubricObj = JSON.parse(rubric); + } catch (e) { + console.error(`Error parsing rubric! ${e}`); + return null; + } + + if (!rubricObj.criteria) { + console.error(`No criteria found in rubric`); + return null; + } + + const criteria: RubricCriteria[] = rubricObj.criteria.map((c: CriteriaData) => { + return getCriteria(c); + }).filter((r: RubricCriteria) => !!r); + + return new Rubric(criteria); + } +} \ No newline at end of file diff --git a/pxtblocks/code-validation/rubricCriteria.ts b/pxtblocks/code-validation/rubricCriteria.ts new file mode 100644 index 000000000000..7459794b7017 --- /dev/null +++ b/pxtblocks/code-validation/rubricCriteria.ts @@ -0,0 +1,56 @@ +namespace pxt.blocks { + interface BlockSet { + blocks: string[]; + count: number; + } + + export interface CriteriaData { + criteriaId: string; + displayText: string; + blockRequirements?: BlockSet[]; + count?: number; + } + + export function getCriteria(data: CriteriaData): RubricCriteria { + switch (data.criteriaId) { + case "blockCheck": + return new BlockCheckCriteria(data.displayText, data.blockRequirements); + case "comment": + return new CommentCriteria(data.displayText, data.count); + default: + console.error(`Unrecognized criteriaId: ${data.criteriaId}`); + return null; + } + } + + export abstract class RubricCriteria { + displayText: string; + abstract criteriaId: string; + + constructor(displayText: string) { + this.displayText = displayText; + } + } + + + class BlockCheckCriteria extends RubricCriteria { + criteriaId: "blockCheck"; + blockRequirements: BlockSet[]; + + constructor(displayText: string, blockRequirements: BlockSet[]) { + super(displayText); + this.blockRequirements = blockRequirements; + } + } + + class CommentCriteria extends RubricCriteria { + criteriaId: "comment"; + count: number; + + constructor(displayText: string, count: number) { + super(displayText); + this.count = count; + } + } + +} \ No newline at end of file diff --git a/teachertool/public/index.html b/teachertool/public/index.html index f314e8e09ff8..de8c743e75d2 100644 --- a/teachertool/public/index.html +++ b/teachertool/public/index.html @@ -34,6 +34,8 @@ + +
diff --git a/teachertool/src/components/DebugInput.tsx b/teachertool/src/components/DebugInput.tsx index 75c5862165ea..bc429f0f38ee 100644 --- a/teachertool/src/components/DebugInput.tsx +++ b/teachertool/src/components/DebugInput.tsx @@ -1,8 +1,10 @@ +/// + import { useState } from "react"; import { Button } from "react-common/components/controls/Button"; import { Input } from "react-common/components/controls/Input"; import { Textarea } from "react-common/components/controls/Textarea"; -import { getProjectMetaAsync, getProjectTextAsync } from "../services/BackendRequests"; +import { runEvaluateAsync } from "../transforms/runEvaluateAsync"; interface IProps {} @@ -10,18 +12,8 @@ const DebugInput: React.FC = ({}) => { const [shareLink, setShareLink] = useState("https://arcade.makecode.com/S50644-45891-08403-36583"); const [rubric, setRubric] = useState(""); - const runEvaluate = async () => { - console.log(`Evaluate ${shareLink} with ${rubric}!`); - const scriptId = pxt.Cloud.parseScriptId(shareLink); - if (!scriptId) { - console.log("Invalid share link!"); - return; - } - const projText = await getProjectTextAsync(scriptId); - if (projText) console.log(projText["main.blocks"] || "Failed to get blocks xml!"); - - const projMeta = await getProjectMetaAsync(scriptId); - if (projMeta) console.log(projMeta); + const evaluate = async () => { + await runEvaluateAsync(shareLink, rubric); } return ( @@ -43,7 +35,7 @@ const DebugInput: React.FC = ({}) => { rows={20} onChange={setRubric} /> -