From 9f4cc04b98175b7658b9237051b94e9de2cfb45c Mon Sep 17 00:00:00 2001 From: Grace Date: Mon, 14 Oct 2024 16:50:42 +0100 Subject: [PATCH 01/23] WIP locally working open in createAI flow --- lang/ui.en.json | 4 ++ src/deployment/default/index.tsx | 2 + src/deployment/index.ts | 1 + src/messages/ui.en.json | 6 +++ src/model.ts | 25 +++++++++ src/pages/HomePage.tsx | 88 ++++++++++++++++++++++++++++++-- src/store.ts | 54 ++++++++++++++++++++ 7 files changed, 176 insertions(+), 4 deletions(-) diff --git a/lang/ui.en.json b/lang/ui.en.json index 4a18add40..29a7ef4cc 100644 --- a/lang/ui.en.json +++ b/lang/ui.en.json @@ -71,6 +71,10 @@ "defaultMessage": "Close", "description": "Close button text or label" }, + "code-download-error": { + "defaultMessage": "Error downloading the target code", + "description": "Title for error message relating to project loading" + }, "coming-soon": { "defaultMessage": "Coming soon", "description": "Placeholder text for future projects" diff --git a/src/deployment/default/index.tsx b/src/deployment/default/index.tsx index ee2bf89d4..d2a6ec046 100644 --- a/src/deployment/default/index.tsx +++ b/src/deployment/default/index.tsx @@ -52,6 +52,8 @@ const defaultDeploymentFactory: DeploymentConfigFactory = () => ({ troubleshooting: "https://support.microbit.org", wearable: "https://support.microbit.org", }, + // TODO: To move to theme + activitiesBaseUrl: "http://localhost:9000/classroom/activities/", }); export default defaultDeploymentFactory; diff --git a/src/deployment/index.ts b/src/deployment/index.ts index ecbf7ddc7..0356d3ebd 100644 --- a/src/deployment/index.ts +++ b/src/deployment/index.ts @@ -56,6 +56,7 @@ export interface DeploymentConfig { termsOfUseLink?: string; privacyPolicyLink?: string; + activitiesBaseUrl?: string; logging: Logging; } diff --git a/src/messages/ui.en.json b/src/messages/ui.en.json index 9f1cb7c56..b3d340ecb 100644 --- a/src/messages/ui.en.json +++ b/src/messages/ui.en.json @@ -149,6 +149,12 @@ "value": "Close" } ], + "code-download-error": [ + { + "type": 0, + "value": "Error downloading the target code" + } + ], "coming-soon": [ { "type": 0, diff --git a/src/model.ts b/src/model.ts index be19a8822..b56f1c61d 100644 --- a/src/model.ts +++ b/src/model.ts @@ -171,3 +171,28 @@ export enum TourId { CollectDataToTrainModel = "collectDataToTrainModel", TestModelPage = "testModelPage", } + +/** + * Information passed omn the URL from microbit.org. + * We call back into microbit.org to grab a JSON file with + * full details. + */ +export type MicrobitOrgResource = { + /** + * ID that can be used when fetching the code from microbit.org. + */ + id: string; + + /** + * Name of the microbit.org project or lesson. + * + * We use this to load the target code. + */ + project: string; + + /** + * Name of the actual code snippet. + * Due to a data issue this can often be the same as the project name. + */ + name: string; +}; diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 23a2aed75..42908d8dd 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -10,8 +10,8 @@ import { useInterval, VStack, } from "@chakra-ui/react"; -import { ReactNode, useCallback, useState } from "react"; -import { FormattedMessage, useIntl } from "react-intl"; +import { ReactNode, useCallback, useEffect, useState } from "react"; +import { FormattedMessage, IntlShape, useIntl } from "react-intl"; import { useNavigate } from "react-router"; import DefaultPageLayout from "../components/DefaultPageLayout"; import PercentageDisplay from "../components/PercentageDisplay"; @@ -24,8 +24,13 @@ import { useDeployment } from "../deployment"; import blockImage from "../images/block.png"; import xyzGraph from "../images/xyz-graph.png"; import clap from "../images/clap-square.png"; -import { createNewPageUrl } from "../urls"; +import { createNewPageUrl, createSessionPageUrl } from "../urls"; import { flags } from "../flags"; +import { useSearchParams } from "react-router-dom"; +import { MicrobitOrgResource } from "../model"; +import { Project } from "@microbit/makecode-embed/react"; +import { useStore } from "../store"; +import { SessionPageId } from "../pages-config"; const graphData = { x: [ @@ -63,13 +68,88 @@ const graphData = { ], }; +const useMicrobitResourceSearchParams = (): MicrobitOrgResource | undefined => { + const [params] = useSearchParams(); + const id = params.get("id"); + const project = params.get("project"); + const name = params.get("name"); + + const resource: MicrobitOrgResource | undefined = + id && name && project + ? { + id, + project, + name, + } + : undefined; + return resource; +}; + +const isValidEditorContent = (content: Project): content is Project => { + return ( + content && + typeof content === "object" && + "text" in content && + !!content.text + ); +}; + +const fetchMicrobitOrgResourceTargetCode = async ( + activitiesBaseUrl: string, + resource: MicrobitOrgResource, + intl: IntlShape +): Promise => { + const url = `${activitiesBaseUrl}${resource.id}-makecode.json`; + let json; + try { + const response = await fetch(url); + json = (await response.json()) as object; + } catch (e) { + const rethrow = new Error( + intl.formatMessage({ id: "code-download-error" }) + ); + rethrow.stack = e instanceof Error ? e.stack : undefined; + throw rethrow; + } + if ( + !("editorContent" in json) || + typeof json.editorContent !== "object" || + !json.editorContent || + !isValidEditorContent(json.editorContent) + ) { + throw new Error(intl.formatMessage({ id: "code-format-error" })); + } + return json.editorContent; +}; + const HomePage = () => { const navigate = useNavigate(); const handleGetStarted = useCallback(() => { navigate(createNewPageUrl()); }, [navigate]); const intl = useIntl(); - const { appNameFull } = useDeployment(); + const { appNameFull, activitiesBaseUrl } = useDeployment(); + const resource = useMicrobitResourceSearchParams(); + const loadProject = useStore((s) => s.loadProject); + console.log("resource", resource); + + useEffect(() => { + const updateAsync = async () => { + if (!resource || !activitiesBaseUrl) { + return; + } + const code = await fetchMicrobitOrgResourceTargetCode( + activitiesBaseUrl, + resource, + intl + ); + console.log("code", code); + loadProject(code); + navigate(createSessionPageUrl(SessionPageId.DataSamples)); + }; + void updateAsync(); + }, [activitiesBaseUrl, intl, loadProject, navigate, resource]); + return ( ()( }); }, + loadProject(project: Project) { + set(({ projectEdited, gestures: prevGestures }) => { + const newGestures = getGesturesFromProject(project, prevGestures); + return { + gestures: newGestures, + model: undefined, + ...updateProject(project, projectEdited, newGestures, undefined), + }; + }); + }, + closeTrainModelDialogs() { set({ trainModelDialogStage: TrainModelDialogStage.Closed, @@ -762,3 +774,45 @@ const gestureIcon = ({ } return useableIcons[0]; }; + +const getGesturesFromProject = ( + project: Project, + prevGestures: GestureData[] +): GestureData[] => { + const { text } = project; + if (text === undefined || !("dataset.json" in text)) { + return prevGestures; + } + const dataset = JSON.parse(text["dataset.json"]) as object; + if (typeof dataset !== "object" || !("data" in dataset)) { + return prevGestures; + } + return dataset.data as GestureData[]; + // { + // "header": { + // "target": "microbit", + // "targetVersion": "7.0.42", + // "editor": "blocksprj", + // "name": "Simple AI exercise timer", + // "meta": {}, + // "pubId": "", + // "pubCurrent": false, + // "id": "f102d806-f767-45c6-3af3-35b3be9dbdcd", + // "recentUse": 1728049865, + // "modificationTime": 1728049865, + // "path": "Simple-AI-exercise-timer", + // "cloudCurrent": false, + // "saveId": null, + // "githubCurrent": false + // }, + // "text": { + // "README.md": "", + // "autogenerated.ts": "// Auto-generated. Do not edit.\nnamespace ml {\n export namespace event {\n //% fixedInstance block=\"Exercising\"\n export const Exercising = new MlEvent(2, \"Exercising\");\n //% fixedInstance block=\"Not exercising\"\n export const NotExercising = new MlEvent(3, \"Not exercising\");\n\n }\n \n events = [event.Unknown,event.Exercising,event.NotExercising];\n \n control.onEvent(MlRunnerIds.MlRunnerInference, 1, () => {\n if (!event.Unknown.onStartHandler) {\n maybeUpdateEventStats(event.Unknown);\n }\n });\n control.onEvent(MlRunnerIds.MlRunnerInference, 2, () => {\n if (!event.Exercising.onStartHandler) {\n maybeUpdateEventStats(event.Exercising);\n }\n });\n control.onEvent(MlRunnerIds.MlRunnerInference, 3, () => {\n if (!event.NotExercising.onStartHandler) {\n maybeUpdateEventStats(event.NotExercising);\n }\n });\n\n getModelBlob = (): Buffer => {\n const result = hex`4C444F4D38001900500003000000000000000002CDCC4C3F0B45786572636973696E6700CDCC4C3F0F4E6F742065786572636973696E6700620F47304D4C3446500000002C0D0000A40500000000000000000000A80000000800000001000000080000000100000000000000000000000000000000000000180000000000000002000000000000002DE9F05F0F460169091839600021796038680346B3EC1E1A07F2080292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A92EC010A20EE0A0A30EE2A0AA2EC010A92EC010A20EE0B0A30EE2B0AA2EC010A92EC010A20EE0C0A30EE2C0AA2EC010A92EC010A20EE0D0A30EE2D0AA2EC010A92EC010A20EE0E0A30EE2E0AA2EC010A92EC010A20EE0F0A30EE2F0AA2EC010A02F22402B3EC121A07F2440292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A02F23C02386800F2C00307F268021024B3EC010A07F20801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC0A0AF3EC0A7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A30EE050AA2EC010A013C8FD107F2680210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C2386800F2007307F208020224B3EC010A07F26801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC020AF3EC027A60EEA70A21EE081A30EE200A30EE010AA2EC010A013CAFD107F208021046022100F002F8BDE8F09F012938B5D0ED002A29D9031D00EB8102F3EC017AF4EE627AF1EE10FAC8BFF0EE672A9A42F4D1002402EE104A054695ED000A30EE620A00F015F80134A14232EE002AA5EC010AF2D8002390ED007AC7EE027A01339942E0EC017AF6D838BD0029E1D138BDDFED297AB4EEE70AF1EE10FA48D4DFED277AB4EEE70AF1EE10FA3ADCDFED247ADFED244A9FED243ADFED243A9FED245A9FED244ADFED245A9FED246ADFED246A60EE277AB7EE007A77EEA47A77EEE47AA7EE830AFDEEE74AA7EEA30AF0EE457AE4EE007A14EE903AE7EE805AA5EE806AE6EE006AF0EE667AF0EE476AE7EE806AA6EE807A17EE102A02EBC35300EE103A7047DFED107AB7EE007A87EE270A70479FED0C0A704700000000AAC20000AE423BAAB83F0000404B007231BF8EBEBFB56E2F093C00A0B43AADAD2A3D28AA2A3EFBFFFF3E0000000059D0953F799026BD2B527B3F93FA7DBECD01913F2730F7BE80DEAE3FB32EDC3E7829A33FB4147A3EFB59A93F5EC956BEBE2B863F6135183F9FF8833F0CB5253F84D6903F9567DA3E6C5CD83FE25994BEAFB6B23FFCBCB7BE45C5AF3F5613BABE20C41F3FF7BD2FBF4E9F023F322A36BF6C53263FBC4959BF39A3EB3C7B329CBFC1E4393D4826DEBF3547223D68007BBF31AFC63FBA16C6BBF4CAC83F6CEDB0BCADFAB83F21358BBDD8E8B23F142A17BF15D1AD3F4F6D31BF8947AB3F87CFD2BE973C4BBC6780D5BD8F1A80BE41A5B0BDE8EFE43DC20F303E8E232BBCFFF501BD0068F4BB4496293D8BB6683E26351D3EA94792BE3FC12EBD42622DBEA1BF40BE7233D6BEC03DF8BDA5779CBD25EB643EB1289D3D05429D3DA4F0C5BE0A83923EF21CA53C22E35A3D8477C0BE68365BBEEA5419BEF32C2FBC56B15F3EB9C991BE33DFB4BEA0220D3EEECF87BEBEEDD6BED46DABBE9F0686BE1DA4F83CF598973C9AF70BBFBB1785BE43AA43BC2E3CA4BE84068A3E29DB37BE34A20C3E37D702BED7F704BE27040E3E34AC90B9AA24BB3DD51308BE6477993D18CB03BE0506C0BEA83CB23EFDDF6CBE0E32243EB8E3D53D78FFD7BDD518B13EF43858BCCF02243E50F610BE4388FCBC5539D03D9B23B5BD3AF8103EC53B843E81B6A43EAEE7ADBE9C0636BE992A85BEC342633EB7318CBD2BB9873E658A66BDD23CB1BE4EFA36BEC0D19EBEB5884D3EBAC9CEBD0CEC83BEBFB2BDBD5A9C56BC1176B2BE7C8EFEBD06EC853EC37F15BE3B991EBE17A814BD79A041BE8BB93C3DD76E53BEEA724E3E884D4F3EBC417BBEDA9A863CF0F455BE7E80C93CCFB8A5BEF7D18A3DC1FA543EEFA34D3E75DDCC3D7D55B73D6073543D0531F0BD3B2E803EE467113DD2F5C53EFDE8A7BD05ACEA3A902CAB3EBFC47A3E7412E03EC852EA3E9D9EF43D131B8D3D5A01A33DC4F7F3BD74A234BEC42D223EFAAEC9BEDA87AA3CE621E53DE31DFB3D2B9F38BE5C433F3E398A8A3E799C8BBE41A084BD5801EBBE137AF9BE9CC6E9BD642991BEC4B9433EEED8A23C802CD3BD4110A23E6F60A43DCC1D0B3E957412BD2AB9953E9FD6A43EEA9974BC55735E3C08C449BE708FED3D99CE5F3DE623B53EDC098CBEDF5BCB3D67F317BEC25A113DB80498BE996E45BD4A6AC7BD3862313E9B628C3E9D72A73E54FA133EA9D7E5BD6CB60C3F0B573B3E119C9EBEEEB0ECBDBFDF0ABD8E18533D49E12DBC1326A53CE0A6C03E742CBABE9FFC92BDA99A9D3DF4EC39BDEDF04A3ECD301ABE314151BE1F0ADCBC95B119BEB9B08EBEECD888BE3A76DEBD4C5D3F3D53F954BE96EAAA3D0D96AB3C4BBB633E0B2BAC3D9800C73D7F9D123D5E13853EB96CCABDAFAB0FBEB68639BE4D1D243E1775BEBD7C39873E3C5E4D3C953E53BE97996ABE719CA0BE3B3FAE3E8874873EAAEFF4BA59B59E3C09473B3C1FC82DBDB2476ABEA6636EBE07F675BEFAC74B3ED2948EBD469156BD2E9F7CBEB42D8B3DDE110FBE5A0F3ABE848580BE6DC6613D364796BDF03B5EBEF29B52BE5A97B93D513B2ABD4996073E7F4F57BEAEB7773E2527AEBD2691123E490AF2BBA593C43D50EB6A3D8269DBBE26E290BE6BB64BBEEE2F92BE4C9A08BD499FAFBE1EE773BE5B9C7B3E5A0968BEBDD4FBBDFACE9ABDCE0822BEAE10473DC49400BE78A3833C9BD6CA3CAC86AABD9B6E9C3ECB8B103EED21BEBEFB0D323DD37300BE156851BCCB6DBC3E34A7DA3D5FC2B53E2FEE48BEA192E4BB19FA20BD1E91C8BD8CA151BE0800D5BE4C667DBDA32CBFBB1EEF793EAD567E3E76BCBC3D7511933EF1B2883E754E223EFE74593C049DFB3CFA97123D61FC8A3ECA815C3E8A42383EA9528A3D2EC4A9BE868E78BB18CFF6BD52E1493DCAF0653DEF5C45BEC51B123D6CAA81BECDD53BBD7C08ED3D8114C03EB8A66BBD7B60993E631C673DF53F0E3DB59DC03C4C4021BE34BB4F3ECFB810BDED7A5ABEF9B40F3D70F9E3BEDF24023D0B83533D1DA8553D7A048CBE1E75C43CEBF4C03DE6C991BE712D3CBE517E3E3E92B4303D63BACC3DD39D553D7614173E30C8843ECA75373D140A193DB1CF863E9F74CE3DCB09973DC04FBB3E299D173E86F5793DAAE9533D0903EC3D3E896DBD61C387BE196ACBBEAB19B43E355C5ABE69774F3D751239BEF7939B3AF9006E3E8E7E3ABDB53CD63D50A500BEE566503EDBE856BEB2181FBDE7D65F3E8548D73E9B13BE3E4966373E731B123E6E79593E524B1D3E817E333D5DF460BEDC2866BC7CE467BEC07094BCEC1FACBE0B8831BE4D4BBDBB702E0F3ED2F49C3D3F8D82BE690FFF3D04AC22BC00D1F8BC3FE270BD6897ACBEBFC419BEE408A03D2CF3DFBCF730443D124B66BE455C5CBEC7A289BD2836EC3CF5A7363D22B9583ED6B0D1BD66ECF73D3A57253D6C9211BFD88874BECC6A85BE6DCE07BF7079E4BD1AD1C4BB7C6CFE3E59653E3E8F7FA9BEF973AB3DF728023D00AE253E153A8E3D18EDA33E99DFEEBEC97051BEEA32433E29B71F3EBC51C03EEDD8703EBFAEB3BE9EF7EE3D9E72FCBE5CB6B9BEDB567D3EA24C4E3CB34F893E41F52C3E9FEF053F194FD6BD482EDBBDB721C2BEA8C568BECA3E41BEA61E04BEDBFD8B3E7403F9BE3E952C3F9EF7EEBD721B8DBE8192D93E16E0A53D59A37A3EDBB7A8BDF99484BE197950BE13CC13BFB57C0A3FD476173F92FEEABE7848F5BE1195B7BD2AA7F5BEAF53383ECE043EBF00000000`;\n return result;\n };\n\n simulatorSendData();\n}\n\n// Auto-generated. Do not edit. Really.\n", + // "dataset.json": "{\n \"data\": [\n {\n \"icon\": \"StickFigure\",\n \"ID\": 1727272450006,\n \"name\": \"Exercising\",\n \"recordings\": [\n {\n \"ID\": 1727272665334,\n \"data\": {\n \"x\": [\n -1.064,\n -0.952,\n -0.776,\n -0.692,\n -0.984,\n -1.172,\n -1.18,\n -1.396,\n -1.876,\n -1.86,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.964,\n -1.664,\n -1.4,\n -1.096,\n -0.868,\n -0.716,\n -0.688,\n -0.692,\n -0.704,\n -0.716,\n -0.72,\n -0.772,\n -0.884,\n -0.944,\n -0.836,\n -0.74,\n -0.716,\n -0.8,\n -1.008,\n -0.976,\n -0.86,\n -0.932,\n -0.992,\n -1.024,\n -0.984,\n -1.292,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.896,\n -1.564,\n -1.232,\n -0.964,\n -0.836,\n -0.764,\n -0.768,\n -0.812,\n -0.892,\n -1.024,\n -1.132,\n -1.22,\n -1.248,\n -1.328,\n -1.236,\n -1.16,\n -0.96,\n -0.852,\n -0.856,\n -1.064,\n -1.236,\n -1.34,\n -1.676,\n -2.04,\n -2.04,\n -2.04\n ],\n \"y\": [\n 0.528,\n 0.392,\n 0.312,\n 0.32,\n 0.112,\n -0.292,\n -0.472,\n -0.668,\n -1.148,\n -1.38,\n -1.604,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.86,\n -1.912,\n -1.788,\n -1.732,\n -1.768,\n -1.88,\n -1.552,\n -1.196,\n -0.748,\n -0.296,\n -0.228,\n -0.208,\n -0.116,\n -0.036,\n 0.048,\n 0.148,\n 0.244,\n 0.288,\n 0.272,\n 0.236,\n 0.228,\n 0.232,\n 0.24,\n 0.312,\n 0.444,\n 0.512,\n 0.512,\n 0.512,\n 0.316,\n -0.052,\n -0.108,\n 0.056,\n -0.484,\n -1.408,\n -2.032,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.936,\n -2.04,\n -1.864,\n -1.52,\n -1.148,\n -0.72,\n -0.472,\n -0.336,\n -0.328,\n -0.26,\n -0.132,\n 0.064,\n 0.272,\n 0.608,\n 0.824,\n 0.548,\n 0.424,\n 0.584,\n 0.672,\n 0.552,\n 0.172,\n -0.028,\n -0.084,\n -0.128,\n -0.14,\n -0.284,\n -0.468,\n -0.68,\n -1.072\n ],\n \"z\": [\n 0.436,\n 0.308,\n 0.184,\n 0.228,\n 0.392,\n 0.26,\n 0.072,\n -0.328,\n -0.152,\n -0.232,\n -0.164,\n -0.02,\n -0.172,\n -0.648,\n -0.728,\n -0.7,\n -0.308,\n -0.016,\n 0.176,\n 0.328,\n 0.672,\n 0.92,\n 1.192,\n 1.384,\n 1.456,\n 1.348,\n 1.196,\n 1.064,\n 0.9,\n 0.812,\n 0.748,\n 0.716,\n 0.704,\n 0.672,\n 0.628,\n 0.544,\n 0.48,\n 0.448,\n 0.424,\n 0.404,\n 0.352,\n 0.336,\n 0.276,\n 0.304,\n 0.316,\n 0.168,\n -0.112,\n -0.156,\n 0.044,\n -0.132,\n -0.284,\n -0.58,\n -0.192,\n -0.272,\n -0.844,\n -0.896,\n -0.588,\n -0.064,\n 0.38,\n 0.352,\n 0.904,\n 1.408,\n 1.74,\n 1.808,\n 1.636,\n 1.46,\n 1.24,\n 1.024,\n 0.816,\n 0.668,\n 0.572,\n 0.676,\n 0.804,\n 0.92,\n 0.98,\n 0.932,\n 0.708,\n 0.72,\n 0.708,\n 0.652,\n 0.46,\n 0.184,\n -0.14,\n -0.2,\n -0.324,\n -0.448,\n -0.468,\n -0.46,\n -0.532\n ]\n }\n },\n {\n \"ID\": 1727272658417,\n \"data\": {\n \"x\": [\n 0.268,\n 0.236,\n 0.096,\n 0.016,\n -0.096,\n -0.144,\n -0.164,\n -0.532,\n -0.936,\n -2.04,\n -1.244,\n -0.868,\n -1.42,\n -1.308,\n -0.616,\n -0.256,\n 0.068,\n 0.444,\n 0.628,\n 0.984,\n 1.052,\n 0.984,\n 1.028,\n 0.916,\n 0.62,\n 0.62,\n 0.2,\n -0.432,\n -1.3,\n -2.04,\n -1.144,\n -1.312,\n -1.024,\n -0.812,\n -0.668,\n -0.16,\n 0.328,\n 0.448,\n 0.668,\n 1.396,\n 0.936,\n 0.952,\n 1.052,\n 1.04,\n 0.596,\n 0.24,\n 0.164,\n -0.244,\n -0.512,\n -1.288,\n -1.728,\n -1.628,\n -1.616,\n -0.792,\n -0.612,\n -0.088,\n 0.388,\n 0.648,\n 1.008,\n 1.612,\n 0.372,\n 1.26,\n 0.38,\n 1.216,\n 0.496,\n 0.264,\n 0.04,\n 0.12,\n -0.024,\n -0.52,\n -1.8,\n -1.672,\n -0.904,\n -0.484,\n -0.448,\n -0.108,\n 0.232,\n 0.36,\n 0.42,\n 0.288,\n 1.02,\n 0.472,\n 0.696,\n 0.376,\n 0.208,\n 0.064,\n -0.18,\n -0.26\n ],\n \"y\": [\n 1.152,\n 1.676,\n 0.884,\n 0.636,\n 0.012,\n -0.268,\n -0.564,\n -1.352,\n -1.904,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.68,\n -0.992,\n -0.528,\n -0.08,\n 0.896,\n 1.16,\n 1.356,\n 0.388,\n 0.348,\n 0.088,\n -0.172,\n -0.464,\n -1.12,\n -2.04,\n -2.016,\n -2.04,\n -2.04,\n -2.04,\n -1.888,\n -1.116,\n -0.644,\n -0.396,\n 0.168,\n 0.924,\n 1.304,\n 1.872,\n 0.444,\n 0.468,\n 0.196,\n 0.644,\n 0.332,\n -0.332,\n -1.128,\n -1.444,\n -1.928,\n -1.584,\n -2.04,\n -2.04,\n -1.304,\n -0.416,\n 0.132,\n 0.028,\n 0.292,\n 0.804,\n 0.984,\n 1.64,\n 1.848,\n 1.92,\n 0.608,\n 1.052,\n 0.344,\n -0.192,\n -1.22,\n -1.6,\n -1.644,\n -1.364,\n -1.764,\n -2.04,\n -2.04,\n -1.192,\n -0.436,\n -0.468,\n -0.532,\n -0.272,\n 0.096,\n 0.592,\n 0.656,\n 0.5,\n 0.156,\n -0.716,\n -0.936,\n -0.896,\n -0.936,\n -0.548\n ],\n \"z\": [\n 2.04,\n 1.74,\n 1.704,\n 1.532,\n 1.112,\n 0.944,\n 0.496,\n 0.008,\n 0.78,\n 1.056,\n -0.548,\n -1.228,\n -1.08,\n -0.348,\n -0.432,\n -0.14,\n 0.496,\n 1.432,\n 2.04,\n 2.04,\n 1.996,\n 1.836,\n 2.04,\n 2.024,\n 1.496,\n 0.336,\n -0.472,\n -0.58,\n 0.524,\n 0.196,\n -1.928,\n -1.62,\n -0.992,\n -0.468,\n 0.032,\n 0.572,\n 1.536,\n 2.04,\n 2.04,\n 1.6,\n 1.58,\n 2.04,\n 2.04,\n 2.04,\n 1.768,\n 1.388,\n 0.34,\n -0.444,\n -0.592,\n 1.776,\n 0.04,\n -1.116,\n -1.068,\n -0.876,\n -0.48,\n 0.052,\n 0.44,\n 1.772,\n 2.04,\n 2.04,\n 0.94,\n -0.36,\n 1.66,\n 2.04,\n 2.04,\n 2.04,\n 1.916,\n 0.824,\n 0.492,\n 1.104,\n 0.248,\n -1.712,\n -1.664,\n -1.436,\n -0.88,\n -0.372,\n 0.288,\n 1.028,\n 1.812,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 1.964,\n 1.388,\n 0.66\n ]\n }\n },\n {\n \"ID\": 1727272638820,\n \"data\": {\n \"x\": [\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.82,\n -1.552,\n -1.416,\n -1.34,\n -1.26,\n -1.196,\n -1.164,\n -1.096,\n -1.004,\n -0.924,\n -0.84,\n -0.772,\n -0.768,\n -0.916,\n -0.952,\n -1.144,\n -1.352,\n -1.72,\n -1.984,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.912,\n -1.696,\n -1.472,\n -1.296,\n -1.08,\n -0.856,\n -0.648,\n -0.504,\n -0.512,\n -0.496,\n -0.476,\n -0.484,\n -0.504,\n -0.54,\n -0.608,\n -0.708,\n -0.904,\n -1.324,\n -1.804,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.876,\n -1.64,\n -1.484,\n -1.292,\n -1.14,\n -0.976,\n -0.868,\n -0.788,\n -0.712,\n -0.672,\n -0.66,\n -0.644,\n -0.816,\n -0.916,\n -0.996,\n -1.14,\n -1.284,\n -1.416,\n -1.54,\n -1.736,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04\n ],\n \"y\": [\n -0.444,\n -0.536,\n -0.504,\n -0.408,\n -0.572,\n -0.752,\n -0.94,\n -0.868,\n -0.456,\n -0.296,\n -0.276,\n -0.344,\n -0.4,\n -0.488,\n -0.544,\n -0.584,\n -0.608,\n -0.64,\n -0.74,\n -0.984,\n -1.096,\n -1.076,\n -0.92,\n -0.864,\n -0.784,\n -0.688,\n -0.572,\n -0.432,\n -0.252,\n -0.132,\n -0.068,\n -0.092,\n -0.036,\n -0.056,\n -0.116,\n -0.172,\n -0.12,\n -0.112,\n 0.012,\n 0.036,\n 0.196,\n 0.34,\n 0.4,\n 0.34,\n 0.328,\n 0.34,\n 0.288,\n 0.184,\n 0.096,\n 0.024,\n 0.024,\n 0.02,\n 0.02,\n -0.064,\n -0.112,\n -0.208,\n -0.336,\n -0.384,\n -0.5,\n -0.712,\n -0.984,\n -0.944,\n -0.832,\n -0.656,\n -0.512,\n -0.464,\n -0.484,\n -0.472,\n -0.452,\n -0.448,\n -0.468,\n -0.536,\n -0.688,\n -0.884,\n -0.916,\n -0.912,\n -0.896,\n -0.768,\n -0.632,\n -0.492,\n -0.36,\n -0.28,\n -0.292,\n -0.336,\n -0.36,\n -0.332,\n -0.216,\n -0.384\n ],\n \"z\": [\n 0.712,\n 0.676,\n 0.748,\n 0.712,\n 0.636,\n 0.428,\n 0.172,\n 0.296,\n 0.068,\n -0.02,\n -0.044,\n -0.032,\n 0.016,\n 0.052,\n 0.092,\n 0.056,\n 0,\n -0.028,\n -0.128,\n -0.276,\n -0.288,\n -0.292,\n -0.308,\n -0.22,\n -0.116,\n -0.064,\n -0.012,\n 0.028,\n 0.004,\n -0.056,\n -0.02,\n 0.12,\n 0.128,\n 0.096,\n 0.128,\n 0.168,\n 0.16,\n 0.144,\n 0.072,\n 0.096,\n 0.028,\n -0.04,\n -0.068,\n -0.08,\n -0.032,\n -0.02,\n -0.008,\n -0.048,\n -0.076,\n -0.108,\n -0.112,\n -0.072,\n -0.044,\n 0.052,\n 0.112,\n 0.272,\n 0.388,\n 0.46,\n 0.464,\n 0.28,\n 0.256,\n 0.16,\n 0.24,\n 0.236,\n 0.2,\n 0.192,\n 0.188,\n 0.136,\n -0.004,\n -0.024,\n -0.048,\n -0.092,\n -0.128,\n -0.228,\n -0.176,\n -0.172,\n -0.1,\n -0.06,\n -0.028,\n -0.064,\n -0.06,\n -0.036,\n -0.024,\n 0.044,\n 0.056,\n 0.168,\n 0.16,\n 0.172\n ]\n }\n },\n {\n \"ID\": 1727272603693,\n \"data\": {\n \"x\": [\n -1.144,\n -0.948,\n -0.888,\n -0.82,\n -0.74,\n -0.768,\n -0.924,\n -1.196,\n -1.48,\n -1.324,\n -1.044,\n -0.796,\n -0.668,\n -0.504,\n -0.356,\n -0.188,\n -0.008,\n 0.244,\n 0.508,\n 0.6,\n 0.5,\n 0.388,\n 0.292,\n 0.124,\n -0.164,\n -0.404,\n -0.868,\n -1.356,\n -1.556,\n -1.62,\n -1.348,\n -1.216,\n -1.02,\n -0.956,\n -0.944,\n -0.872,\n -0.84,\n -0.776,\n -0.752,\n -0.812,\n -0.956,\n -1.072,\n -1.316,\n -1.632,\n -1.84,\n -1.756,\n -1.42,\n -1.076,\n -0.868,\n -0.684,\n -0.508,\n -0.268,\n -0.052,\n 0.176,\n 0.336,\n 0.376,\n 0.26,\n 0.128,\n -0.024,\n -0.216,\n -0.48,\n -0.792,\n -0.904,\n -1.16,\n -1.276,\n -1.276,\n -1.228,\n -1.16,\n -1.28,\n -1.364,\n -1.08,\n -0.924,\n -0.856,\n -0.876,\n -0.984,\n -0.996,\n -1.052,\n -1.492,\n -1.66,\n -1.424,\n -2.04,\n -1.744,\n -1.22,\n -0.74,\n -0.424,\n -0.196,\n 0.016,\n 0.256,\n 0.52\n ],\n \"y\": [\n -0.24,\n 0.188,\n 0.496,\n 0.448,\n 0.184,\n -0.128,\n -0.492,\n -0.964,\n -1.396,\n -1.644,\n -1.756,\n -1.708,\n -1.728,\n -1.672,\n -1.368,\n -1.132,\n -1,\n -0.904,\n -1.028,\n -1.112,\n -1.092,\n -0.992,\n -0.88,\n -0.952,\n -1.16,\n -1.532,\n -2.04,\n -2.04,\n -2.04,\n -2.032,\n -1.412,\n -0.936,\n -0.596,\n -0.452,\n -0.348,\n -0.276,\n -0.144,\n 0.128,\n 0.352,\n 0.316,\n 0.1,\n -0.064,\n -0.34,\n -0.9,\n -1.452,\n -1.712,\n -1.732,\n -1.504,\n -1.352,\n -1.368,\n -1.288,\n -1.132,\n -0.988,\n -0.908,\n -0.928,\n -0.888,\n -0.912,\n -1.008,\n -1.168,\n -1.288,\n -1.412,\n -1.548,\n -1.74,\n -2.04,\n -2.04,\n -2.04,\n -1.724,\n -1.056,\n -0.38,\n 0.032,\n 0.292,\n 0.496,\n 0.632,\n 0.556,\n 0.296,\n 0.012,\n -0.248,\n -0.688,\n -1.204,\n -1.764,\n -2.04,\n -2.04,\n -1.788,\n -1.688,\n -1.9,\n -1.876,\n -1.636,\n -1.376,\n -1.212\n ],\n \"z\": [\n -0.632,\n -0.664,\n -0.516,\n -0.34,\n -0.192,\n -0.176,\n -0.176,\n -0.216,\n -0.204,\n -0.564,\n -0.892,\n -0.972,\n -0.768,\n -0.572,\n -0.44,\n -0.3,\n -0.224,\n -0.16,\n -0.012,\n 0.168,\n 0.224,\n 0.176,\n 0.092,\n 0.012,\n -0.076,\n -0.116,\n 0.064,\n 0.536,\n 0.404,\n 0.224,\n 0.148,\n 0.144,\n 0.152,\n 0.072,\n 0.02,\n -0.06,\n -0.108,\n -0.14,\n -0.092,\n -0.104,\n -0.128,\n -0.18,\n -0.12,\n -0.096,\n -0.204,\n -0.424,\n -0.64,\n -0.712,\n -0.624,\n -0.528,\n -0.476,\n -0.464,\n -0.376,\n -0.244,\n -0.144,\n -0.06,\n -0.032,\n 0,\n -0.008,\n -0.036,\n -0.004,\n 0.02,\n -0.024,\n 0.016,\n 0.128,\n 0.112,\n -0.024,\n -0.172,\n -0.028,\n 0.112,\n 0.036,\n -0.096,\n -0.216,\n -0.2,\n -0.072,\n 0.04,\n 0.004,\n 0.256,\n 0.372,\n 0.124,\n 0.208,\n 0.12,\n -0.072,\n -0.076,\n 0.096,\n 0.036,\n -0.152,\n -0.208,\n -0.308\n ]\n }\n },\n {\n \"ID\": 1727272585713,\n \"data\": {\n \"x\": [\n -2.04,\n -2.04,\n -1.612,\n -1.492,\n -1.368,\n -1.344,\n -0.848,\n -0.78,\n -0.472,\n -0.624,\n -0.592,\n -0.612,\n -0.504,\n -0.508,\n -0.468,\n -0.284,\n -0.324,\n -0.776,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.984,\n -1.912,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.976,\n -1.796,\n -1.708,\n -1.62,\n -1.576,\n -1.692,\n -1.472,\n -1.376,\n -1.192,\n -0.992,\n -0.784,\n -0.748,\n -0.58,\n -0.492,\n -1.06,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.952,\n -2.04,\n -2.036,\n -2.04,\n -1.992,\n -1.952,\n -1.928,\n -1.904,\n -1.952,\n -2.02,\n -2.04,\n -2.024,\n -1.916,\n -1.668,\n -1.296,\n -0.764,\n -0.4,\n -0.18,\n 0,\n -0.168,\n -0.596,\n -1.764,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04\n ],\n \"y\": [\n -1.064,\n -0.612,\n -0.376,\n -0.22,\n -0.004,\n 0.612,\n 0.936,\n -0.144,\n 0.008,\n 1.456,\n 1.9,\n 1.516,\n 1.272,\n 0.988,\n 0.748,\n 0.752,\n 0.984,\n 0.864,\n 0.152,\n -1.26,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.52,\n -1,\n -0.588,\n -0.188,\n 0.2,\n 0.436,\n 0.928,\n 1.048,\n 0.34,\n 1.4,\n 2.04,\n 1.52,\n 1.216,\n 1.316,\n 1.544,\n 1.4,\n 0.776,\n -0.088,\n 0.212,\n -1.304,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.716,\n -1.056,\n -0.612,\n -0.276,\n -0.18,\n -0.24,\n -0.02,\n 0.292,\n 0.692,\n 0.776,\n 0.912,\n 1.176,\n 1.316,\n 1.08,\n 1.06,\n 1.332,\n 1.472,\n 1.548,\n 1.232,\n 0.46,\n -1.088,\n -1.892,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04\n ],\n \"z\": [\n 0.88,\n 0.664,\n 0.34,\n 0.308,\n 0.464,\n 0.976,\n 1.3,\n 1.268,\n 1.136,\n 1.32,\n 1.372,\n 1.196,\n 0.868,\n 0.716,\n 0.548,\n 0.348,\n 0.368,\n 0.764,\n 1.364,\n 1.06,\n 0.88,\n 0.48,\n -0.856,\n -1.98,\n -2.04,\n -2.04,\n -2.04,\n -1.576,\n -0.652,\n 0.304,\n 0.784,\n 0.932,\n 1.024,\n 0.932,\n 0.74,\n 0.736,\n 0.728,\n 0.744,\n 0.984,\n 1.26,\n 1.204,\n 1.112,\n 1.264,\n 1.096,\n 0.988,\n 0.936,\n 0.784,\n 0.92,\n 1.348,\n 1.488,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 0.264,\n -0.068,\n 1.112,\n 1.468,\n 1.332,\n 1.348,\n 1.852,\n 2.04,\n 2.04,\n 1.904,\n 1.66,\n 1.26,\n 0.976,\n 0.752,\n 0.82,\n 0.848,\n 0.772,\n 0.62,\n 0.456,\n 0.312,\n 0.324,\n 0.468,\n 0.616,\n 0.608,\n 0.524,\n 0.672,\n 1.26,\n 0.088,\n 1.036,\n 2.04,\n 0.764,\n -1.112,\n -1.716,\n -0.876,\n -0.972\n ]\n }\n }\n ]\n },\n {\n \"icon\": \"Asleep\",\n \"ID\": 1727272691910,\n \"name\": \"Not exercising\",\n \"recordings\": [\n {\n \"ID\": 1727272846488,\n \"data\": {\n \"x\": [\n -0.296,\n -0.296,\n -0.3,\n -0.3,\n -0.288,\n -0.296,\n -0.304,\n -0.316,\n -0.304,\n -0.3,\n -0.3,\n -0.304,\n -0.3,\n -0.3,\n -0.304,\n -0.296,\n -0.296,\n -0.292,\n -0.3,\n -0.304,\n -0.304,\n -0.304,\n -0.308,\n -0.304,\n -0.304,\n -0.308,\n -0.304,\n -0.312,\n -0.308,\n -0.312,\n -0.316,\n -0.312,\n -0.304,\n -0.308,\n -0.304,\n -0.312,\n -0.304,\n -0.312,\n -0.304,\n -0.3,\n -0.304,\n -0.292,\n -0.304,\n -0.296,\n -0.3,\n -0.304,\n -0.3,\n -0.3,\n -0.296,\n -0.3,\n -0.296,\n -0.304,\n -0.304,\n -0.308,\n -0.308,\n -0.308,\n -0.3,\n -0.304,\n -0.308,\n -0.308,\n -0.304,\n -0.316,\n -0.308,\n -0.304,\n -0.312,\n -0.296,\n -0.304,\n -0.304,\n -0.304,\n -0.304,\n -0.3,\n -0.3,\n -0.296,\n -0.292,\n -0.296,\n -0.3,\n -0.296,\n -0.304,\n -0.3,\n -0.292,\n -0.284,\n -0.304,\n -0.292,\n -0.304,\n -0.292,\n -0.3,\n -0.308,\n -0.312\n ],\n \"y\": [\n 0.98,\n 0.992,\n 1,\n 0.976,\n 0.952,\n 0.964,\n 0.972,\n 0.98,\n 0.972,\n 0.972,\n 0.98,\n 0.984,\n 0.976,\n 0.984,\n 0.98,\n 0.972,\n 0.964,\n 0.972,\n 0.976,\n 0.98,\n 0.964,\n 0.98,\n 0.98,\n 0.988,\n 0.988,\n 0.988,\n 0.984,\n 0.984,\n 0.976,\n 0.98,\n 0.972,\n 0.984,\n 0.984,\n 0.996,\n 0.984,\n 0.976,\n 0.976,\n 0.98,\n 0.984,\n 0.976,\n 0.964,\n 0.984,\n 0.98,\n 0.976,\n 0.976,\n 0.98,\n 0.976,\n 0.98,\n 0.988,\n 0.98,\n 0.98,\n 0.98,\n 0.996,\n 0.976,\n 0.976,\n 0.976,\n 0.968,\n 0.98,\n 0.968,\n 0.972,\n 0.992,\n 0.984,\n 0.976,\n 0.984,\n 0.992,\n 0.996,\n 0.98,\n 0.972,\n 0.98,\n 0.976,\n 0.976,\n 0.984,\n 0.984,\n 0.976,\n 0.972,\n 0.976,\n 0.976,\n 0.992,\n 0.972,\n 0.964,\n 0.972,\n 0.988,\n 1,\n 0.996,\n 0.992,\n 0.98,\n 0.984,\n 0.972\n ],\n \"z\": [\n -0.08,\n -0.092,\n -0.092,\n -0.096,\n -0.096,\n -0.092,\n -0.096,\n -0.104,\n -0.092,\n -0.096,\n -0.096,\n -0.088,\n -0.096,\n -0.088,\n -0.096,\n -0.092,\n -0.096,\n -0.1,\n -0.096,\n -0.084,\n -0.1,\n -0.084,\n -0.092,\n -0.08,\n -0.072,\n -0.084,\n -0.084,\n -0.088,\n -0.084,\n -0.084,\n -0.08,\n -0.076,\n -0.084,\n -0.092,\n -0.084,\n -0.088,\n -0.08,\n -0.092,\n -0.076,\n -0.092,\n -0.092,\n -0.1,\n -0.092,\n -0.088,\n -0.092,\n -0.088,\n -0.084,\n -0.092,\n -0.092,\n -0.088,\n -0.072,\n -0.092,\n -0.092,\n -0.092,\n -0.084,\n -0.084,\n -0.08,\n -0.092,\n -0.092,\n -0.088,\n -0.08,\n -0.096,\n -0.092,\n -0.084,\n -0.088,\n -0.092,\n -0.096,\n -0.088,\n -0.092,\n -0.096,\n -0.096,\n -0.096,\n -0.096,\n -0.1,\n -0.088,\n -0.1,\n -0.096,\n -0.1,\n -0.1,\n -0.092,\n -0.1,\n -0.108,\n -0.084,\n -0.092,\n -0.084,\n -0.092,\n -0.104,\n -0.08\n ]\n }\n },\n {\n \"ID\": 1727272840320,\n \"data\": {\n \"x\": [\n 0.256,\n 0.256,\n 0.252,\n 0.256,\n 0.26,\n 0.256,\n 0.252,\n 0.256,\n 0.256,\n 0.252,\n 0.252,\n 0.252,\n 0.252,\n 0.256,\n 0.264,\n 0.26,\n 0.252,\n 0.252,\n 0.264,\n 0.256,\n 0.256,\n 0.244,\n 0.248,\n 0.256,\n 0.256,\n 0.256,\n 0.264,\n 0.256,\n 0.248,\n 0.264,\n 0.256,\n 0.252,\n 0.248,\n 0.248,\n 0.248,\n 0.268,\n 0.268,\n 0.264,\n 0.252,\n 0.256,\n 0.256,\n 0.256,\n 0.252,\n 0.252,\n 0.252,\n 0.252,\n 0.252,\n 0.256,\n 0.256,\n 0.256,\n 0.248,\n 0.256,\n 0.252,\n 0.26,\n 0.248,\n 0.252,\n 0.252,\n 0.256,\n 0.256,\n 0.256,\n 0.248,\n 0.256,\n 0.252,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.256,\n 0.244,\n 0.252,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.248,\n 0.248,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.252\n ],\n \"y\": [\n -0.852,\n -0.848,\n -0.856,\n -0.856,\n -0.848,\n -0.856,\n -0.848,\n -0.86,\n -0.868,\n -0.856,\n -0.86,\n -0.852,\n -0.86,\n -0.864,\n -0.856,\n -0.852,\n -0.852,\n -0.848,\n -0.844,\n -0.86,\n -0.844,\n -0.848,\n -0.852,\n -0.852,\n -0.86,\n -0.86,\n -0.856,\n -0.852,\n -0.856,\n -0.848,\n -0.852,\n -0.856,\n -0.848,\n -0.844,\n -0.84,\n -0.852,\n -0.86,\n -0.868,\n -0.872,\n -0.868,\n -0.856,\n -0.852,\n -0.848,\n -0.852,\n -0.844,\n -0.848,\n -0.848,\n -0.848,\n -0.86,\n -0.856,\n -0.864,\n -0.86,\n -0.856,\n -0.852,\n -0.848,\n -0.856,\n -0.852,\n -0.856,\n -0.848,\n -0.872,\n -0.86,\n -0.856,\n -0.856,\n -0.856,\n -0.86,\n -0.856,\n -0.852,\n -0.856,\n -0.864,\n -0.856,\n -0.852,\n -0.86,\n -0.852,\n -0.852,\n -0.856,\n -0.856,\n -0.864,\n -0.86,\n -0.852,\n -0.86,\n -0.852,\n -0.856,\n -0.856,\n -0.856,\n -0.86,\n -0.852,\n -0.86,\n -0.852,\n -0.868\n ],\n \"z\": [\n -0.488,\n -0.476,\n -0.48,\n -0.476,\n -0.472,\n -0.48,\n -0.48,\n -0.484,\n -0.476,\n -0.48,\n -0.488,\n -0.488,\n -0.484,\n -0.48,\n -0.48,\n -0.476,\n -0.48,\n -0.476,\n -0.476,\n -0.476,\n -0.476,\n -0.472,\n -0.484,\n -0.476,\n -0.476,\n -0.488,\n -0.48,\n -0.488,\n -0.484,\n -0.484,\n -0.48,\n -0.484,\n -0.488,\n -0.48,\n -0.472,\n -0.476,\n -0.48,\n -0.472,\n -0.488,\n -0.48,\n -0.476,\n -0.488,\n -0.484,\n -0.484,\n -0.48,\n -0.468,\n -0.476,\n -0.484,\n -0.476,\n -0.472,\n -0.476,\n -0.484,\n -0.484,\n -0.48,\n -0.484,\n -0.48,\n -0.476,\n -0.48,\n -0.48,\n -0.48,\n -0.472,\n -0.484,\n -0.476,\n -0.484,\n -0.488,\n -0.472,\n -0.472,\n -0.48,\n -0.476,\n -0.48,\n -0.48,\n -0.488,\n -0.484,\n -0.48,\n -0.488,\n -0.476,\n -0.48,\n -0.472,\n -0.484,\n -0.48,\n -0.48,\n -0.472,\n -0.476,\n -0.476,\n -0.476,\n -0.48,\n -0.472,\n -0.476,\n -0.48\n ]\n }\n },\n {\n \"ID\": 1727272790047,\n \"data\": {\n \"x\": [\n -1.056,\n -1.056,\n -1.06,\n -1.06,\n -1.052,\n -1.052,\n -1.048,\n -1.056,\n -1.048,\n -1.056,\n -1.052,\n -1.044,\n -1.048,\n -1.048,\n -1.056,\n -1.06,\n -1.052,\n -1.056,\n -1.052,\n -1.052,\n -1.06,\n -1.06,\n -1.056,\n -1.064,\n -1.048,\n -1.044,\n -1.044,\n -1.048,\n -1.056,\n -1.056,\n -1.06,\n -1.044,\n -1.052,\n -1.052,\n -1.056,\n -1.052,\n -1.056,\n -1.052,\n -1.052,\n -1.06,\n -1.044,\n -1.048,\n -1.048,\n -1.056,\n -1.052,\n -1.044,\n -1.048,\n -1.06,\n -1.048,\n -1.052,\n -1.056,\n -1.06,\n -1.056,\n -1.06,\n -1.06,\n -1.056,\n -1.064,\n -1.06,\n -1.052,\n -1.044,\n -1.052,\n -1.052,\n -1.06,\n -1.052,\n -1.056,\n -1.056,\n -1.056,\n -1.056,\n -1.056,\n -1.056,\n -1.06,\n -1.06,\n -1.06,\n -1.048,\n -1.06,\n -1.056,\n -1.052,\n -1.06,\n -1.052,\n -1.052,\n -1.056,\n -1.056,\n -1.056,\n -1.06,\n -1.048,\n -1.056,\n -1.056,\n -1.048,\n -1.064\n ],\n \"y\": [\n -0.144,\n -0.152,\n -0.148,\n -0.148,\n -0.144,\n -0.168,\n -0.152,\n -0.164,\n -0.152,\n -0.152,\n -0.156,\n -0.144,\n -0.152,\n -0.14,\n -0.16,\n -0.144,\n -0.148,\n -0.144,\n -0.148,\n -0.144,\n -0.148,\n -0.144,\n -0.144,\n -0.164,\n -0.144,\n -0.152,\n -0.156,\n -0.144,\n -0.144,\n -0.144,\n -0.144,\n -0.14,\n -0.136,\n -0.152,\n -0.144,\n -0.164,\n -0.148,\n -0.16,\n -0.148,\n -0.16,\n -0.156,\n -0.14,\n -0.14,\n -0.14,\n -0.144,\n -0.144,\n -0.136,\n -0.144,\n -0.144,\n -0.144,\n -0.148,\n -0.152,\n -0.148,\n -0.14,\n -0.16,\n -0.156,\n -0.152,\n -0.148,\n -0.152,\n -0.144,\n -0.14,\n -0.14,\n -0.144,\n -0.14,\n -0.144,\n -0.148,\n -0.16,\n -0.156,\n -0.152,\n -0.152,\n -0.144,\n -0.148,\n -0.144,\n -0.144,\n -0.148,\n -0.14,\n -0.136,\n -0.14,\n -0.156,\n -0.156,\n -0.14,\n -0.144,\n -0.144,\n -0.144,\n -0.148,\n -0.14,\n -0.144,\n -0.144,\n -0.14\n ],\n \"z\": [\n 0.032,\n 0.036,\n 0.032,\n 0.02,\n 0.032,\n 0.024,\n 0.024,\n 0.032,\n 0.036,\n 0.028,\n 0.036,\n 0.04,\n 0.028,\n 0.032,\n 0.032,\n 0.036,\n 0.032,\n 0.024,\n 0.024,\n 0.028,\n 0.028,\n 0.032,\n 0.024,\n 0.04,\n 0.036,\n 0.032,\n 0.028,\n 0.032,\n 0.028,\n 0.028,\n 0.028,\n 0.028,\n 0.02,\n 0.032,\n 0.032,\n 0.028,\n 0.036,\n 0.04,\n 0.028,\n 0.032,\n 0.024,\n 0.02,\n 0.02,\n 0.02,\n 0.032,\n 0.02,\n 0.024,\n 0.024,\n 0.024,\n 0.028,\n 0.024,\n 0.024,\n 0.032,\n 0.028,\n 0.024,\n 0.024,\n 0.02,\n 0.024,\n 0.024,\n 0.016,\n 0.028,\n 0.024,\n 0.028,\n 0.032,\n 0.028,\n 0.028,\n 0.028,\n 0.028,\n 0.028,\n 0.024,\n 0.02,\n 0.024,\n 0.028,\n 0.024,\n 0.024,\n 0.02,\n 0.028,\n 0.016,\n 0.024,\n 0.024,\n 0.024,\n 0.02,\n 0.024,\n 0.028,\n 0.024,\n 0.028,\n 0.02,\n 0.024,\n 0.02\n ]\n }\n },\n {\n \"ID\": 1727272784043,\n \"data\": {\n \"x\": [\n 0.008,\n 0.008,\n 0.012,\n 0.008,\n 0.004,\n 0.004,\n 0.004,\n -0.004,\n 0.004,\n 0.004,\n 0.004,\n -0.004,\n 0,\n -0.004,\n 0,\n 0,\n 0,\n 0,\n 0.004,\n 0.008,\n -0.004,\n 0.004,\n 0,\n 0,\n 0.004,\n 0,\n 0.008,\n 0.004,\n 0.004,\n 0.004,\n 0.004,\n 0.004,\n 0.008,\n 0.004,\n 0.008,\n 0.004,\n 0.004,\n 0.008,\n 0.008,\n 0.012,\n 0.008,\n 0.008,\n 0.004,\n 0.008,\n 0.004,\n 0,\n 0,\n 0.004,\n 0.004,\n 0,\n 0.004,\n 0,\n 0.004,\n 0,\n 0.004,\n 0.004,\n 0.008,\n 0.004,\n 0.008,\n 0.016,\n 0.008,\n 0.012,\n 0.004,\n 0.012,\n 0.008,\n 0.008,\n 0.008,\n 0.012,\n 0.004,\n 0.012,\n 0.004,\n 0.004,\n 0.004,\n 0.012,\n 0.008,\n 0.008,\n 0.008,\n 0.008,\n 0.016,\n 0.012,\n 0.004,\n 0.016,\n 0,\n 0.004,\n 0.008,\n 0.004,\n 0,\n 0.004,\n 0.016\n ],\n \"y\": [\n -0.952,\n -0.948,\n -0.952,\n -0.956,\n -0.968,\n -0.952,\n -0.948,\n -0.956,\n -0.952,\n -0.944,\n -0.96,\n -0.96,\n -0.972,\n -0.956,\n -0.956,\n -0.952,\n -0.968,\n -0.96,\n -0.96,\n -0.968,\n -0.956,\n -0.96,\n -0.944,\n -0.948,\n -0.944,\n -0.944,\n -0.952,\n -0.956,\n -0.952,\n -0.956,\n -0.96,\n -0.952,\n -0.96,\n -0.952,\n -0.948,\n -0.936,\n -0.944,\n -0.948,\n -0.94,\n -0.952,\n -0.948,\n -0.936,\n -0.944,\n -0.948,\n -0.956,\n -0.952,\n -0.952,\n -0.968,\n -0.964,\n -0.96,\n -0.964,\n -0.956,\n -0.956,\n -0.948,\n -0.96,\n -0.956,\n -0.96,\n -0.964,\n -0.956,\n -0.956,\n -0.948,\n -0.944,\n -0.948,\n -0.94,\n -0.952,\n -0.956,\n -0.956,\n -0.956,\n -0.96,\n -0.952,\n -0.956,\n -0.952,\n -0.952,\n -0.952,\n -0.956,\n -0.952,\n -0.956,\n -0.96,\n -0.96,\n -0.96,\n -0.968,\n -0.964,\n -0.968,\n -0.956,\n -0.944,\n -0.944,\n -0.948,\n -0.952,\n -0.944\n ],\n \"z\": [\n 0.284,\n 0.276,\n 0.268,\n 0.284,\n 0.276,\n 0.276,\n 0.276,\n 0.264,\n 0.272,\n 0.26,\n 0.272,\n 0.276,\n 0.28,\n 0.276,\n 0.268,\n 0.276,\n 0.272,\n 0.28,\n 0.26,\n 0.272,\n 0.272,\n 0.272,\n 0.268,\n 0.268,\n 0.268,\n 0.268,\n 0.272,\n 0.268,\n 0.276,\n 0.272,\n 0.276,\n 0.272,\n 0.26,\n 0.28,\n 0.28,\n 0.268,\n 0.276,\n 0.272,\n 0.264,\n 0.276,\n 0.268,\n 0.26,\n 0.264,\n 0.26,\n 0.264,\n 0.272,\n 0.264,\n 0.264,\n 0.268,\n 0.268,\n 0.26,\n 0.268,\n 0.268,\n 0.268,\n 0.272,\n 0.276,\n 0.28,\n 0.268,\n 0.268,\n 0.256,\n 0.256,\n 0.252,\n 0.248,\n 0.256,\n 0.252,\n 0.264,\n 0.244,\n 0.256,\n 0.264,\n 0.264,\n 0.264,\n 0.248,\n 0.264,\n 0.256,\n 0.252,\n 0.256,\n 0.248,\n 0.256,\n 0.248,\n 0.244,\n 0.244,\n 0.252,\n 0.252,\n 0.256,\n 0.256,\n 0.252,\n 0.248,\n 0.244,\n 0.252\n ]\n }\n },\n {\n \"ID\": 1727272755599,\n \"data\": {\n \"x\": [\n -0.048,\n -0.052,\n -0.048,\n -0.048,\n -0.048,\n -0.052,\n -0.044,\n -0.048,\n -0.048,\n -0.052,\n -0.048,\n -0.048,\n -0.048,\n -0.048,\n -0.044,\n -0.044,\n -0.052,\n -0.048,\n -0.048,\n -0.048,\n -0.04,\n -0.044,\n -0.048,\n -0.048,\n -0.048,\n -0.044,\n -0.052,\n -0.04,\n -0.04,\n -0.048,\n -0.052,\n -0.044,\n -0.052,\n -0.052,\n -0.044,\n -0.036,\n -0.044,\n -0.044,\n -0.044,\n -0.052,\n -0.044,\n -0.048,\n -0.052,\n -0.052,\n -0.056,\n -0.036,\n -0.044,\n -0.04,\n -0.048,\n -0.048,\n -0.056,\n -0.044,\n -0.044,\n -0.048,\n -0.044,\n -0.052,\n -0.052,\n -0.048,\n -0.052,\n -0.052,\n -0.044,\n -0.044,\n -0.04,\n -0.048,\n -0.04,\n -0.044,\n -0.044,\n -0.056,\n -0.044,\n -0.048,\n -0.048,\n -0.044,\n -0.052,\n -0.048,\n -0.052,\n -0.044,\n -0.052,\n -0.048,\n -0.048,\n -0.052,\n -0.048,\n -0.052,\n -0.044,\n -0.052,\n -0.052,\n -0.044,\n -0.052,\n -0.044\n ],\n \"y\": [\n -0.352,\n -0.336,\n -0.356,\n -0.34,\n -0.348,\n -0.348,\n -0.344,\n -0.356,\n -0.344,\n -0.348,\n -0.356,\n -0.348,\n -0.344,\n -0.336,\n -0.356,\n -0.348,\n -0.344,\n -0.34,\n -0.356,\n -0.348,\n -0.352,\n -0.348,\n -0.34,\n -0.352,\n -0.352,\n -0.348,\n -0.34,\n -0.352,\n -0.352,\n -0.344,\n -0.348,\n -0.356,\n -0.34,\n -0.344,\n -0.344,\n -0.352,\n -0.344,\n -0.344,\n -0.356,\n -0.344,\n -0.344,\n -0.348,\n -0.344,\n -0.348,\n -0.348,\n -0.348,\n -0.344,\n -0.34,\n -0.34,\n -0.348,\n -0.352,\n -0.348,\n -0.344,\n -0.352,\n -0.348,\n -0.34,\n -0.348,\n -0.34,\n -0.344,\n -0.34,\n -0.344,\n -0.36,\n -0.344,\n -0.348,\n -0.344,\n -0.352,\n -0.348,\n -0.344,\n -0.344,\n -0.332,\n -0.352,\n -0.352,\n -0.348,\n -0.344,\n -0.34,\n -0.348,\n -0.356,\n -0.352,\n -0.348,\n -0.352,\n -0.348,\n -0.344,\n -0.34,\n -0.356,\n -0.356,\n -0.348,\n -0.34,\n -0.344\n ],\n \"z\": [\n -1.032,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.028,\n -1.028,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.032,\n -1.028,\n -1.032,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.032,\n -1.024,\n -1.024,\n -1.02,\n -1.032,\n -1.02,\n -1.024,\n -1.028,\n -1.028,\n -1.024,\n -1.02,\n -1.028,\n -1.02,\n -1.02,\n -1.028,\n -1.028,\n -1.02,\n -1.024,\n -1.04,\n -1.024,\n -1.032,\n -1.028,\n -1.02,\n -1.024,\n -1.032,\n -1.036,\n -1.024,\n -1.02,\n -1.028,\n -1.028,\n -1.024,\n -1.024,\n -1.032,\n -1.032,\n -1.028,\n -1.028,\n -1.024,\n -1.024,\n -1.024,\n -1.02,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.028,\n -1.032,\n -1.028,\n -1.036,\n -1.024,\n -1.032,\n -1.016,\n -1.032,\n -1.028,\n -1.036,\n -1.02,\n -1.032,\n -1.02,\n -1.02,\n -1.028,\n -1.032,\n -1.028,\n -1.02,\n -1.028,\n -1.024,\n -1.028,\n -1.024,\n -1.024,\n -1.032,\n -1.036,\n -1.028\n ]\n }\n }\n ]\n }\n ]\n}", + // "main.blocks": "exercising-timenot-exercising-timeunknown-timeexercising-time0not-exercising-time0ml.event.Exercisingdurationexercising-time1durationButton.A0DIVIDE0exercising-time1000ml.event.NotExercisingdurationnot-exercising-time1durationButton.B0DIVIDE0not-exercising-time1000", + // "main.ts": "ml.onStopDetailed(ml.event.Exercising, function (duration) {\n basic.clearScreen()\n exercisingtime += duration\n})\ninput.onButtonPressed(Button.A, function () {\n basic.showNumber(exercisingtime / 1000)\n})\ninput.onButtonPressed(Button.B, function () {\n basic.showNumber(notexercisingtime / 1000)\n})\nml.onStopDetailed(ml.event.NotExercising, function (duration) {\n basic.clearScreen()\n notexercisingtime += duration\n})\nlet notexercisingtime = 0\nlet exercisingtime = 0\nexercisingtime = 0\nnotexercisingtime = 0\n", + // "pxt.json": "{\n \"name\": \"Simple AI exercise timer\",\n \"description\": \"\",\n \"dependencies\": {\n \"core\": \"*\",\n \"microphone\": \"*\",\n \"radio\": \"*\",\n \"machine-learning\": \"github:microbit-foundation/pxt-microbit-ml#v0.4.3\"\n },\n \"files\": [\n \"main.ts\",\n \"main.blocks\",\n \"autogenerated.ts\",\n \"dataset.json\",\n \"pxt.json\",\n \"README.md\"\n ],\n \"targetVersions\": {\n \"target\": \"7.1.2\",\n \"pxt\": \"10.3.5\"\n },\n \"preferredEditor\": \"blocksprj\"\n}\n", + // "_history": "{\"entries\":[{\"timestamp\":1728049865319,\"editorVersion\":\"7.0.42\",\"changes\":[{\"type\":\"added\",\"filename\":\"autogenerated.ts\",\"value\":\"// Auto-generated. Do not edit.\\nnamespace ml {\\n export namespace event {\\n //% fixedInstance block=\\\"Exercising\\\"\\n export const Exercising = new MlEvent(2, \\\"Exercising\\\");\\n //% fixedInstance block=\\\"Not exercising\\\"\\n export const NotExercising = new MlEvent(3, \\\"Not exercising\\\");\\n\\n }\\n \\n events = [event.Unknown,event.Exercising,event.NotExercising];\\n \\n control.onEvent(MlRunnerIds.MlRunnerInference, 1, () => {\\n if (!event.Unknown.onStartHandler) {\\n maybeUpdateEventStats(event.Unknown);\\n }\\n });\\n control.onEvent(MlRunnerIds.MlRunnerInference, 2, () => {\\n if (!event.Exercising.onStartHandler) {\\n maybeUpdateEventStats(event.Exercising);\\n }\\n });\\n control.onEvent(MlRunnerIds.MlRunnerInference, 3, () => {\\n if (!event.NotExercising.onStartHandler) {\\n maybeUpdateEventStats(event.NotExercising);\\n }\\n });\\n\\n getModelBlob = (): Buffer => {\\n const result = hex`4C444F4D38001900500003000000000000000002CDCC4C3F0B45786572636973696E6700CDCC4C3F0F4E6F742065786572636973696E6700620F47304D4C3446500000002C0D0000A40500000000000000000000A80000000800000001000000080000000100000000000000000000000000000000000000180000000000000002000000000000002DE9F05F0F460169091839600021796038680346B3EC1E1A07F2080292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A92EC010A20EE0A0A30EE2A0AA2EC010A92EC010A20EE0B0A30EE2B0AA2EC010A92EC010A20EE0C0A30EE2C0AA2EC010A92EC010A20EE0D0A30EE2D0AA2EC010A92EC010A20EE0E0A30EE2E0AA2EC010A92EC010A20EE0F0A30EE2F0AA2EC010A02F22402B3EC121A07F2440292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A02F23C02386800F2C00307F268021024B3EC010A07F20801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC0A0AF3EC0A7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A30EE050AA2EC010A013C8FD107F2680210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C2386800F2007307F208020224B3EC010A07F26801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC020AF3EC027A60EEA70A21EE081A30EE200A30EE010AA2EC010A013CAFD107F208021046022100F002F8BDE8F09F012938B5D0ED002A29D9031D00EB8102F3EC017AF4EE627AF1EE10FAC8BFF0EE672A9A42F4D1002402EE104A054695ED000A30EE620A00F015F80134A14232EE002AA5EC010AF2D8002390ED007AC7EE027A01339942E0EC017AF6D838BD0029E1D138BDDFED297AB4EEE70AF1EE10FA48D4DFED277AB4EEE70AF1EE10FA3ADCDFED247ADFED244A9FED243ADFED243A9FED245A9FED244ADFED245A9FED246ADFED246A60EE277AB7EE007A77EEA47A77EEE47AA7EE830AFDEEE74AA7EEA30AF0EE457AE4EE007A14EE903AE7EE805AA5EE806AE6EE006AF0EE667AF0EE476AE7EE806AA6EE807A17EE102A02EBC35300EE103A7047DFED107AB7EE007A87EE270A70479FED0C0A704700000000AAC20000AE423BAAB83F0000404B007231BF8EBEBFB56E2F093C00A0B43AADAD2A3D28AA2A3EFBFFFF3E0000000059D0953F799026BD2B527B3F93FA7DBECD01913F2730F7BE80DEAE3FB32EDC3E7829A33FB4147A3EFB59A93F5EC956BEBE2B863F6135183F9FF8833F0CB5253F84D6903F9567DA3E6C5CD83FE25994BEAFB6B23FFCBCB7BE45C5AF3F5613BABE20C41F3FF7BD2FBF4E9F023F322A36BF6C53263FBC4959BF39A3EB3C7B329CBFC1E4393D4826DEBF3547223D68007BBF31AFC63FBA16C6BBF4CAC83F6CEDB0BCADFAB83F21358BBDD8E8B23F142A17BF15D1AD3F4F6D31BF8947AB3F87CFD2BE973C4BBC6780D5BD8F1A80BE41A5B0BDE8EFE43DC20F303E8E232BBCFFF501BD0068F4BB4496293D8BB6683E26351D3EA94792BE3FC12EBD42622DBEA1BF40BE7233D6BEC03DF8BDA5779CBD25EB643EB1289D3D05429D3DA4F0C5BE0A83923EF21CA53C22E35A3D8477C0BE68365BBEEA5419BEF32C2FBC56B15F3EB9C991BE33DFB4BEA0220D3EEECF87BEBEEDD6BED46DABBE9F0686BE1DA4F83CF598973C9AF70BBFBB1785BE43AA43BC2E3CA4BE84068A3E29DB37BE34A20C3E37D702BED7F704BE27040E3E34AC90B9AA24BB3DD51308BE6477993D18CB03BE0506C0BEA83CB23EFDDF6CBE0E32243EB8E3D53D78FFD7BDD518B13EF43858BCCF02243E50F610BE4388FCBC5539D03D9B23B5BD3AF8103EC53B843E81B6A43EAEE7ADBE9C0636BE992A85BEC342633EB7318CBD2BB9873E658A66BDD23CB1BE4EFA36BEC0D19EBEB5884D3EBAC9CEBD0CEC83BEBFB2BDBD5A9C56BC1176B2BE7C8EFEBD06EC853EC37F15BE3B991EBE17A814BD79A041BE8BB93C3DD76E53BEEA724E3E884D4F3EBC417BBEDA9A863CF0F455BE7E80C93CCFB8A5BEF7D18A3DC1FA543EEFA34D3E75DDCC3D7D55B73D6073543D0531F0BD3B2E803EE467113DD2F5C53EFDE8A7BD05ACEA3A902CAB3EBFC47A3E7412E03EC852EA3E9D9EF43D131B8D3D5A01A33DC4F7F3BD74A234BEC42D223EFAAEC9BEDA87AA3CE621E53DE31DFB3D2B9F38BE5C433F3E398A8A3E799C8BBE41A084BD5801EBBE137AF9BE9CC6E9BD642991BEC4B9433EEED8A23C802CD3BD4110A23E6F60A43DCC1D0B3E957412BD2AB9953E9FD6A43EEA9974BC55735E3C08C449BE708FED3D99CE5F3DE623B53EDC098CBEDF5BCB3D67F317BEC25A113DB80498BE996E45BD4A6AC7BD3862313E9B628C3E9D72A73E54FA133EA9D7E5BD6CB60C3F0B573B3E119C9EBEEEB0ECBDBFDF0ABD8E18533D49E12DBC1326A53CE0A6C03E742CBABE9FFC92BDA99A9D3DF4EC39BDEDF04A3ECD301ABE314151BE1F0ADCBC95B119BEB9B08EBEECD888BE3A76DEBD4C5D3F3D53F954BE96EAAA3D0D96AB3C4BBB633E0B2BAC3D9800C73D7F9D123D5E13853EB96CCABDAFAB0FBEB68639BE4D1D243E1775BEBD7C39873E3C5E4D3C953E53BE97996ABE719CA0BE3B3FAE3E8874873EAAEFF4BA59B59E3C09473B3C1FC82DBDB2476ABEA6636EBE07F675BEFAC74B3ED2948EBD469156BD2E9F7CBEB42D8B3DDE110FBE5A0F3ABE848580BE6DC6613D364796BDF03B5EBEF29B52BE5A97B93D513B2ABD4996073E7F4F57BEAEB7773E2527AEBD2691123E490AF2BBA593C43D50EB6A3D8269DBBE26E290BE6BB64BBEEE2F92BE4C9A08BD499FAFBE1EE773BE5B9C7B3E5A0968BEBDD4FBBDFACE9ABDCE0822BEAE10473DC49400BE78A3833C9BD6CA3CAC86AABD9B6E9C3ECB8B103EED21BEBEFB0D323DD37300BE156851BCCB6DBC3E34A7DA3D5FC2B53E2FEE48BEA192E4BB19FA20BD1E91C8BD8CA151BE0800D5BE4C667DBDA32CBFBB1EEF793EAD567E3E76BCBC3D7511933EF1B2883E754E223EFE74593C049DFB3CFA97123D61FC8A3ECA815C3E8A42383EA9528A3D2EC4A9BE868E78BB18CFF6BD52E1493DCAF0653DEF5C45BEC51B123D6CAA81BECDD53BBD7C08ED3D8114C03EB8A66BBD7B60993E631C673DF53F0E3DB59DC03C4C4021BE34BB4F3ECFB810BDED7A5ABEF9B40F3D70F9E3BEDF24023D0B83533D1DA8553D7A048CBE1E75C43CEBF4C03DE6C991BE712D3CBE517E3E3E92B4303D63BACC3DD39D553D7614173E30C8843ECA75373D140A193DB1CF863E9F74CE3DCB09973DC04FBB3E299D173E86F5793DAAE9533D0903EC3D3E896DBD61C387BE196ACBBEAB19B43E355C5ABE69774F3D751239BEF7939B3AF9006E3E8E7E3ABDB53CD63D50A500BEE566503EDBE856BEB2181FBDE7D65F3E8548D73E9B13BE3E4966373E731B123E6E79593E524B1D3E817E333D5DF460BEDC2866BC7CE467BEC07094BCEC1FACBE0B8831BE4D4BBDBB702E0F3ED2F49C3D3F8D82BE690FFF3D04AC22BC00D1F8BC3FE270BD6897ACBEBFC419BEE408A03D2CF3DFBCF730443D124B66BE455C5CBEC7A289BD2836EC3CF5A7363D22B9583ED6B0D1BD66ECF73D3A57253D6C9211BFD88874BECC6A85BE6DCE07BF7079E4BD1AD1C4BB7C6CFE3E59653E3E8F7FA9BEF973AB3DF728023D00AE253E153A8E3D18EDA33E99DFEEBEC97051BEEA32433E29B71F3EBC51C03EEDD8703EBFAEB3BE9EF7EE3D9E72FCBE5CB6B9BEDB567D3EA24C4E3CB34F893E41F52C3E9FEF053F194FD6BD482EDBBDB721C2BEA8C568BECA3E41BEA61E04BEDBFD8B3E7403F9BE3E952C3F9EF7EEBD721B8DBE8192D93E16E0A53D59A37A3EDBB7A8BDF99484BE197950BE13CC13BFB57C0A3FD476173F92FEEABE7848F5BE1195B7BD2AA7F5BEAF53383ECE043EBF00000000`;\\n return result;\\n };\\n\\n simulatorSendData();\\n}\\n\\n// Auto-generated. Do not edit. Really.\\n\"},{\"type\":\"added\",\"filename\":\"main.blocks\",\"value\":\"exercising-timenot-exercising-timeunknown-timeexercising-time0not-exercising-time0ml.event.Exercisingdurationexercising-time1durationButton.A0DIVIDE0exercising-time1000ml.event.NotExercisingdurationnot-exercising-time1durationButton.B0DIVIDE0not-exercising-time1000\"},{\"type\":\"added\",\"filename\":\"main.ts\",\"value\":\"ml.onStopDetailed(ml.event.Exercising, function (duration) {\\n basic.clearScreen()\\n exercisingtime += duration\\n})\\ninput.onButtonPressed(Button.A, function () {\\n basic.showNumber(exercisingtime / 1000)\\n})\\ninput.onButtonPressed(Button.B, function () {\\n basic.showNumber(notexercisingtime / 1000)\\n})\\nml.onStopDetailed(ml.event.NotExercising, function (duration) {\\n basic.clearScreen()\\n notexercisingtime += duration\\n})\\nlet notexercisingtime = 0\\nlet exercisingtime = 0\\nexercisingtime = 0\\nnotexercisingtime = 0\\n\"},{\"type\":\"added\",\"filename\":\"pxt.json\",\"value\":\"{\\n \\\"name\\\": \\\"Simple AI exercise timer\\\",\\n \\\"description\\\": \\\"\\\",\\n \\\"dependencies\\\": {\\n \\\"core\\\": \\\"*\\\",\\n \\\"microphone\\\": \\\"*\\\",\\n \\\"radio\\\": \\\"*\\\",\\n \\\"machine-learning\\\": \\\"github:microbit-foundation/pxt-microbit-ml#v0.4.3\\\"\\n },\\n \\\"files\\\": [\\n \\\"main.ts\\\",\\n \\\"main.blocks\\\",\\n \\\"autogenerated.ts\\\",\\n \\\"dataset.json\\\",\\n \\\"pxt.json\\\",\\n \\\"README.md\\\"\\n ],\\n \\\"targetVersions\\\": {\\n \\\"target\\\": \\\"7.1.2\\\",\\n \\\"pxt\\\": \\\"10.3.5\\\"\\n },\\n \\\"preferredEditor\\\": \\\"blocksprj\\\"\\n}\\n\"}]}],\"snapshots\":[{\"timestamp\":1728049865318,\"editorVersion\":\"7.0.42\",\"text\":{}}],\"shares\":[],\"lastSaveTime\":1728049865319}" + // } + // } +}; From c6a00976edc616385f61be4abdefdd8fe3fde314 Mon Sep 17 00:00:00 2001 From: Grace Date: Mon, 14 Oct 2024 17:08:16 +0100 Subject: [PATCH 02/23] Add import page --- src/App.tsx | 6 +++ src/pages/ImportPage.tsx | 86 ++++++++++++++++++++++++++++++++++++++++ src/urls.ts | 2 + 3 files changed, 94 insertions(+) create mode 100644 src/pages/ImportPage.tsx diff --git a/src/App.tsx b/src/App.tsx index 4dcc90495..bac118186 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,9 +22,11 @@ import { LoggingProvider } from "./logging/logging-hooks"; import TranslationProvider from "./messages/TranslationProvider"; import { sessionPageConfigs } from "./pages-config"; import HomePage from "./pages/HomePage"; +import ImportPage from "./pages/ImportPage"; import NewPage from "./pages/NewPage"; import { createHomePageUrl, + createImportPageUrl, createNewPageUrl, createSessionPageUrl, } from "./urls"; @@ -94,6 +96,10 @@ const createRouter = () => { path: createNewPageUrl(), element: , }, + { + path: createImportPageUrl(), + element: , + }, ...sessionPageConfigs.map((config) => { return { path: createSessionPageUrl(config.id), diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx new file mode 100644 index 000000000..6015afe35 --- /dev/null +++ b/src/pages/ImportPage.tsx @@ -0,0 +1,86 @@ +import { Project } from "@microbit/makecode-embed/react"; +import { useEffect } from "react"; +import { IntlShape, useIntl } from "react-intl"; +import { useNavigate } from "react-router"; +import { useSearchParams } from "react-router-dom"; +import { useDeployment } from "../deployment"; +import { MicrobitOrgResource } from "../model"; +import { SessionPageId } from "../pages-config"; +import { useStore } from "../store"; +import { createSessionPageUrl } from "../urls"; + +const ImportPage = () => { + const navigate = useNavigate(); + const intl = useIntl(); + const { activitiesBaseUrl } = useDeployment(); + const resource = useMicrobitResourceSearchParams(); + const loadProject = useStore((s) => s.loadProject); + console.log("resource", resource); + + useEffect(() => { + const updateAsync = async () => { + if (!resource || !activitiesBaseUrl) { + return; + } + const code = await fetchMicrobitOrgResourceTargetCode( + activitiesBaseUrl, + resource, + intl + ); + console.log("code", code); + loadProject(code); + navigate(createSessionPageUrl(SessionPageId.DataSamples)); + }; + void updateAsync(); + }, [activitiesBaseUrl, intl, loadProject, navigate, resource]); + + return <>; +}; + +const useMicrobitResourceSearchParams = (): MicrobitOrgResource | undefined => { + const [params] = useSearchParams(); + const id = params.get("id"); + const project = params.get("project"); + const name = params.get("name"); + + return id && name && project ? { id, project, name } : undefined; +}; + +const isValidEditorContent = (content: Project): content is Project => { + return ( + content && + typeof content === "object" && + "text" in content && + !!content.text + ); +}; + +const fetchMicrobitOrgResourceTargetCode = async ( + activitiesBaseUrl: string, + resource: MicrobitOrgResource, + intl: IntlShape +): Promise => { + const url = `${activitiesBaseUrl}${resource.id}-makecode.json`; + let json; + try { + const response = await fetch(url); + json = (await response.json()) as object; + } catch (e) { + const rethrow = new Error( + intl.formatMessage({ id: "code-download-error" }) + ); + rethrow.stack = e instanceof Error ? e.stack : undefined; + throw rethrow; + } + if ( + !("editorContent" in json) || + typeof json.editorContent !== "object" || + !json.editorContent || + !isValidEditorContent(json.editorContent) + ) { + throw new Error(intl.formatMessage({ id: "code-format-error" })); + } + return json.editorContent; +}; + +export default ImportPage; diff --git a/src/urls.ts b/src/urls.ts index 2dd2a9163..611fd8a71 100644 --- a/src/urls.ts +++ b/src/urls.ts @@ -10,5 +10,7 @@ export const createHomePageUrl = () => `${basepath}`; export const createNewPageUrl = () => `${basepath}new`; +export const createImportPageUrl = () => `${basepath}import`; + export const createSessionPageUrl = (pageId: SessionPageId) => `${basepath}${pageId}`; From 089aa45393e6beac140b7b936016ea69bdc59d52 Mon Sep 17 00:00:00 2001 From: Grace Date: Mon, 14 Oct 2024 17:18:09 +0100 Subject: [PATCH 03/23] Remove not needed commented out block --- src/store.ts | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/store.ts b/src/store.ts index 4c3a887e9..2c0c97717 100644 --- a/src/store.ts +++ b/src/store.ts @@ -788,31 +788,4 @@ const getGesturesFromProject = ( return prevGestures; } return dataset.data as GestureData[]; - // { - // "header": { - // "target": "microbit", - // "targetVersion": "7.0.42", - // "editor": "blocksprj", - // "name": "Simple AI exercise timer", - // "meta": {}, - // "pubId": "", - // "pubCurrent": false, - // "id": "f102d806-f767-45c6-3af3-35b3be9dbdcd", - // "recentUse": 1728049865, - // "modificationTime": 1728049865, - // "path": "Simple-AI-exercise-timer", - // "cloudCurrent": false, - // "saveId": null, - // "githubCurrent": false - // }, - // "text": { - // "README.md": "", - // "autogenerated.ts": "// Auto-generated. Do not edit.\nnamespace ml {\n export namespace event {\n //% fixedInstance block=\"Exercising\"\n export const Exercising = new MlEvent(2, \"Exercising\");\n //% fixedInstance block=\"Not exercising\"\n export const NotExercising = new MlEvent(3, \"Not exercising\");\n\n }\n \n events = [event.Unknown,event.Exercising,event.NotExercising];\n \n control.onEvent(MlRunnerIds.MlRunnerInference, 1, () => {\n if (!event.Unknown.onStartHandler) {\n maybeUpdateEventStats(event.Unknown);\n }\n });\n control.onEvent(MlRunnerIds.MlRunnerInference, 2, () => {\n if (!event.Exercising.onStartHandler) {\n maybeUpdateEventStats(event.Exercising);\n }\n });\n control.onEvent(MlRunnerIds.MlRunnerInference, 3, () => {\n if (!event.NotExercising.onStartHandler) {\n maybeUpdateEventStats(event.NotExercising);\n }\n });\n\n getModelBlob = (): Buffer => {\n const result = hex`4C444F4D38001900500003000000000000000002CDCC4C3F0B45786572636973696E6700CDCC4C3F0F4E6F742065786572636973696E6700620F47304D4C3446500000002C0D0000A40500000000000000000000A80000000800000001000000080000000100000000000000000000000000000000000000180000000000000002000000000000002DE9F05F0F460169091839600021796038680346B3EC1E1A07F2080292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A92EC010A20EE0A0A30EE2A0AA2EC010A92EC010A20EE0B0A30EE2B0AA2EC010A92EC010A20EE0C0A30EE2C0AA2EC010A92EC010A20EE0D0A30EE2D0AA2EC010A92EC010A20EE0E0A30EE2E0AA2EC010A92EC010A20EE0F0A30EE2F0AA2EC010A02F22402B3EC121A07F2440292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A02F23C02386800F2C00307F268021024B3EC010A07F20801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC0A0AF3EC0A7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A30EE050AA2EC010A013C8FD107F2680210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C2386800F2007307F208020224B3EC010A07F26801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC020AF3EC027A60EEA70A21EE081A30EE200A30EE010AA2EC010A013CAFD107F208021046022100F002F8BDE8F09F012938B5D0ED002A29D9031D00EB8102F3EC017AF4EE627AF1EE10FAC8BFF0EE672A9A42F4D1002402EE104A054695ED000A30EE620A00F015F80134A14232EE002AA5EC010AF2D8002390ED007AC7EE027A01339942E0EC017AF6D838BD0029E1D138BDDFED297AB4EEE70AF1EE10FA48D4DFED277AB4EEE70AF1EE10FA3ADCDFED247ADFED244A9FED243ADFED243A9FED245A9FED244ADFED245A9FED246ADFED246A60EE277AB7EE007A77EEA47A77EEE47AA7EE830AFDEEE74AA7EEA30AF0EE457AE4EE007A14EE903AE7EE805AA5EE806AE6EE006AF0EE667AF0EE476AE7EE806AA6EE807A17EE102A02EBC35300EE103A7047DFED107AB7EE007A87EE270A70479FED0C0A704700000000AAC20000AE423BAAB83F0000404B007231BF8EBEBFB56E2F093C00A0B43AADAD2A3D28AA2A3EFBFFFF3E0000000059D0953F799026BD2B527B3F93FA7DBECD01913F2730F7BE80DEAE3FB32EDC3E7829A33FB4147A3EFB59A93F5EC956BEBE2B863F6135183F9FF8833F0CB5253F84D6903F9567DA3E6C5CD83FE25994BEAFB6B23FFCBCB7BE45C5AF3F5613BABE20C41F3FF7BD2FBF4E9F023F322A36BF6C53263FBC4959BF39A3EB3C7B329CBFC1E4393D4826DEBF3547223D68007BBF31AFC63FBA16C6BBF4CAC83F6CEDB0BCADFAB83F21358BBDD8E8B23F142A17BF15D1AD3F4F6D31BF8947AB3F87CFD2BE973C4BBC6780D5BD8F1A80BE41A5B0BDE8EFE43DC20F303E8E232BBCFFF501BD0068F4BB4496293D8BB6683E26351D3EA94792BE3FC12EBD42622DBEA1BF40BE7233D6BEC03DF8BDA5779CBD25EB643EB1289D3D05429D3DA4F0C5BE0A83923EF21CA53C22E35A3D8477C0BE68365BBEEA5419BEF32C2FBC56B15F3EB9C991BE33DFB4BEA0220D3EEECF87BEBEEDD6BED46DABBE9F0686BE1DA4F83CF598973C9AF70BBFBB1785BE43AA43BC2E3CA4BE84068A3E29DB37BE34A20C3E37D702BED7F704BE27040E3E34AC90B9AA24BB3DD51308BE6477993D18CB03BE0506C0BEA83CB23EFDDF6CBE0E32243EB8E3D53D78FFD7BDD518B13EF43858BCCF02243E50F610BE4388FCBC5539D03D9B23B5BD3AF8103EC53B843E81B6A43EAEE7ADBE9C0636BE992A85BEC342633EB7318CBD2BB9873E658A66BDD23CB1BE4EFA36BEC0D19EBEB5884D3EBAC9CEBD0CEC83BEBFB2BDBD5A9C56BC1176B2BE7C8EFEBD06EC853EC37F15BE3B991EBE17A814BD79A041BE8BB93C3DD76E53BEEA724E3E884D4F3EBC417BBEDA9A863CF0F455BE7E80C93CCFB8A5BEF7D18A3DC1FA543EEFA34D3E75DDCC3D7D55B73D6073543D0531F0BD3B2E803EE467113DD2F5C53EFDE8A7BD05ACEA3A902CAB3EBFC47A3E7412E03EC852EA3E9D9EF43D131B8D3D5A01A33DC4F7F3BD74A234BEC42D223EFAAEC9BEDA87AA3CE621E53DE31DFB3D2B9F38BE5C433F3E398A8A3E799C8BBE41A084BD5801EBBE137AF9BE9CC6E9BD642991BEC4B9433EEED8A23C802CD3BD4110A23E6F60A43DCC1D0B3E957412BD2AB9953E9FD6A43EEA9974BC55735E3C08C449BE708FED3D99CE5F3DE623B53EDC098CBEDF5BCB3D67F317BEC25A113DB80498BE996E45BD4A6AC7BD3862313E9B628C3E9D72A73E54FA133EA9D7E5BD6CB60C3F0B573B3E119C9EBEEEB0ECBDBFDF0ABD8E18533D49E12DBC1326A53CE0A6C03E742CBABE9FFC92BDA99A9D3DF4EC39BDEDF04A3ECD301ABE314151BE1F0ADCBC95B119BEB9B08EBEECD888BE3A76DEBD4C5D3F3D53F954BE96EAAA3D0D96AB3C4BBB633E0B2BAC3D9800C73D7F9D123D5E13853EB96CCABDAFAB0FBEB68639BE4D1D243E1775BEBD7C39873E3C5E4D3C953E53BE97996ABE719CA0BE3B3FAE3E8874873EAAEFF4BA59B59E3C09473B3C1FC82DBDB2476ABEA6636EBE07F675BEFAC74B3ED2948EBD469156BD2E9F7CBEB42D8B3DDE110FBE5A0F3ABE848580BE6DC6613D364796BDF03B5EBEF29B52BE5A97B93D513B2ABD4996073E7F4F57BEAEB7773E2527AEBD2691123E490AF2BBA593C43D50EB6A3D8269DBBE26E290BE6BB64BBEEE2F92BE4C9A08BD499FAFBE1EE773BE5B9C7B3E5A0968BEBDD4FBBDFACE9ABDCE0822BEAE10473DC49400BE78A3833C9BD6CA3CAC86AABD9B6E9C3ECB8B103EED21BEBEFB0D323DD37300BE156851BCCB6DBC3E34A7DA3D5FC2B53E2FEE48BEA192E4BB19FA20BD1E91C8BD8CA151BE0800D5BE4C667DBDA32CBFBB1EEF793EAD567E3E76BCBC3D7511933EF1B2883E754E223EFE74593C049DFB3CFA97123D61FC8A3ECA815C3E8A42383EA9528A3D2EC4A9BE868E78BB18CFF6BD52E1493DCAF0653DEF5C45BEC51B123D6CAA81BECDD53BBD7C08ED3D8114C03EB8A66BBD7B60993E631C673DF53F0E3DB59DC03C4C4021BE34BB4F3ECFB810BDED7A5ABEF9B40F3D70F9E3BEDF24023D0B83533D1DA8553D7A048CBE1E75C43CEBF4C03DE6C991BE712D3CBE517E3E3E92B4303D63BACC3DD39D553D7614173E30C8843ECA75373D140A193DB1CF863E9F74CE3DCB09973DC04FBB3E299D173E86F5793DAAE9533D0903EC3D3E896DBD61C387BE196ACBBEAB19B43E355C5ABE69774F3D751239BEF7939B3AF9006E3E8E7E3ABDB53CD63D50A500BEE566503EDBE856BEB2181FBDE7D65F3E8548D73E9B13BE3E4966373E731B123E6E79593E524B1D3E817E333D5DF460BEDC2866BC7CE467BEC07094BCEC1FACBE0B8831BE4D4BBDBB702E0F3ED2F49C3D3F8D82BE690FFF3D04AC22BC00D1F8BC3FE270BD6897ACBEBFC419BEE408A03D2CF3DFBCF730443D124B66BE455C5CBEC7A289BD2836EC3CF5A7363D22B9583ED6B0D1BD66ECF73D3A57253D6C9211BFD88874BECC6A85BE6DCE07BF7079E4BD1AD1C4BB7C6CFE3E59653E3E8F7FA9BEF973AB3DF728023D00AE253E153A8E3D18EDA33E99DFEEBEC97051BEEA32433E29B71F3EBC51C03EEDD8703EBFAEB3BE9EF7EE3D9E72FCBE5CB6B9BEDB567D3EA24C4E3CB34F893E41F52C3E9FEF053F194FD6BD482EDBBDB721C2BEA8C568BECA3E41BEA61E04BEDBFD8B3E7403F9BE3E952C3F9EF7EEBD721B8DBE8192D93E16E0A53D59A37A3EDBB7A8BDF99484BE197950BE13CC13BFB57C0A3FD476173F92FEEABE7848F5BE1195B7BD2AA7F5BEAF53383ECE043EBF00000000`;\n return result;\n };\n\n simulatorSendData();\n}\n\n// Auto-generated. Do not edit. Really.\n", - // "dataset.json": "{\n \"data\": [\n {\n \"icon\": \"StickFigure\",\n \"ID\": 1727272450006,\n \"name\": \"Exercising\",\n \"recordings\": [\n {\n \"ID\": 1727272665334,\n \"data\": {\n \"x\": [\n -1.064,\n -0.952,\n -0.776,\n -0.692,\n -0.984,\n -1.172,\n -1.18,\n -1.396,\n -1.876,\n -1.86,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.964,\n -1.664,\n -1.4,\n -1.096,\n -0.868,\n -0.716,\n -0.688,\n -0.692,\n -0.704,\n -0.716,\n -0.72,\n -0.772,\n -0.884,\n -0.944,\n -0.836,\n -0.74,\n -0.716,\n -0.8,\n -1.008,\n -0.976,\n -0.86,\n -0.932,\n -0.992,\n -1.024,\n -0.984,\n -1.292,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.896,\n -1.564,\n -1.232,\n -0.964,\n -0.836,\n -0.764,\n -0.768,\n -0.812,\n -0.892,\n -1.024,\n -1.132,\n -1.22,\n -1.248,\n -1.328,\n -1.236,\n -1.16,\n -0.96,\n -0.852,\n -0.856,\n -1.064,\n -1.236,\n -1.34,\n -1.676,\n -2.04,\n -2.04,\n -2.04\n ],\n \"y\": [\n 0.528,\n 0.392,\n 0.312,\n 0.32,\n 0.112,\n -0.292,\n -0.472,\n -0.668,\n -1.148,\n -1.38,\n -1.604,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.86,\n -1.912,\n -1.788,\n -1.732,\n -1.768,\n -1.88,\n -1.552,\n -1.196,\n -0.748,\n -0.296,\n -0.228,\n -0.208,\n -0.116,\n -0.036,\n 0.048,\n 0.148,\n 0.244,\n 0.288,\n 0.272,\n 0.236,\n 0.228,\n 0.232,\n 0.24,\n 0.312,\n 0.444,\n 0.512,\n 0.512,\n 0.512,\n 0.316,\n -0.052,\n -0.108,\n 0.056,\n -0.484,\n -1.408,\n -2.032,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.936,\n -2.04,\n -1.864,\n -1.52,\n -1.148,\n -0.72,\n -0.472,\n -0.336,\n -0.328,\n -0.26,\n -0.132,\n 0.064,\n 0.272,\n 0.608,\n 0.824,\n 0.548,\n 0.424,\n 0.584,\n 0.672,\n 0.552,\n 0.172,\n -0.028,\n -0.084,\n -0.128,\n -0.14,\n -0.284,\n -0.468,\n -0.68,\n -1.072\n ],\n \"z\": [\n 0.436,\n 0.308,\n 0.184,\n 0.228,\n 0.392,\n 0.26,\n 0.072,\n -0.328,\n -0.152,\n -0.232,\n -0.164,\n -0.02,\n -0.172,\n -0.648,\n -0.728,\n -0.7,\n -0.308,\n -0.016,\n 0.176,\n 0.328,\n 0.672,\n 0.92,\n 1.192,\n 1.384,\n 1.456,\n 1.348,\n 1.196,\n 1.064,\n 0.9,\n 0.812,\n 0.748,\n 0.716,\n 0.704,\n 0.672,\n 0.628,\n 0.544,\n 0.48,\n 0.448,\n 0.424,\n 0.404,\n 0.352,\n 0.336,\n 0.276,\n 0.304,\n 0.316,\n 0.168,\n -0.112,\n -0.156,\n 0.044,\n -0.132,\n -0.284,\n -0.58,\n -0.192,\n -0.272,\n -0.844,\n -0.896,\n -0.588,\n -0.064,\n 0.38,\n 0.352,\n 0.904,\n 1.408,\n 1.74,\n 1.808,\n 1.636,\n 1.46,\n 1.24,\n 1.024,\n 0.816,\n 0.668,\n 0.572,\n 0.676,\n 0.804,\n 0.92,\n 0.98,\n 0.932,\n 0.708,\n 0.72,\n 0.708,\n 0.652,\n 0.46,\n 0.184,\n -0.14,\n -0.2,\n -0.324,\n -0.448,\n -0.468,\n -0.46,\n -0.532\n ]\n }\n },\n {\n \"ID\": 1727272658417,\n \"data\": {\n \"x\": [\n 0.268,\n 0.236,\n 0.096,\n 0.016,\n -0.096,\n -0.144,\n -0.164,\n -0.532,\n -0.936,\n -2.04,\n -1.244,\n -0.868,\n -1.42,\n -1.308,\n -0.616,\n -0.256,\n 0.068,\n 0.444,\n 0.628,\n 0.984,\n 1.052,\n 0.984,\n 1.028,\n 0.916,\n 0.62,\n 0.62,\n 0.2,\n -0.432,\n -1.3,\n -2.04,\n -1.144,\n -1.312,\n -1.024,\n -0.812,\n -0.668,\n -0.16,\n 0.328,\n 0.448,\n 0.668,\n 1.396,\n 0.936,\n 0.952,\n 1.052,\n 1.04,\n 0.596,\n 0.24,\n 0.164,\n -0.244,\n -0.512,\n -1.288,\n -1.728,\n -1.628,\n -1.616,\n -0.792,\n -0.612,\n -0.088,\n 0.388,\n 0.648,\n 1.008,\n 1.612,\n 0.372,\n 1.26,\n 0.38,\n 1.216,\n 0.496,\n 0.264,\n 0.04,\n 0.12,\n -0.024,\n -0.52,\n -1.8,\n -1.672,\n -0.904,\n -0.484,\n -0.448,\n -0.108,\n 0.232,\n 0.36,\n 0.42,\n 0.288,\n 1.02,\n 0.472,\n 0.696,\n 0.376,\n 0.208,\n 0.064,\n -0.18,\n -0.26\n ],\n \"y\": [\n 1.152,\n 1.676,\n 0.884,\n 0.636,\n 0.012,\n -0.268,\n -0.564,\n -1.352,\n -1.904,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.68,\n -0.992,\n -0.528,\n -0.08,\n 0.896,\n 1.16,\n 1.356,\n 0.388,\n 0.348,\n 0.088,\n -0.172,\n -0.464,\n -1.12,\n -2.04,\n -2.016,\n -2.04,\n -2.04,\n -2.04,\n -1.888,\n -1.116,\n -0.644,\n -0.396,\n 0.168,\n 0.924,\n 1.304,\n 1.872,\n 0.444,\n 0.468,\n 0.196,\n 0.644,\n 0.332,\n -0.332,\n -1.128,\n -1.444,\n -1.928,\n -1.584,\n -2.04,\n -2.04,\n -1.304,\n -0.416,\n 0.132,\n 0.028,\n 0.292,\n 0.804,\n 0.984,\n 1.64,\n 1.848,\n 1.92,\n 0.608,\n 1.052,\n 0.344,\n -0.192,\n -1.22,\n -1.6,\n -1.644,\n -1.364,\n -1.764,\n -2.04,\n -2.04,\n -1.192,\n -0.436,\n -0.468,\n -0.532,\n -0.272,\n 0.096,\n 0.592,\n 0.656,\n 0.5,\n 0.156,\n -0.716,\n -0.936,\n -0.896,\n -0.936,\n -0.548\n ],\n \"z\": [\n 2.04,\n 1.74,\n 1.704,\n 1.532,\n 1.112,\n 0.944,\n 0.496,\n 0.008,\n 0.78,\n 1.056,\n -0.548,\n -1.228,\n -1.08,\n -0.348,\n -0.432,\n -0.14,\n 0.496,\n 1.432,\n 2.04,\n 2.04,\n 1.996,\n 1.836,\n 2.04,\n 2.024,\n 1.496,\n 0.336,\n -0.472,\n -0.58,\n 0.524,\n 0.196,\n -1.928,\n -1.62,\n -0.992,\n -0.468,\n 0.032,\n 0.572,\n 1.536,\n 2.04,\n 2.04,\n 1.6,\n 1.58,\n 2.04,\n 2.04,\n 2.04,\n 1.768,\n 1.388,\n 0.34,\n -0.444,\n -0.592,\n 1.776,\n 0.04,\n -1.116,\n -1.068,\n -0.876,\n -0.48,\n 0.052,\n 0.44,\n 1.772,\n 2.04,\n 2.04,\n 0.94,\n -0.36,\n 1.66,\n 2.04,\n 2.04,\n 2.04,\n 1.916,\n 0.824,\n 0.492,\n 1.104,\n 0.248,\n -1.712,\n -1.664,\n -1.436,\n -0.88,\n -0.372,\n 0.288,\n 1.028,\n 1.812,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 1.964,\n 1.388,\n 0.66\n ]\n }\n },\n {\n \"ID\": 1727272638820,\n \"data\": {\n \"x\": [\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.82,\n -1.552,\n -1.416,\n -1.34,\n -1.26,\n -1.196,\n -1.164,\n -1.096,\n -1.004,\n -0.924,\n -0.84,\n -0.772,\n -0.768,\n -0.916,\n -0.952,\n -1.144,\n -1.352,\n -1.72,\n -1.984,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.912,\n -1.696,\n -1.472,\n -1.296,\n -1.08,\n -0.856,\n -0.648,\n -0.504,\n -0.512,\n -0.496,\n -0.476,\n -0.484,\n -0.504,\n -0.54,\n -0.608,\n -0.708,\n -0.904,\n -1.324,\n -1.804,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.876,\n -1.64,\n -1.484,\n -1.292,\n -1.14,\n -0.976,\n -0.868,\n -0.788,\n -0.712,\n -0.672,\n -0.66,\n -0.644,\n -0.816,\n -0.916,\n -0.996,\n -1.14,\n -1.284,\n -1.416,\n -1.54,\n -1.736,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04\n ],\n \"y\": [\n -0.444,\n -0.536,\n -0.504,\n -0.408,\n -0.572,\n -0.752,\n -0.94,\n -0.868,\n -0.456,\n -0.296,\n -0.276,\n -0.344,\n -0.4,\n -0.488,\n -0.544,\n -0.584,\n -0.608,\n -0.64,\n -0.74,\n -0.984,\n -1.096,\n -1.076,\n -0.92,\n -0.864,\n -0.784,\n -0.688,\n -0.572,\n -0.432,\n -0.252,\n -0.132,\n -0.068,\n -0.092,\n -0.036,\n -0.056,\n -0.116,\n -0.172,\n -0.12,\n -0.112,\n 0.012,\n 0.036,\n 0.196,\n 0.34,\n 0.4,\n 0.34,\n 0.328,\n 0.34,\n 0.288,\n 0.184,\n 0.096,\n 0.024,\n 0.024,\n 0.02,\n 0.02,\n -0.064,\n -0.112,\n -0.208,\n -0.336,\n -0.384,\n -0.5,\n -0.712,\n -0.984,\n -0.944,\n -0.832,\n -0.656,\n -0.512,\n -0.464,\n -0.484,\n -0.472,\n -0.452,\n -0.448,\n -0.468,\n -0.536,\n -0.688,\n -0.884,\n -0.916,\n -0.912,\n -0.896,\n -0.768,\n -0.632,\n -0.492,\n -0.36,\n -0.28,\n -0.292,\n -0.336,\n -0.36,\n -0.332,\n -0.216,\n -0.384\n ],\n \"z\": [\n 0.712,\n 0.676,\n 0.748,\n 0.712,\n 0.636,\n 0.428,\n 0.172,\n 0.296,\n 0.068,\n -0.02,\n -0.044,\n -0.032,\n 0.016,\n 0.052,\n 0.092,\n 0.056,\n 0,\n -0.028,\n -0.128,\n -0.276,\n -0.288,\n -0.292,\n -0.308,\n -0.22,\n -0.116,\n -0.064,\n -0.012,\n 0.028,\n 0.004,\n -0.056,\n -0.02,\n 0.12,\n 0.128,\n 0.096,\n 0.128,\n 0.168,\n 0.16,\n 0.144,\n 0.072,\n 0.096,\n 0.028,\n -0.04,\n -0.068,\n -0.08,\n -0.032,\n -0.02,\n -0.008,\n -0.048,\n -0.076,\n -0.108,\n -0.112,\n -0.072,\n -0.044,\n 0.052,\n 0.112,\n 0.272,\n 0.388,\n 0.46,\n 0.464,\n 0.28,\n 0.256,\n 0.16,\n 0.24,\n 0.236,\n 0.2,\n 0.192,\n 0.188,\n 0.136,\n -0.004,\n -0.024,\n -0.048,\n -0.092,\n -0.128,\n -0.228,\n -0.176,\n -0.172,\n -0.1,\n -0.06,\n -0.028,\n -0.064,\n -0.06,\n -0.036,\n -0.024,\n 0.044,\n 0.056,\n 0.168,\n 0.16,\n 0.172\n ]\n }\n },\n {\n \"ID\": 1727272603693,\n \"data\": {\n \"x\": [\n -1.144,\n -0.948,\n -0.888,\n -0.82,\n -0.74,\n -0.768,\n -0.924,\n -1.196,\n -1.48,\n -1.324,\n -1.044,\n -0.796,\n -0.668,\n -0.504,\n -0.356,\n -0.188,\n -0.008,\n 0.244,\n 0.508,\n 0.6,\n 0.5,\n 0.388,\n 0.292,\n 0.124,\n -0.164,\n -0.404,\n -0.868,\n -1.356,\n -1.556,\n -1.62,\n -1.348,\n -1.216,\n -1.02,\n -0.956,\n -0.944,\n -0.872,\n -0.84,\n -0.776,\n -0.752,\n -0.812,\n -0.956,\n -1.072,\n -1.316,\n -1.632,\n -1.84,\n -1.756,\n -1.42,\n -1.076,\n -0.868,\n -0.684,\n -0.508,\n -0.268,\n -0.052,\n 0.176,\n 0.336,\n 0.376,\n 0.26,\n 0.128,\n -0.024,\n -0.216,\n -0.48,\n -0.792,\n -0.904,\n -1.16,\n -1.276,\n -1.276,\n -1.228,\n -1.16,\n -1.28,\n -1.364,\n -1.08,\n -0.924,\n -0.856,\n -0.876,\n -0.984,\n -0.996,\n -1.052,\n -1.492,\n -1.66,\n -1.424,\n -2.04,\n -1.744,\n -1.22,\n -0.74,\n -0.424,\n -0.196,\n 0.016,\n 0.256,\n 0.52\n ],\n \"y\": [\n -0.24,\n 0.188,\n 0.496,\n 0.448,\n 0.184,\n -0.128,\n -0.492,\n -0.964,\n -1.396,\n -1.644,\n -1.756,\n -1.708,\n -1.728,\n -1.672,\n -1.368,\n -1.132,\n -1,\n -0.904,\n -1.028,\n -1.112,\n -1.092,\n -0.992,\n -0.88,\n -0.952,\n -1.16,\n -1.532,\n -2.04,\n -2.04,\n -2.04,\n -2.032,\n -1.412,\n -0.936,\n -0.596,\n -0.452,\n -0.348,\n -0.276,\n -0.144,\n 0.128,\n 0.352,\n 0.316,\n 0.1,\n -0.064,\n -0.34,\n -0.9,\n -1.452,\n -1.712,\n -1.732,\n -1.504,\n -1.352,\n -1.368,\n -1.288,\n -1.132,\n -0.988,\n -0.908,\n -0.928,\n -0.888,\n -0.912,\n -1.008,\n -1.168,\n -1.288,\n -1.412,\n -1.548,\n -1.74,\n -2.04,\n -2.04,\n -2.04,\n -1.724,\n -1.056,\n -0.38,\n 0.032,\n 0.292,\n 0.496,\n 0.632,\n 0.556,\n 0.296,\n 0.012,\n -0.248,\n -0.688,\n -1.204,\n -1.764,\n -2.04,\n -2.04,\n -1.788,\n -1.688,\n -1.9,\n -1.876,\n -1.636,\n -1.376,\n -1.212\n ],\n \"z\": [\n -0.632,\n -0.664,\n -0.516,\n -0.34,\n -0.192,\n -0.176,\n -0.176,\n -0.216,\n -0.204,\n -0.564,\n -0.892,\n -0.972,\n -0.768,\n -0.572,\n -0.44,\n -0.3,\n -0.224,\n -0.16,\n -0.012,\n 0.168,\n 0.224,\n 0.176,\n 0.092,\n 0.012,\n -0.076,\n -0.116,\n 0.064,\n 0.536,\n 0.404,\n 0.224,\n 0.148,\n 0.144,\n 0.152,\n 0.072,\n 0.02,\n -0.06,\n -0.108,\n -0.14,\n -0.092,\n -0.104,\n -0.128,\n -0.18,\n -0.12,\n -0.096,\n -0.204,\n -0.424,\n -0.64,\n -0.712,\n -0.624,\n -0.528,\n -0.476,\n -0.464,\n -0.376,\n -0.244,\n -0.144,\n -0.06,\n -0.032,\n 0,\n -0.008,\n -0.036,\n -0.004,\n 0.02,\n -0.024,\n 0.016,\n 0.128,\n 0.112,\n -0.024,\n -0.172,\n -0.028,\n 0.112,\n 0.036,\n -0.096,\n -0.216,\n -0.2,\n -0.072,\n 0.04,\n 0.004,\n 0.256,\n 0.372,\n 0.124,\n 0.208,\n 0.12,\n -0.072,\n -0.076,\n 0.096,\n 0.036,\n -0.152,\n -0.208,\n -0.308\n ]\n }\n },\n {\n \"ID\": 1727272585713,\n \"data\": {\n \"x\": [\n -2.04,\n -2.04,\n -1.612,\n -1.492,\n -1.368,\n -1.344,\n -0.848,\n -0.78,\n -0.472,\n -0.624,\n -0.592,\n -0.612,\n -0.504,\n -0.508,\n -0.468,\n -0.284,\n -0.324,\n -0.776,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.984,\n -1.912,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.976,\n -1.796,\n -1.708,\n -1.62,\n -1.576,\n -1.692,\n -1.472,\n -1.376,\n -1.192,\n -0.992,\n -0.784,\n -0.748,\n -0.58,\n -0.492,\n -1.06,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.952,\n -2.04,\n -2.036,\n -2.04,\n -1.992,\n -1.952,\n -1.928,\n -1.904,\n -1.952,\n -2.02,\n -2.04,\n -2.024,\n -1.916,\n -1.668,\n -1.296,\n -0.764,\n -0.4,\n -0.18,\n 0,\n -0.168,\n -0.596,\n -1.764,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04\n ],\n \"y\": [\n -1.064,\n -0.612,\n -0.376,\n -0.22,\n -0.004,\n 0.612,\n 0.936,\n -0.144,\n 0.008,\n 1.456,\n 1.9,\n 1.516,\n 1.272,\n 0.988,\n 0.748,\n 0.752,\n 0.984,\n 0.864,\n 0.152,\n -1.26,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.52,\n -1,\n -0.588,\n -0.188,\n 0.2,\n 0.436,\n 0.928,\n 1.048,\n 0.34,\n 1.4,\n 2.04,\n 1.52,\n 1.216,\n 1.316,\n 1.544,\n 1.4,\n 0.776,\n -0.088,\n 0.212,\n -1.304,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -1.716,\n -1.056,\n -0.612,\n -0.276,\n -0.18,\n -0.24,\n -0.02,\n 0.292,\n 0.692,\n 0.776,\n 0.912,\n 1.176,\n 1.316,\n 1.08,\n 1.06,\n 1.332,\n 1.472,\n 1.548,\n 1.232,\n 0.46,\n -1.088,\n -1.892,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04,\n -2.04\n ],\n \"z\": [\n 0.88,\n 0.664,\n 0.34,\n 0.308,\n 0.464,\n 0.976,\n 1.3,\n 1.268,\n 1.136,\n 1.32,\n 1.372,\n 1.196,\n 0.868,\n 0.716,\n 0.548,\n 0.348,\n 0.368,\n 0.764,\n 1.364,\n 1.06,\n 0.88,\n 0.48,\n -0.856,\n -1.98,\n -2.04,\n -2.04,\n -2.04,\n -1.576,\n -0.652,\n 0.304,\n 0.784,\n 0.932,\n 1.024,\n 0.932,\n 0.74,\n 0.736,\n 0.728,\n 0.744,\n 0.984,\n 1.26,\n 1.204,\n 1.112,\n 1.264,\n 1.096,\n 0.988,\n 0.936,\n 0.784,\n 0.92,\n 1.348,\n 1.488,\n 2.04,\n 2.04,\n 2.04,\n 2.04,\n 0.264,\n -0.068,\n 1.112,\n 1.468,\n 1.332,\n 1.348,\n 1.852,\n 2.04,\n 2.04,\n 1.904,\n 1.66,\n 1.26,\n 0.976,\n 0.752,\n 0.82,\n 0.848,\n 0.772,\n 0.62,\n 0.456,\n 0.312,\n 0.324,\n 0.468,\n 0.616,\n 0.608,\n 0.524,\n 0.672,\n 1.26,\n 0.088,\n 1.036,\n 2.04,\n 0.764,\n -1.112,\n -1.716,\n -0.876,\n -0.972\n ]\n }\n }\n ]\n },\n {\n \"icon\": \"Asleep\",\n \"ID\": 1727272691910,\n \"name\": \"Not exercising\",\n \"recordings\": [\n {\n \"ID\": 1727272846488,\n \"data\": {\n \"x\": [\n -0.296,\n -0.296,\n -0.3,\n -0.3,\n -0.288,\n -0.296,\n -0.304,\n -0.316,\n -0.304,\n -0.3,\n -0.3,\n -0.304,\n -0.3,\n -0.3,\n -0.304,\n -0.296,\n -0.296,\n -0.292,\n -0.3,\n -0.304,\n -0.304,\n -0.304,\n -0.308,\n -0.304,\n -0.304,\n -0.308,\n -0.304,\n -0.312,\n -0.308,\n -0.312,\n -0.316,\n -0.312,\n -0.304,\n -0.308,\n -0.304,\n -0.312,\n -0.304,\n -0.312,\n -0.304,\n -0.3,\n -0.304,\n -0.292,\n -0.304,\n -0.296,\n -0.3,\n -0.304,\n -0.3,\n -0.3,\n -0.296,\n -0.3,\n -0.296,\n -0.304,\n -0.304,\n -0.308,\n -0.308,\n -0.308,\n -0.3,\n -0.304,\n -0.308,\n -0.308,\n -0.304,\n -0.316,\n -0.308,\n -0.304,\n -0.312,\n -0.296,\n -0.304,\n -0.304,\n -0.304,\n -0.304,\n -0.3,\n -0.3,\n -0.296,\n -0.292,\n -0.296,\n -0.3,\n -0.296,\n -0.304,\n -0.3,\n -0.292,\n -0.284,\n -0.304,\n -0.292,\n -0.304,\n -0.292,\n -0.3,\n -0.308,\n -0.312\n ],\n \"y\": [\n 0.98,\n 0.992,\n 1,\n 0.976,\n 0.952,\n 0.964,\n 0.972,\n 0.98,\n 0.972,\n 0.972,\n 0.98,\n 0.984,\n 0.976,\n 0.984,\n 0.98,\n 0.972,\n 0.964,\n 0.972,\n 0.976,\n 0.98,\n 0.964,\n 0.98,\n 0.98,\n 0.988,\n 0.988,\n 0.988,\n 0.984,\n 0.984,\n 0.976,\n 0.98,\n 0.972,\n 0.984,\n 0.984,\n 0.996,\n 0.984,\n 0.976,\n 0.976,\n 0.98,\n 0.984,\n 0.976,\n 0.964,\n 0.984,\n 0.98,\n 0.976,\n 0.976,\n 0.98,\n 0.976,\n 0.98,\n 0.988,\n 0.98,\n 0.98,\n 0.98,\n 0.996,\n 0.976,\n 0.976,\n 0.976,\n 0.968,\n 0.98,\n 0.968,\n 0.972,\n 0.992,\n 0.984,\n 0.976,\n 0.984,\n 0.992,\n 0.996,\n 0.98,\n 0.972,\n 0.98,\n 0.976,\n 0.976,\n 0.984,\n 0.984,\n 0.976,\n 0.972,\n 0.976,\n 0.976,\n 0.992,\n 0.972,\n 0.964,\n 0.972,\n 0.988,\n 1,\n 0.996,\n 0.992,\n 0.98,\n 0.984,\n 0.972\n ],\n \"z\": [\n -0.08,\n -0.092,\n -0.092,\n -0.096,\n -0.096,\n -0.092,\n -0.096,\n -0.104,\n -0.092,\n -0.096,\n -0.096,\n -0.088,\n -0.096,\n -0.088,\n -0.096,\n -0.092,\n -0.096,\n -0.1,\n -0.096,\n -0.084,\n -0.1,\n -0.084,\n -0.092,\n -0.08,\n -0.072,\n -0.084,\n -0.084,\n -0.088,\n -0.084,\n -0.084,\n -0.08,\n -0.076,\n -0.084,\n -0.092,\n -0.084,\n -0.088,\n -0.08,\n -0.092,\n -0.076,\n -0.092,\n -0.092,\n -0.1,\n -0.092,\n -0.088,\n -0.092,\n -0.088,\n -0.084,\n -0.092,\n -0.092,\n -0.088,\n -0.072,\n -0.092,\n -0.092,\n -0.092,\n -0.084,\n -0.084,\n -0.08,\n -0.092,\n -0.092,\n -0.088,\n -0.08,\n -0.096,\n -0.092,\n -0.084,\n -0.088,\n -0.092,\n -0.096,\n -0.088,\n -0.092,\n -0.096,\n -0.096,\n -0.096,\n -0.096,\n -0.1,\n -0.088,\n -0.1,\n -0.096,\n -0.1,\n -0.1,\n -0.092,\n -0.1,\n -0.108,\n -0.084,\n -0.092,\n -0.084,\n -0.092,\n -0.104,\n -0.08\n ]\n }\n },\n {\n \"ID\": 1727272840320,\n \"data\": {\n \"x\": [\n 0.256,\n 0.256,\n 0.252,\n 0.256,\n 0.26,\n 0.256,\n 0.252,\n 0.256,\n 0.256,\n 0.252,\n 0.252,\n 0.252,\n 0.252,\n 0.256,\n 0.264,\n 0.26,\n 0.252,\n 0.252,\n 0.264,\n 0.256,\n 0.256,\n 0.244,\n 0.248,\n 0.256,\n 0.256,\n 0.256,\n 0.264,\n 0.256,\n 0.248,\n 0.264,\n 0.256,\n 0.252,\n 0.248,\n 0.248,\n 0.248,\n 0.268,\n 0.268,\n 0.264,\n 0.252,\n 0.256,\n 0.256,\n 0.256,\n 0.252,\n 0.252,\n 0.252,\n 0.252,\n 0.252,\n 0.256,\n 0.256,\n 0.256,\n 0.248,\n 0.256,\n 0.252,\n 0.26,\n 0.248,\n 0.252,\n 0.252,\n 0.256,\n 0.256,\n 0.256,\n 0.248,\n 0.256,\n 0.252,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.256,\n 0.244,\n 0.252,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.248,\n 0.248,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.248,\n 0.252,\n 0.248,\n 0.252,\n 0.252,\n 0.252\n ],\n \"y\": [\n -0.852,\n -0.848,\n -0.856,\n -0.856,\n -0.848,\n -0.856,\n -0.848,\n -0.86,\n -0.868,\n -0.856,\n -0.86,\n -0.852,\n -0.86,\n -0.864,\n -0.856,\n -0.852,\n -0.852,\n -0.848,\n -0.844,\n -0.86,\n -0.844,\n -0.848,\n -0.852,\n -0.852,\n -0.86,\n -0.86,\n -0.856,\n -0.852,\n -0.856,\n -0.848,\n -0.852,\n -0.856,\n -0.848,\n -0.844,\n -0.84,\n -0.852,\n -0.86,\n -0.868,\n -0.872,\n -0.868,\n -0.856,\n -0.852,\n -0.848,\n -0.852,\n -0.844,\n -0.848,\n -0.848,\n -0.848,\n -0.86,\n -0.856,\n -0.864,\n -0.86,\n -0.856,\n -0.852,\n -0.848,\n -0.856,\n -0.852,\n -0.856,\n -0.848,\n -0.872,\n -0.86,\n -0.856,\n -0.856,\n -0.856,\n -0.86,\n -0.856,\n -0.852,\n -0.856,\n -0.864,\n -0.856,\n -0.852,\n -0.86,\n -0.852,\n -0.852,\n -0.856,\n -0.856,\n -0.864,\n -0.86,\n -0.852,\n -0.86,\n -0.852,\n -0.856,\n -0.856,\n -0.856,\n -0.86,\n -0.852,\n -0.86,\n -0.852,\n -0.868\n ],\n \"z\": [\n -0.488,\n -0.476,\n -0.48,\n -0.476,\n -0.472,\n -0.48,\n -0.48,\n -0.484,\n -0.476,\n -0.48,\n -0.488,\n -0.488,\n -0.484,\n -0.48,\n -0.48,\n -0.476,\n -0.48,\n -0.476,\n -0.476,\n -0.476,\n -0.476,\n -0.472,\n -0.484,\n -0.476,\n -0.476,\n -0.488,\n -0.48,\n -0.488,\n -0.484,\n -0.484,\n -0.48,\n -0.484,\n -0.488,\n -0.48,\n -0.472,\n -0.476,\n -0.48,\n -0.472,\n -0.488,\n -0.48,\n -0.476,\n -0.488,\n -0.484,\n -0.484,\n -0.48,\n -0.468,\n -0.476,\n -0.484,\n -0.476,\n -0.472,\n -0.476,\n -0.484,\n -0.484,\n -0.48,\n -0.484,\n -0.48,\n -0.476,\n -0.48,\n -0.48,\n -0.48,\n -0.472,\n -0.484,\n -0.476,\n -0.484,\n -0.488,\n -0.472,\n -0.472,\n -0.48,\n -0.476,\n -0.48,\n -0.48,\n -0.488,\n -0.484,\n -0.48,\n -0.488,\n -0.476,\n -0.48,\n -0.472,\n -0.484,\n -0.48,\n -0.48,\n -0.472,\n -0.476,\n -0.476,\n -0.476,\n -0.48,\n -0.472,\n -0.476,\n -0.48\n ]\n }\n },\n {\n \"ID\": 1727272790047,\n \"data\": {\n \"x\": [\n -1.056,\n -1.056,\n -1.06,\n -1.06,\n -1.052,\n -1.052,\n -1.048,\n -1.056,\n -1.048,\n -1.056,\n -1.052,\n -1.044,\n -1.048,\n -1.048,\n -1.056,\n -1.06,\n -1.052,\n -1.056,\n -1.052,\n -1.052,\n -1.06,\n -1.06,\n -1.056,\n -1.064,\n -1.048,\n -1.044,\n -1.044,\n -1.048,\n -1.056,\n -1.056,\n -1.06,\n -1.044,\n -1.052,\n -1.052,\n -1.056,\n -1.052,\n -1.056,\n -1.052,\n -1.052,\n -1.06,\n -1.044,\n -1.048,\n -1.048,\n -1.056,\n -1.052,\n -1.044,\n -1.048,\n -1.06,\n -1.048,\n -1.052,\n -1.056,\n -1.06,\n -1.056,\n -1.06,\n -1.06,\n -1.056,\n -1.064,\n -1.06,\n -1.052,\n -1.044,\n -1.052,\n -1.052,\n -1.06,\n -1.052,\n -1.056,\n -1.056,\n -1.056,\n -1.056,\n -1.056,\n -1.056,\n -1.06,\n -1.06,\n -1.06,\n -1.048,\n -1.06,\n -1.056,\n -1.052,\n -1.06,\n -1.052,\n -1.052,\n -1.056,\n -1.056,\n -1.056,\n -1.06,\n -1.048,\n -1.056,\n -1.056,\n -1.048,\n -1.064\n ],\n \"y\": [\n -0.144,\n -0.152,\n -0.148,\n -0.148,\n -0.144,\n -0.168,\n -0.152,\n -0.164,\n -0.152,\n -0.152,\n -0.156,\n -0.144,\n -0.152,\n -0.14,\n -0.16,\n -0.144,\n -0.148,\n -0.144,\n -0.148,\n -0.144,\n -0.148,\n -0.144,\n -0.144,\n -0.164,\n -0.144,\n -0.152,\n -0.156,\n -0.144,\n -0.144,\n -0.144,\n -0.144,\n -0.14,\n -0.136,\n -0.152,\n -0.144,\n -0.164,\n -0.148,\n -0.16,\n -0.148,\n -0.16,\n -0.156,\n -0.14,\n -0.14,\n -0.14,\n -0.144,\n -0.144,\n -0.136,\n -0.144,\n -0.144,\n -0.144,\n -0.148,\n -0.152,\n -0.148,\n -0.14,\n -0.16,\n -0.156,\n -0.152,\n -0.148,\n -0.152,\n -0.144,\n -0.14,\n -0.14,\n -0.144,\n -0.14,\n -0.144,\n -0.148,\n -0.16,\n -0.156,\n -0.152,\n -0.152,\n -0.144,\n -0.148,\n -0.144,\n -0.144,\n -0.148,\n -0.14,\n -0.136,\n -0.14,\n -0.156,\n -0.156,\n -0.14,\n -0.144,\n -0.144,\n -0.144,\n -0.148,\n -0.14,\n -0.144,\n -0.144,\n -0.14\n ],\n \"z\": [\n 0.032,\n 0.036,\n 0.032,\n 0.02,\n 0.032,\n 0.024,\n 0.024,\n 0.032,\n 0.036,\n 0.028,\n 0.036,\n 0.04,\n 0.028,\n 0.032,\n 0.032,\n 0.036,\n 0.032,\n 0.024,\n 0.024,\n 0.028,\n 0.028,\n 0.032,\n 0.024,\n 0.04,\n 0.036,\n 0.032,\n 0.028,\n 0.032,\n 0.028,\n 0.028,\n 0.028,\n 0.028,\n 0.02,\n 0.032,\n 0.032,\n 0.028,\n 0.036,\n 0.04,\n 0.028,\n 0.032,\n 0.024,\n 0.02,\n 0.02,\n 0.02,\n 0.032,\n 0.02,\n 0.024,\n 0.024,\n 0.024,\n 0.028,\n 0.024,\n 0.024,\n 0.032,\n 0.028,\n 0.024,\n 0.024,\n 0.02,\n 0.024,\n 0.024,\n 0.016,\n 0.028,\n 0.024,\n 0.028,\n 0.032,\n 0.028,\n 0.028,\n 0.028,\n 0.028,\n 0.028,\n 0.024,\n 0.02,\n 0.024,\n 0.028,\n 0.024,\n 0.024,\n 0.02,\n 0.028,\n 0.016,\n 0.024,\n 0.024,\n 0.024,\n 0.02,\n 0.024,\n 0.028,\n 0.024,\n 0.028,\n 0.02,\n 0.024,\n 0.02\n ]\n }\n },\n {\n \"ID\": 1727272784043,\n \"data\": {\n \"x\": [\n 0.008,\n 0.008,\n 0.012,\n 0.008,\n 0.004,\n 0.004,\n 0.004,\n -0.004,\n 0.004,\n 0.004,\n 0.004,\n -0.004,\n 0,\n -0.004,\n 0,\n 0,\n 0,\n 0,\n 0.004,\n 0.008,\n -0.004,\n 0.004,\n 0,\n 0,\n 0.004,\n 0,\n 0.008,\n 0.004,\n 0.004,\n 0.004,\n 0.004,\n 0.004,\n 0.008,\n 0.004,\n 0.008,\n 0.004,\n 0.004,\n 0.008,\n 0.008,\n 0.012,\n 0.008,\n 0.008,\n 0.004,\n 0.008,\n 0.004,\n 0,\n 0,\n 0.004,\n 0.004,\n 0,\n 0.004,\n 0,\n 0.004,\n 0,\n 0.004,\n 0.004,\n 0.008,\n 0.004,\n 0.008,\n 0.016,\n 0.008,\n 0.012,\n 0.004,\n 0.012,\n 0.008,\n 0.008,\n 0.008,\n 0.012,\n 0.004,\n 0.012,\n 0.004,\n 0.004,\n 0.004,\n 0.012,\n 0.008,\n 0.008,\n 0.008,\n 0.008,\n 0.016,\n 0.012,\n 0.004,\n 0.016,\n 0,\n 0.004,\n 0.008,\n 0.004,\n 0,\n 0.004,\n 0.016\n ],\n \"y\": [\n -0.952,\n -0.948,\n -0.952,\n -0.956,\n -0.968,\n -0.952,\n -0.948,\n -0.956,\n -0.952,\n -0.944,\n -0.96,\n -0.96,\n -0.972,\n -0.956,\n -0.956,\n -0.952,\n -0.968,\n -0.96,\n -0.96,\n -0.968,\n -0.956,\n -0.96,\n -0.944,\n -0.948,\n -0.944,\n -0.944,\n -0.952,\n -0.956,\n -0.952,\n -0.956,\n -0.96,\n -0.952,\n -0.96,\n -0.952,\n -0.948,\n -0.936,\n -0.944,\n -0.948,\n -0.94,\n -0.952,\n -0.948,\n -0.936,\n -0.944,\n -0.948,\n -0.956,\n -0.952,\n -0.952,\n -0.968,\n -0.964,\n -0.96,\n -0.964,\n -0.956,\n -0.956,\n -0.948,\n -0.96,\n -0.956,\n -0.96,\n -0.964,\n -0.956,\n -0.956,\n -0.948,\n -0.944,\n -0.948,\n -0.94,\n -0.952,\n -0.956,\n -0.956,\n -0.956,\n -0.96,\n -0.952,\n -0.956,\n -0.952,\n -0.952,\n -0.952,\n -0.956,\n -0.952,\n -0.956,\n -0.96,\n -0.96,\n -0.96,\n -0.968,\n -0.964,\n -0.968,\n -0.956,\n -0.944,\n -0.944,\n -0.948,\n -0.952,\n -0.944\n ],\n \"z\": [\n 0.284,\n 0.276,\n 0.268,\n 0.284,\n 0.276,\n 0.276,\n 0.276,\n 0.264,\n 0.272,\n 0.26,\n 0.272,\n 0.276,\n 0.28,\n 0.276,\n 0.268,\n 0.276,\n 0.272,\n 0.28,\n 0.26,\n 0.272,\n 0.272,\n 0.272,\n 0.268,\n 0.268,\n 0.268,\n 0.268,\n 0.272,\n 0.268,\n 0.276,\n 0.272,\n 0.276,\n 0.272,\n 0.26,\n 0.28,\n 0.28,\n 0.268,\n 0.276,\n 0.272,\n 0.264,\n 0.276,\n 0.268,\n 0.26,\n 0.264,\n 0.26,\n 0.264,\n 0.272,\n 0.264,\n 0.264,\n 0.268,\n 0.268,\n 0.26,\n 0.268,\n 0.268,\n 0.268,\n 0.272,\n 0.276,\n 0.28,\n 0.268,\n 0.268,\n 0.256,\n 0.256,\n 0.252,\n 0.248,\n 0.256,\n 0.252,\n 0.264,\n 0.244,\n 0.256,\n 0.264,\n 0.264,\n 0.264,\n 0.248,\n 0.264,\n 0.256,\n 0.252,\n 0.256,\n 0.248,\n 0.256,\n 0.248,\n 0.244,\n 0.244,\n 0.252,\n 0.252,\n 0.256,\n 0.256,\n 0.252,\n 0.248,\n 0.244,\n 0.252\n ]\n }\n },\n {\n \"ID\": 1727272755599,\n \"data\": {\n \"x\": [\n -0.048,\n -0.052,\n -0.048,\n -0.048,\n -0.048,\n -0.052,\n -0.044,\n -0.048,\n -0.048,\n -0.052,\n -0.048,\n -0.048,\n -0.048,\n -0.048,\n -0.044,\n -0.044,\n -0.052,\n -0.048,\n -0.048,\n -0.048,\n -0.04,\n -0.044,\n -0.048,\n -0.048,\n -0.048,\n -0.044,\n -0.052,\n -0.04,\n -0.04,\n -0.048,\n -0.052,\n -0.044,\n -0.052,\n -0.052,\n -0.044,\n -0.036,\n -0.044,\n -0.044,\n -0.044,\n -0.052,\n -0.044,\n -0.048,\n -0.052,\n -0.052,\n -0.056,\n -0.036,\n -0.044,\n -0.04,\n -0.048,\n -0.048,\n -0.056,\n -0.044,\n -0.044,\n -0.048,\n -0.044,\n -0.052,\n -0.052,\n -0.048,\n -0.052,\n -0.052,\n -0.044,\n -0.044,\n -0.04,\n -0.048,\n -0.04,\n -0.044,\n -0.044,\n -0.056,\n -0.044,\n -0.048,\n -0.048,\n -0.044,\n -0.052,\n -0.048,\n -0.052,\n -0.044,\n -0.052,\n -0.048,\n -0.048,\n -0.052,\n -0.048,\n -0.052,\n -0.044,\n -0.052,\n -0.052,\n -0.044,\n -0.052,\n -0.044\n ],\n \"y\": [\n -0.352,\n -0.336,\n -0.356,\n -0.34,\n -0.348,\n -0.348,\n -0.344,\n -0.356,\n -0.344,\n -0.348,\n -0.356,\n -0.348,\n -0.344,\n -0.336,\n -0.356,\n -0.348,\n -0.344,\n -0.34,\n -0.356,\n -0.348,\n -0.352,\n -0.348,\n -0.34,\n -0.352,\n -0.352,\n -0.348,\n -0.34,\n -0.352,\n -0.352,\n -0.344,\n -0.348,\n -0.356,\n -0.34,\n -0.344,\n -0.344,\n -0.352,\n -0.344,\n -0.344,\n -0.356,\n -0.344,\n -0.344,\n -0.348,\n -0.344,\n -0.348,\n -0.348,\n -0.348,\n -0.344,\n -0.34,\n -0.34,\n -0.348,\n -0.352,\n -0.348,\n -0.344,\n -0.352,\n -0.348,\n -0.34,\n -0.348,\n -0.34,\n -0.344,\n -0.34,\n -0.344,\n -0.36,\n -0.344,\n -0.348,\n -0.344,\n -0.352,\n -0.348,\n -0.344,\n -0.344,\n -0.332,\n -0.352,\n -0.352,\n -0.348,\n -0.344,\n -0.34,\n -0.348,\n -0.356,\n -0.352,\n -0.348,\n -0.352,\n -0.348,\n -0.344,\n -0.34,\n -0.356,\n -0.356,\n -0.348,\n -0.34,\n -0.344\n ],\n \"z\": [\n -1.032,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.028,\n -1.028,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.032,\n -1.028,\n -1.032,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.032,\n -1.024,\n -1.024,\n -1.02,\n -1.032,\n -1.02,\n -1.024,\n -1.028,\n -1.028,\n -1.024,\n -1.02,\n -1.028,\n -1.02,\n -1.02,\n -1.028,\n -1.028,\n -1.02,\n -1.024,\n -1.04,\n -1.024,\n -1.032,\n -1.028,\n -1.02,\n -1.024,\n -1.032,\n -1.036,\n -1.024,\n -1.02,\n -1.028,\n -1.028,\n -1.024,\n -1.024,\n -1.032,\n -1.032,\n -1.028,\n -1.028,\n -1.024,\n -1.024,\n -1.024,\n -1.02,\n -1.024,\n -1.02,\n -1.024,\n -1.024,\n -1.028,\n -1.032,\n -1.028,\n -1.036,\n -1.024,\n -1.032,\n -1.016,\n -1.032,\n -1.028,\n -1.036,\n -1.02,\n -1.032,\n -1.02,\n -1.02,\n -1.028,\n -1.032,\n -1.028,\n -1.02,\n -1.028,\n -1.024,\n -1.028,\n -1.024,\n -1.024,\n -1.032,\n -1.036,\n -1.028\n ]\n }\n }\n ]\n }\n ]\n}", - // "main.blocks": "exercising-timenot-exercising-timeunknown-timeexercising-time0not-exercising-time0ml.event.Exercisingdurationexercising-time1durationButton.A0DIVIDE0exercising-time1000ml.event.NotExercisingdurationnot-exercising-time1durationButton.B0DIVIDE0not-exercising-time1000", - // "main.ts": "ml.onStopDetailed(ml.event.Exercising, function (duration) {\n basic.clearScreen()\n exercisingtime += duration\n})\ninput.onButtonPressed(Button.A, function () {\n basic.showNumber(exercisingtime / 1000)\n})\ninput.onButtonPressed(Button.B, function () {\n basic.showNumber(notexercisingtime / 1000)\n})\nml.onStopDetailed(ml.event.NotExercising, function (duration) {\n basic.clearScreen()\n notexercisingtime += duration\n})\nlet notexercisingtime = 0\nlet exercisingtime = 0\nexercisingtime = 0\nnotexercisingtime = 0\n", - // "pxt.json": "{\n \"name\": \"Simple AI exercise timer\",\n \"description\": \"\",\n \"dependencies\": {\n \"core\": \"*\",\n \"microphone\": \"*\",\n \"radio\": \"*\",\n \"machine-learning\": \"github:microbit-foundation/pxt-microbit-ml#v0.4.3\"\n },\n \"files\": [\n \"main.ts\",\n \"main.blocks\",\n \"autogenerated.ts\",\n \"dataset.json\",\n \"pxt.json\",\n \"README.md\"\n ],\n \"targetVersions\": {\n \"target\": \"7.1.2\",\n \"pxt\": \"10.3.5\"\n },\n \"preferredEditor\": \"blocksprj\"\n}\n", - // "_history": "{\"entries\":[{\"timestamp\":1728049865319,\"editorVersion\":\"7.0.42\",\"changes\":[{\"type\":\"added\",\"filename\":\"autogenerated.ts\",\"value\":\"// Auto-generated. Do not edit.\\nnamespace ml {\\n export namespace event {\\n //% fixedInstance block=\\\"Exercising\\\"\\n export const Exercising = new MlEvent(2, \\\"Exercising\\\");\\n //% fixedInstance block=\\\"Not exercising\\\"\\n export const NotExercising = new MlEvent(3, \\\"Not exercising\\\");\\n\\n }\\n \\n events = [event.Unknown,event.Exercising,event.NotExercising];\\n \\n control.onEvent(MlRunnerIds.MlRunnerInference, 1, () => {\\n if (!event.Unknown.onStartHandler) {\\n maybeUpdateEventStats(event.Unknown);\\n }\\n });\\n control.onEvent(MlRunnerIds.MlRunnerInference, 2, () => {\\n if (!event.Exercising.onStartHandler) {\\n maybeUpdateEventStats(event.Exercising);\\n }\\n });\\n control.onEvent(MlRunnerIds.MlRunnerInference, 3, () => {\\n if (!event.NotExercising.onStartHandler) {\\n maybeUpdateEventStats(event.NotExercising);\\n }\\n });\\n\\n getModelBlob = (): Buffer => {\\n const result = hex`4C444F4D38001900500003000000000000000002CDCC4C3F0B45786572636973696E6700CDCC4C3F0F4E6F742065786572636973696E6700620F47304D4C3446500000002C0D0000A40500000000000000000000A80000000800000001000000080000000100000000000000000000000000000000000000180000000000000002000000000000002DE9F05F0F460169091839600021796038680346B3EC1E1A07F2080292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A92EC010A20EE0A0A30EE2A0AA2EC010A92EC010A20EE0B0A30EE2B0AA2EC010A92EC010A20EE0C0A30EE2C0AA2EC010A92EC010A20EE0D0A30EE2D0AA2EC010A92EC010A20EE0E0A30EE2E0AA2EC010A92EC010A20EE0F0A30EE2F0AA2EC010A02F22402B3EC121A07F2440292EC010A20EE010A30EE210AA2EC010A92EC010A20EE020A30EE220AA2EC010A92EC010A20EE030A30EE230AA2EC010A92EC010A20EE040A30EE240AA2EC010A92EC010A20EE050A30EE250AA2EC010A92EC010A20EE060A30EE260AA2EC010A92EC010A20EE070A30EE270AA2EC010A92EC010A20EE080A30EE280AA2EC010A92EC010A20EE090A30EE290AA2EC010A02F23C02386800F2C00307F268021024B3EC010A07F20801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC0A0AF3EC0A7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A30EE050AA2EC010A013C8FD107F2680210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C210680028B8BF40F2000001C2386800F2007307F208020224B3EC010A07F26801F1EC0E0AF3EC0E7A60EEA70A21EE081A30EE200A61EEA81A30EE010A22EE092A30EE210A62EEA92A30EE020A23EE0A3A30EE220A63EEAA3A30EE030A24EE0B4A30EE230A64EEAB4A30EE040A25EE0C5A30EE240A65EEAC5A30EE050A26EE0D6A30EE250A66EEAD6A30EE060A27EE0E7A30EE260A30EE070AF1EC020AF3EC027A60EEA70A21EE081A30EE200A30EE010AA2EC010A013CAFD107F208021046022100F002F8BDE8F09F012938B5D0ED002A29D9031D00EB8102F3EC017AF4EE627AF1EE10FAC8BFF0EE672A9A42F4D1002402EE104A054695ED000A30EE620A00F015F80134A14232EE002AA5EC010AF2D8002390ED007AC7EE027A01339942E0EC017AF6D838BD0029E1D138BDDFED297AB4EEE70AF1EE10FA48D4DFED277AB4EEE70AF1EE10FA3ADCDFED247ADFED244A9FED243ADFED243A9FED245A9FED244ADFED245A9FED246ADFED246A60EE277AB7EE007A77EEA47A77EEE47AA7EE830AFDEEE74AA7EEA30AF0EE457AE4EE007A14EE903AE7EE805AA5EE806AE6EE006AF0EE667AF0EE476AE7EE806AA6EE807A17EE102A02EBC35300EE103A7047DFED107AB7EE007A87EE270A70479FED0C0A704700000000AAC20000AE423BAAB83F0000404B007231BF8EBEBFB56E2F093C00A0B43AADAD2A3D28AA2A3EFBFFFF3E0000000059D0953F799026BD2B527B3F93FA7DBECD01913F2730F7BE80DEAE3FB32EDC3E7829A33FB4147A3EFB59A93F5EC956BEBE2B863F6135183F9FF8833F0CB5253F84D6903F9567DA3E6C5CD83FE25994BEAFB6B23FFCBCB7BE45C5AF3F5613BABE20C41F3FF7BD2FBF4E9F023F322A36BF6C53263FBC4959BF39A3EB3C7B329CBFC1E4393D4826DEBF3547223D68007BBF31AFC63FBA16C6BBF4CAC83F6CEDB0BCADFAB83F21358BBDD8E8B23F142A17BF15D1AD3F4F6D31BF8947AB3F87CFD2BE973C4BBC6780D5BD8F1A80BE41A5B0BDE8EFE43DC20F303E8E232BBCFFF501BD0068F4BB4496293D8BB6683E26351D3EA94792BE3FC12EBD42622DBEA1BF40BE7233D6BEC03DF8BDA5779CBD25EB643EB1289D3D05429D3DA4F0C5BE0A83923EF21CA53C22E35A3D8477C0BE68365BBEEA5419BEF32C2FBC56B15F3EB9C991BE33DFB4BEA0220D3EEECF87BEBEEDD6BED46DABBE9F0686BE1DA4F83CF598973C9AF70BBFBB1785BE43AA43BC2E3CA4BE84068A3E29DB37BE34A20C3E37D702BED7F704BE27040E3E34AC90B9AA24BB3DD51308BE6477993D18CB03BE0506C0BEA83CB23EFDDF6CBE0E32243EB8E3D53D78FFD7BDD518B13EF43858BCCF02243E50F610BE4388FCBC5539D03D9B23B5BD3AF8103EC53B843E81B6A43EAEE7ADBE9C0636BE992A85BEC342633EB7318CBD2BB9873E658A66BDD23CB1BE4EFA36BEC0D19EBEB5884D3EBAC9CEBD0CEC83BEBFB2BDBD5A9C56BC1176B2BE7C8EFEBD06EC853EC37F15BE3B991EBE17A814BD79A041BE8BB93C3DD76E53BEEA724E3E884D4F3EBC417BBEDA9A863CF0F455BE7E80C93CCFB8A5BEF7D18A3DC1FA543EEFA34D3E75DDCC3D7D55B73D6073543D0531F0BD3B2E803EE467113DD2F5C53EFDE8A7BD05ACEA3A902CAB3EBFC47A3E7412E03EC852EA3E9D9EF43D131B8D3D5A01A33DC4F7F3BD74A234BEC42D223EFAAEC9BEDA87AA3CE621E53DE31DFB3D2B9F38BE5C433F3E398A8A3E799C8BBE41A084BD5801EBBE137AF9BE9CC6E9BD642991BEC4B9433EEED8A23C802CD3BD4110A23E6F60A43DCC1D0B3E957412BD2AB9953E9FD6A43EEA9974BC55735E3C08C449BE708FED3D99CE5F3DE623B53EDC098CBEDF5BCB3D67F317BEC25A113DB80498BE996E45BD4A6AC7BD3862313E9B628C3E9D72A73E54FA133EA9D7E5BD6CB60C3F0B573B3E119C9EBEEEB0ECBDBFDF0ABD8E18533D49E12DBC1326A53CE0A6C03E742CBABE9FFC92BDA99A9D3DF4EC39BDEDF04A3ECD301ABE314151BE1F0ADCBC95B119BEB9B08EBEECD888BE3A76DEBD4C5D3F3D53F954BE96EAAA3D0D96AB3C4BBB633E0B2BAC3D9800C73D7F9D123D5E13853EB96CCABDAFAB0FBEB68639BE4D1D243E1775BEBD7C39873E3C5E4D3C953E53BE97996ABE719CA0BE3B3FAE3E8874873EAAEFF4BA59B59E3C09473B3C1FC82DBDB2476ABEA6636EBE07F675BEFAC74B3ED2948EBD469156BD2E9F7CBEB42D8B3DDE110FBE5A0F3ABE848580BE6DC6613D364796BDF03B5EBEF29B52BE5A97B93D513B2ABD4996073E7F4F57BEAEB7773E2527AEBD2691123E490AF2BBA593C43D50EB6A3D8269DBBE26E290BE6BB64BBEEE2F92BE4C9A08BD499FAFBE1EE773BE5B9C7B3E5A0968BEBDD4FBBDFACE9ABDCE0822BEAE10473DC49400BE78A3833C9BD6CA3CAC86AABD9B6E9C3ECB8B103EED21BEBEFB0D323DD37300BE156851BCCB6DBC3E34A7DA3D5FC2B53E2FEE48BEA192E4BB19FA20BD1E91C8BD8CA151BE0800D5BE4C667DBDA32CBFBB1EEF793EAD567E3E76BCBC3D7511933EF1B2883E754E223EFE74593C049DFB3CFA97123D61FC8A3ECA815C3E8A42383EA9528A3D2EC4A9BE868E78BB18CFF6BD52E1493DCAF0653DEF5C45BEC51B123D6CAA81BECDD53BBD7C08ED3D8114C03EB8A66BBD7B60993E631C673DF53F0E3DB59DC03C4C4021BE34BB4F3ECFB810BDED7A5ABEF9B40F3D70F9E3BEDF24023D0B83533D1DA8553D7A048CBE1E75C43CEBF4C03DE6C991BE712D3CBE517E3E3E92B4303D63BACC3DD39D553D7614173E30C8843ECA75373D140A193DB1CF863E9F74CE3DCB09973DC04FBB3E299D173E86F5793DAAE9533D0903EC3D3E896DBD61C387BE196ACBBEAB19B43E355C5ABE69774F3D751239BEF7939B3AF9006E3E8E7E3ABDB53CD63D50A500BEE566503EDBE856BEB2181FBDE7D65F3E8548D73E9B13BE3E4966373E731B123E6E79593E524B1D3E817E333D5DF460BEDC2866BC7CE467BEC07094BCEC1FACBE0B8831BE4D4BBDBB702E0F3ED2F49C3D3F8D82BE690FFF3D04AC22BC00D1F8BC3FE270BD6897ACBEBFC419BEE408A03D2CF3DFBCF730443D124B66BE455C5CBEC7A289BD2836EC3CF5A7363D22B9583ED6B0D1BD66ECF73D3A57253D6C9211BFD88874BECC6A85BE6DCE07BF7079E4BD1AD1C4BB7C6CFE3E59653E3E8F7FA9BEF973AB3DF728023D00AE253E153A8E3D18EDA33E99DFEEBEC97051BEEA32433E29B71F3EBC51C03EEDD8703EBFAEB3BE9EF7EE3D9E72FCBE5CB6B9BEDB567D3EA24C4E3CB34F893E41F52C3E9FEF053F194FD6BD482EDBBDB721C2BEA8C568BECA3E41BEA61E04BEDBFD8B3E7403F9BE3E952C3F9EF7EEBD721B8DBE8192D93E16E0A53D59A37A3EDBB7A8BDF99484BE197950BE13CC13BFB57C0A3FD476173F92FEEABE7848F5BE1195B7BD2AA7F5BEAF53383ECE043EBF00000000`;\\n return result;\\n };\\n\\n simulatorSendData();\\n}\\n\\n// Auto-generated. Do not edit. Really.\\n\"},{\"type\":\"added\",\"filename\":\"main.blocks\",\"value\":\"exercising-timenot-exercising-timeunknown-timeexercising-time0not-exercising-time0ml.event.Exercisingdurationexercising-time1durationButton.A0DIVIDE0exercising-time1000ml.event.NotExercisingdurationnot-exercising-time1durationButton.B0DIVIDE0not-exercising-time1000\"},{\"type\":\"added\",\"filename\":\"main.ts\",\"value\":\"ml.onStopDetailed(ml.event.Exercising, function (duration) {\\n basic.clearScreen()\\n exercisingtime += duration\\n})\\ninput.onButtonPressed(Button.A, function () {\\n basic.showNumber(exercisingtime / 1000)\\n})\\ninput.onButtonPressed(Button.B, function () {\\n basic.showNumber(notexercisingtime / 1000)\\n})\\nml.onStopDetailed(ml.event.NotExercising, function (duration) {\\n basic.clearScreen()\\n notexercisingtime += duration\\n})\\nlet notexercisingtime = 0\\nlet exercisingtime = 0\\nexercisingtime = 0\\nnotexercisingtime = 0\\n\"},{\"type\":\"added\",\"filename\":\"pxt.json\",\"value\":\"{\\n \\\"name\\\": \\\"Simple AI exercise timer\\\",\\n \\\"description\\\": \\\"\\\",\\n \\\"dependencies\\\": {\\n \\\"core\\\": \\\"*\\\",\\n \\\"microphone\\\": \\\"*\\\",\\n \\\"radio\\\": \\\"*\\\",\\n \\\"machine-learning\\\": \\\"github:microbit-foundation/pxt-microbit-ml#v0.4.3\\\"\\n },\\n \\\"files\\\": [\\n \\\"main.ts\\\",\\n \\\"main.blocks\\\",\\n \\\"autogenerated.ts\\\",\\n \\\"dataset.json\\\",\\n \\\"pxt.json\\\",\\n \\\"README.md\\\"\\n ],\\n \\\"targetVersions\\\": {\\n \\\"target\\\": \\\"7.1.2\\\",\\n \\\"pxt\\\": \\\"10.3.5\\\"\\n },\\n \\\"preferredEditor\\\": \\\"blocksprj\\\"\\n}\\n\"}]}],\"snapshots\":[{\"timestamp\":1728049865318,\"editorVersion\":\"7.0.42\",\"text\":{}}],\"shares\":[],\"lastSaveTime\":1728049865319}" - // } - // } }; From a7c3c9fd3326399be8ddb3c97c5f53146bceede3 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 10:25:36 +0100 Subject: [PATCH 04/23] Remove activitiesBaseUrl --- src/deployment/default/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/deployment/default/index.tsx b/src/deployment/default/index.tsx index d2a6ec046..ee2bf89d4 100644 --- a/src/deployment/default/index.tsx +++ b/src/deployment/default/index.tsx @@ -52,8 +52,6 @@ const defaultDeploymentFactory: DeploymentConfigFactory = () => ({ troubleshooting: "https://support.microbit.org", wearable: "https://support.microbit.org", }, - // TODO: To move to theme - activitiesBaseUrl: "http://localhost:9000/classroom/activities/", }); export default defaultDeploymentFactory; From f80fb61d2eb9681b24628de288ac16719048cb79 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 10:39:04 +0100 Subject: [PATCH 05/23] Revert Homepage.tsx --- src/pages/HomePage.tsx | 88 ++---------------------------------------- 1 file changed, 4 insertions(+), 84 deletions(-) diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 42908d8dd..23a2aed75 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -10,8 +10,8 @@ import { useInterval, VStack, } from "@chakra-ui/react"; -import { ReactNode, useCallback, useEffect, useState } from "react"; -import { FormattedMessage, IntlShape, useIntl } from "react-intl"; +import { ReactNode, useCallback, useState } from "react"; +import { FormattedMessage, useIntl } from "react-intl"; import { useNavigate } from "react-router"; import DefaultPageLayout from "../components/DefaultPageLayout"; import PercentageDisplay from "../components/PercentageDisplay"; @@ -24,13 +24,8 @@ import { useDeployment } from "../deployment"; import blockImage from "../images/block.png"; import xyzGraph from "../images/xyz-graph.png"; import clap from "../images/clap-square.png"; -import { createNewPageUrl, createSessionPageUrl } from "../urls"; +import { createNewPageUrl } from "../urls"; import { flags } from "../flags"; -import { useSearchParams } from "react-router-dom"; -import { MicrobitOrgResource } from "../model"; -import { Project } from "@microbit/makecode-embed/react"; -import { useStore } from "../store"; -import { SessionPageId } from "../pages-config"; const graphData = { x: [ @@ -68,88 +63,13 @@ const graphData = { ], }; -const useMicrobitResourceSearchParams = (): MicrobitOrgResource | undefined => { - const [params] = useSearchParams(); - const id = params.get("id"); - const project = params.get("project"); - const name = params.get("name"); - - const resource: MicrobitOrgResource | undefined = - id && name && project - ? { - id, - project, - name, - } - : undefined; - return resource; -}; - -const isValidEditorContent = (content: Project): content is Project => { - return ( - content && - typeof content === "object" && - "text" in content && - !!content.text - ); -}; - -const fetchMicrobitOrgResourceTargetCode = async ( - activitiesBaseUrl: string, - resource: MicrobitOrgResource, - intl: IntlShape -): Promise => { - const url = `${activitiesBaseUrl}${resource.id}-makecode.json`; - let json; - try { - const response = await fetch(url); - json = (await response.json()) as object; - } catch (e) { - const rethrow = new Error( - intl.formatMessage({ id: "code-download-error" }) - ); - rethrow.stack = e instanceof Error ? e.stack : undefined; - throw rethrow; - } - if ( - !("editorContent" in json) || - typeof json.editorContent !== "object" || - !json.editorContent || - !isValidEditorContent(json.editorContent) - ) { - throw new Error(intl.formatMessage({ id: "code-format-error" })); - } - return json.editorContent; -}; - const HomePage = () => { const navigate = useNavigate(); const handleGetStarted = useCallback(() => { navigate(createNewPageUrl()); }, [navigate]); const intl = useIntl(); - const { appNameFull, activitiesBaseUrl } = useDeployment(); - const resource = useMicrobitResourceSearchParams(); - const loadProject = useStore((s) => s.loadProject); - console.log("resource", resource); - - useEffect(() => { - const updateAsync = async () => { - if (!resource || !activitiesBaseUrl) { - return; - } - const code = await fetchMicrobitOrgResourceTargetCode( - activitiesBaseUrl, - resource, - intl - ); - console.log("code", code); - loadProject(code); - navigate(createSessionPageUrl(SessionPageId.DataSamples)); - }; - void updateAsync(); - }, [activitiesBaseUrl, intl, loadProject, navigate, resource]); - + const { appNameFull } = useDeployment(); return ( Date: Tue, 15 Oct 2024 10:39:45 +0100 Subject: [PATCH 06/23] Fix merge --- src/pages/ImportPage.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 6015afe35..6c3eaae6f 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -5,9 +5,8 @@ import { useNavigate } from "react-router"; import { useSearchParams } from "react-router-dom"; import { useDeployment } from "../deployment"; import { MicrobitOrgResource } from "../model"; -import { SessionPageId } from "../pages-config"; import { useStore } from "../store"; -import { createSessionPageUrl } from "../urls"; +import { createDataSamplesPageUrl } from "../urls"; const ImportPage = () => { const navigate = useNavigate(); @@ -29,7 +28,7 @@ const ImportPage = () => { ); console.log("code", code); loadProject(code); - navigate(createSessionPageUrl(SessionPageId.DataSamples)); + navigate(createDataSamplesPageUrl()); }; void updateAsync(); }, [activitiesBaseUrl, intl, loadProject, navigate, resource]); From 34160b00e46c1b3c02aa6385b226884391dd4cfa Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 10:42:35 +0100 Subject: [PATCH 07/23] Temp activitiesBaseUrl --- src/deployment/default/index.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/deployment/default/index.tsx b/src/deployment/default/index.tsx index ee2bf89d4..0dbc9c28b 100644 --- a/src/deployment/default/index.tsx +++ b/src/deployment/default/index.tsx @@ -52,6 +52,9 @@ const defaultDeploymentFactory: DeploymentConfigFactory = () => ({ troubleshooting: "https://support.microbit.org", wearable: "https://support.microbit.org", }, + // TODO: To remove from default theme + activitiesBaseUrl: + "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities", }); export default defaultDeploymentFactory; From 0ab41d40903af3867dd45f67a8e6a119d9da8430 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 10:53:40 +0100 Subject: [PATCH 08/23] Hardcode activitiesBaseUrl --- src/deployment/default/index.tsx | 3 --- src/pages/ImportPage.tsx | 8 ++++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/deployment/default/index.tsx b/src/deployment/default/index.tsx index 0dbc9c28b..ee2bf89d4 100644 --- a/src/deployment/default/index.tsx +++ b/src/deployment/default/index.tsx @@ -52,9 +52,6 @@ const defaultDeploymentFactory: DeploymentConfigFactory = () => ({ troubleshooting: "https://support.microbit.org", wearable: "https://support.microbit.org", }, - // TODO: To remove from default theme - activitiesBaseUrl: - "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities", }); export default defaultDeploymentFactory; diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 6c3eaae6f..ee2fad721 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -3,7 +3,8 @@ import { useEffect } from "react"; import { IntlShape, useIntl } from "react-intl"; import { useNavigate } from "react-router"; import { useSearchParams } from "react-router-dom"; -import { useDeployment } from "../deployment"; +// TODO: Use theme activitiesBaseUrl +// import { useDeployment } from "../deployment"; import { MicrobitOrgResource } from "../model"; import { useStore } from "../store"; import { createDataSamplesPageUrl } from "../urls"; @@ -11,7 +12,10 @@ import { createDataSamplesPageUrl } from "../urls"; const ImportPage = () => { const navigate = useNavigate(); const intl = useIntl(); - const { activitiesBaseUrl } = useDeployment(); + // TODO: Use theme activitiesBaseUrl + // const { activitiesBaseUrl } = useDeployment(); + const activitiesBaseUrl = + "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities"; const resource = useMicrobitResourceSearchParams(); const loadProject = useStore((s) => s.loadProject); console.log("resource", resource); From f3b0fd6b3a6fe76b26a98d3f9bd3b321f3bbbd73 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 11:10:48 +0100 Subject: [PATCH 09/23] Remove debug logging --- src/pages/ImportPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index ee2fad721..7e08d79c1 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -18,7 +18,6 @@ const ImportPage = () => { "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities"; const resource = useMicrobitResourceSearchParams(); const loadProject = useStore((s) => s.loadProject); - console.log("resource", resource); useEffect(() => { const updateAsync = async () => { @@ -30,7 +29,6 @@ const ImportPage = () => { resource, intl ); - console.log("code", code); loadProject(code); navigate(createDataSamplesPageUrl()); }; From f0370fe1469394caf03dc11464bc80074d95a8a0 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 11:20:12 +0100 Subject: [PATCH 10/23] Temp hardcoding for local testing --- src/pages/ImportPage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 7e08d79c1..19c0d8537 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -14,8 +14,7 @@ const ImportPage = () => { const intl = useIntl(); // TODO: Use theme activitiesBaseUrl // const { activitiesBaseUrl } = useDeployment(); - const activitiesBaseUrl = - "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities"; + const activitiesBaseUrl = "http://localhost:9000/classroom/activities/"; const resource = useMicrobitResourceSearchParams(); const loadProject = useStore((s) => s.loadProject); From d94db351b06fa5c6c5df61569749b91f8d65d153 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 13:08:04 +0100 Subject: [PATCH 11/23] Change hardcoded url to preview url --- src/pages/ImportPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 19c0d8537..2fce178cf 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -14,7 +14,8 @@ const ImportPage = () => { const intl = useIntl(); // TODO: Use theme activitiesBaseUrl // const { activitiesBaseUrl } = useDeployment(); - const activitiesBaseUrl = "http://localhost:9000/classroom/activities/"; + const activitiesBaseUrl = + "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities/"; const resource = useMicrobitResourceSearchParams(); const loadProject = useStore((s) => s.loadProject); From 2ba8c6b6ce0dadced4cd0d821c98b1678ae6d70e Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 16:58:07 +0100 Subject: [PATCH 12/23] Use deployment activitiesBaseUrl --- src/pages/ImportPage.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 2fce178cf..5d242dc5d 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -3,8 +3,7 @@ import { useEffect } from "react"; import { IntlShape, useIntl } from "react-intl"; import { useNavigate } from "react-router"; import { useSearchParams } from "react-router-dom"; -// TODO: Use theme activitiesBaseUrl -// import { useDeployment } from "../deployment"; +import { useDeployment } from "../deployment"; import { MicrobitOrgResource } from "../model"; import { useStore } from "../store"; import { createDataSamplesPageUrl } from "../urls"; @@ -12,10 +11,7 @@ import { createDataSamplesPageUrl } from "../urls"; const ImportPage = () => { const navigate = useNavigate(); const intl = useIntl(); - // TODO: Use theme activitiesBaseUrl - // const { activitiesBaseUrl } = useDeployment(); - const activitiesBaseUrl = - "http://open-in-createai.next-review.microbit.org.s3-website-eu-west-1.amazonaws.com/classroom/activities/"; + const { activitiesBaseUrl } = useDeployment(); const resource = useMicrobitResourceSearchParams(); const loadProject = useStore((s) => s.loadProject); @@ -43,7 +39,6 @@ const useMicrobitResourceSearchParams = (): MicrobitOrgResource | undefined => { const id = params.get("id"); const project = params.get("project"); const name = params.get("name"); - return id && name && project ? { id, project, name } : undefined; }; From 6c3960fccf97e9c2188dd585020d9d5da95331bf Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 17:03:18 +0100 Subject: [PATCH 13/23] Update ml-trainer-microbit version --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e0d48603..a273ef706 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ jobs: - run: npm ci env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: npm install --no-save @microbit-foundation/ml-trainer-microbit@0.2.0-dev.10 @microbit-foundation/website-deploy-aws@0.6 @microbit-foundation/website-deploy-aws-config@0.9 + - run: npm install --no-save @microbit-foundation/ml-trainer-microbit@0.2.0-dev.13 @microbit-foundation/website-deploy-aws@0.6 @microbit-foundation/website-deploy-aws-config@0.9 if: github.repository_owner == 'microbit-foundation' env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 33152af20a2764335adce3dc819981134ce9947c Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 17:23:51 +0100 Subject: [PATCH 14/23] Updated testing-library/react lib `act` from the library was marked as deprecated even though it should not be. Fix was made in more recent version of the library. --- package-lock.json | 226 +++++----------------------------------------- package.json | 2 +- 2 files changed, 24 insertions(+), 204 deletions(-) diff --git a/package-lock.json b/package-lock.json index e489b336f..afd3bff8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,7 @@ "@formatjs/cli": "^6.2.7", "@playwright/test": "^1.42.1", "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^14.0.0", + "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.0.0", "@types/d3": "^7.4.1", "@types/ejs": "^3.1.5", @@ -5399,119 +5399,30 @@ } }, "node_modules/@testing-library/react": { - "version": "14.3.1", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.3.1.tgz", - "integrity": "sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==", + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz", + "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==", "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "@testing-library/dom": "^9.0.0", - "@types/react-dom": "^18.0.0" + "@babel/runtime": "^7.12.5" }, "engines": { - "node": ">=14" + "node": ">=18" }, "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "react": "^18.0.0", "react-dom": "^18.0.0" - } - }, - "node_modules/@testing-library/react/node_modules/@testing-library/dom": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", - "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@testing-library/react/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@testing-library/react/node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/@testing-library/react/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@testing-library/react/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@testing-library/react/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@testing-library/react/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/react/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" }, - "engines": { - "node": ">=8" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, "node_modules/@testing-library/user-event": { @@ -5531,7 +5442,8 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -7833,38 +7745,6 @@ "node": ">=6" } }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -8120,26 +8000,6 @@ "node": ">= 0.4" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-iterator-helpers": { "version": "1.0.19", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", @@ -9524,22 +9384,6 @@ "loose-envify": "^1.0.0" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -10937,6 +10781,7 @@ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, + "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -11219,22 +11064,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -11657,6 +11486,7 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -11671,6 +11501,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, + "peer": true, "engines": { "node": ">=10" }, @@ -11682,7 +11513,8 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "dev": true, + "peer": true }, "node_modules/promise": { "version": "7.3.1", @@ -12588,18 +12420,6 @@ "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 7e52fba60..0f27c092f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@formatjs/cli": "^6.2.7", "@playwright/test": "^1.42.1", "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^14.0.0", + "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.0.0", "@types/d3": "^7.4.1", "@types/ejs": "^3.1.5", From fa5dca4045adefd27a71ce3042614854cd5eb158 Mon Sep 17 00:00:00 2001 From: Grace Date: Tue, 15 Oct 2024 17:54:32 +0100 Subject: [PATCH 15/23] Add loadProject store test --- src/__mocks__/zustand.ts | 57 ++++++++++++++++++++++++++++++++++++++++ src/store.test.ts | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/__mocks__/zustand.ts create mode 100644 src/store.test.ts diff --git a/src/__mocks__/zustand.ts b/src/__mocks__/zustand.ts new file mode 100644 index 000000000..575f89e6a --- /dev/null +++ b/src/__mocks__/zustand.ts @@ -0,0 +1,57 @@ +// Copied from https://zustand.docs.pmnd.rs/guides/testing#jest +// __mocks__/zustand.ts +import * as zustand from "zustand"; +import { act } from "@testing-library/react"; + +const { create: actualCreate, createStore: actualCreateStore } = + jest.requireActual("zustand"); + +// a variable to hold reset functions for all stores declared in the app +export const storeResetFns = new Set<() => void>(); + +const createUncurried = (stateCreator: zustand.StateCreator) => { + const store = actualCreate(stateCreator); + const initialState = store.getInitialState(); + storeResetFns.add(() => { + store.setState(initialState, true); + }); + return store; +}; + +// when creating a store, we get its initial state, create a reset function and add it in the set +export const create = ((stateCreator: zustand.StateCreator) => { + console.log("zustand create mock"); + + // to support curried version of create + return typeof stateCreator === "function" + ? createUncurried(stateCreator) + : createUncurried; +}) as typeof zustand.create; + +const createStoreUncurried = (stateCreator: zustand.StateCreator) => { + const store = actualCreateStore(stateCreator); + const initialState = store.getInitialState(); + storeResetFns.add(() => { + store.setState(initialState, true); + }); + return store; +}; + +// when creating a store, we get its initial state, create a reset function and add it in the set +export const createStore = ((stateCreator: zustand.StateCreator) => { + console.log("zustand createStore mock"); + + // to support curried version of createStore + return typeof stateCreator === "function" + ? createStoreUncurried(stateCreator) + : createStoreUncurried; +}) as typeof zustand.createStore; + +// reset all stores after each test run +afterEach(() => { + act(() => { + storeResetFns.forEach((resetFn) => { + resetFn(); + }); + }); +}); diff --git a/src/store.test.ts b/src/store.test.ts new file mode 100644 index 000000000..e6f81f53c --- /dev/null +++ b/src/store.test.ts @@ -0,0 +1,50 @@ +import { act, renderHook } from "@testing-library/react"; +import { useStore } from "./store"; +import { Project } from "@microbit/makecode-embed/react"; +import { makecodeIcons } from "./utils/icons"; +import { GestureData } from "./model"; + +const projectHeader = { + target: "microbit", + targetVersion: "7.0.42", + editor: "blocksprj", + name: "Simple AI exercise timer", + meta: {}, + pubId: "", + pubCurrent: false, + id: "f102d806-f767-45c6-3af3-35b3be9dbdcd", + recentUse: 1728049865, + modificationTime: 1728049865, + path: "Simple-AI-exercise-timer", + cloudCurrent: false, + saveId: null, + githubCurrent: false, + _rev: "", + isDeleted: false, + cloudVersion: "", + cloudLastSyncTime: 1, +}; + +const gestureData = [ + { name: "action1", ID: 1, icon: makecodeIcons.Heart, recordings: [] }, + { name: "action2", ID: 2, icon: makecodeIcons.House, recordings: [] }, +] as GestureData[]; + +const sampleProject: Project = { + header: projectHeader, + text: { + "README.md": "", + "autogenerated.ts": "", + "dataset.json": JSON.stringify({ data: gestureData }), + }, +}; + +describe("loadProject", () => { + test("imports gesture data", () => { + const { result } = renderHook(() => useStore()); + act(() => result.current.loadProject(sampleProject)); + + expect(result.current.gestures.length).toEqual(gestureData.length); + expect(result.current.model).toEqual(undefined); + }); +}); From 92dc85a725aaf0f35b6e81fd222a1194a3acf788 Mon Sep 17 00:00:00 2001 From: Grace Date: Wed, 16 Oct 2024 09:37:22 +0100 Subject: [PATCH 16/23] Revert "Updated testing-library/react lib" This reverts commit 33152af20a2764335adce3dc819981134ce9947c. --- package-lock.json | 226 +++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 2 files changed, 204 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index afd3bff8b..e489b336f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,7 @@ "@formatjs/cli": "^6.2.7", "@playwright/test": "^1.42.1", "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^16.0.1", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/d3": "^7.4.1", "@types/ejs": "^3.1.5", @@ -5399,30 +5399,119 @@ } }, "node_modules/@testing-library/react": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz", - "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.3.1.tgz", + "integrity": "sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": ">=18" + "node": ">=14" }, "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", "react": "^18.0.0", "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz", + "integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=14" + } + }, + "node_modules/@testing-library/react/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/@testing-library/react/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/react/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/@testing-library/user-event": { @@ -5442,8 +5531,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -7745,6 +7833,38 @@ "node": ">=6" } }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -8000,6 +8120,26 @@ "node": ">= 0.4" } }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-iterator-helpers": { "version": "1.0.19", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", @@ -9384,6 +9524,22 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -10781,7 +10937,6 @@ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -11064,6 +11219,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -11486,7 +11657,6 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -11501,7 +11671,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -11513,8 +11682,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true, - "peer": true + "dev": true }, "node_modules/promise": { "version": "7.3.1", @@ -12420,6 +12588,18 @@ "integrity": "sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==", "dev": true }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 0f27c092f..7e52fba60 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@formatjs/cli": "^6.2.7", "@playwright/test": "^1.42.1", "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^16.0.1", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "@types/d3": "^7.4.1", "@types/ejs": "^3.1.5", From f1e15779eb5b46a47239d955f890873f3eb9e703 Mon Sep 17 00:00:00 2001 From: Grace Date: Wed, 16 Oct 2024 09:40:32 +0100 Subject: [PATCH 17/23] Revert "Add loadProject store test" This reverts commit fa5dca4045adefd27a71ce3042614854cd5eb158. --- src/__mocks__/zustand.ts | 57 ---------------------------------------- src/store.test.ts | 50 ----------------------------------- 2 files changed, 107 deletions(-) delete mode 100644 src/__mocks__/zustand.ts delete mode 100644 src/store.test.ts diff --git a/src/__mocks__/zustand.ts b/src/__mocks__/zustand.ts deleted file mode 100644 index 575f89e6a..000000000 --- a/src/__mocks__/zustand.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Copied from https://zustand.docs.pmnd.rs/guides/testing#jest -// __mocks__/zustand.ts -import * as zustand from "zustand"; -import { act } from "@testing-library/react"; - -const { create: actualCreate, createStore: actualCreateStore } = - jest.requireActual("zustand"); - -// a variable to hold reset functions for all stores declared in the app -export const storeResetFns = new Set<() => void>(); - -const createUncurried = (stateCreator: zustand.StateCreator) => { - const store = actualCreate(stateCreator); - const initialState = store.getInitialState(); - storeResetFns.add(() => { - store.setState(initialState, true); - }); - return store; -}; - -// when creating a store, we get its initial state, create a reset function and add it in the set -export const create = ((stateCreator: zustand.StateCreator) => { - console.log("zustand create mock"); - - // to support curried version of create - return typeof stateCreator === "function" - ? createUncurried(stateCreator) - : createUncurried; -}) as typeof zustand.create; - -const createStoreUncurried = (stateCreator: zustand.StateCreator) => { - const store = actualCreateStore(stateCreator); - const initialState = store.getInitialState(); - storeResetFns.add(() => { - store.setState(initialState, true); - }); - return store; -}; - -// when creating a store, we get its initial state, create a reset function and add it in the set -export const createStore = ((stateCreator: zustand.StateCreator) => { - console.log("zustand createStore mock"); - - // to support curried version of createStore - return typeof stateCreator === "function" - ? createStoreUncurried(stateCreator) - : createStoreUncurried; -}) as typeof zustand.createStore; - -// reset all stores after each test run -afterEach(() => { - act(() => { - storeResetFns.forEach((resetFn) => { - resetFn(); - }); - }); -}); diff --git a/src/store.test.ts b/src/store.test.ts deleted file mode 100644 index e6f81f53c..000000000 --- a/src/store.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { act, renderHook } from "@testing-library/react"; -import { useStore } from "./store"; -import { Project } from "@microbit/makecode-embed/react"; -import { makecodeIcons } from "./utils/icons"; -import { GestureData } from "./model"; - -const projectHeader = { - target: "microbit", - targetVersion: "7.0.42", - editor: "blocksprj", - name: "Simple AI exercise timer", - meta: {}, - pubId: "", - pubCurrent: false, - id: "f102d806-f767-45c6-3af3-35b3be9dbdcd", - recentUse: 1728049865, - modificationTime: 1728049865, - path: "Simple-AI-exercise-timer", - cloudCurrent: false, - saveId: null, - githubCurrent: false, - _rev: "", - isDeleted: false, - cloudVersion: "", - cloudLastSyncTime: 1, -}; - -const gestureData = [ - { name: "action1", ID: 1, icon: makecodeIcons.Heart, recordings: [] }, - { name: "action2", ID: 2, icon: makecodeIcons.House, recordings: [] }, -] as GestureData[]; - -const sampleProject: Project = { - header: projectHeader, - text: { - "README.md": "", - "autogenerated.ts": "", - "dataset.json": JSON.stringify({ data: gestureData }), - }, -}; - -describe("loadProject", () => { - test("imports gesture data", () => { - const { result } = renderHook(() => useStore()); - act(() => result.current.loadProject(sampleProject)); - - expect(result.current.gestures.length).toEqual(gestureData.length); - expect(result.current.model).toEqual(undefined); - }); -}); From c44bb77549068af51cb4ee971131e9b2bc6ae56d Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Wed, 16 Oct 2024 09:47:43 +0100 Subject: [PATCH 18/23] Tweak copy --- lang/ui.en.json | 2 +- src/messages/ui.en.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/ui.en.json b/lang/ui.en.json index 3cd024858..3a49a5ee0 100644 --- a/lang/ui.en.json +++ b/lang/ui.en.json @@ -88,7 +88,7 @@ "description": "Close button text or label" }, "code-download-error": { - "defaultMessage": "Error downloading the target code", + "defaultMessage": "Error downloading the project code", "description": "Title for error message relating to project loading" }, "coming-soon": { diff --git a/src/messages/ui.en.json b/src/messages/ui.en.json index 13c2b7814..5c5d94f56 100644 --- a/src/messages/ui.en.json +++ b/src/messages/ui.en.json @@ -176,7 +176,7 @@ "code-download-error": [ { "type": 0, - "value": "Error downloading the target code" + "value": "Error downloading the project code" } ], "coming-soon": [ From a2833ab60e95fc4a9ea9af392e2515ec64c05504 Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Wed, 16 Oct 2024 09:50:39 +0100 Subject: [PATCH 19/23] Tweaks --- src/pages/ImportPage.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 5d242dc5d..d34226e76 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -42,7 +42,7 @@ const useMicrobitResourceSearchParams = (): MicrobitOrgResource | undefined => { return id && name && project ? { id, project, name } : undefined; }; -const isValidEditorContent = (content: Project): content is Project => { +const isValidProject = (content: Project): content is Project => { return ( content && typeof content === "object" && @@ -56,10 +56,15 @@ const fetchMicrobitOrgResourceTargetCode = async ( resource: MicrobitOrgResource, intl: IntlShape ): Promise => { - const url = `${activitiesBaseUrl}${resource.id}-makecode.json`; + const url = `${activitiesBaseUrl}${encodeURIComponent( + resource.id + )}-makecode.json`; let json; try { const response = await fetch(url); + if (!response.ok) { + throw new Error(`Unexpected response ${response.status}`); + } json = (await response.json()) as object; } catch (e) { const rethrow = new Error( @@ -72,7 +77,7 @@ const fetchMicrobitOrgResourceTargetCode = async ( !("editorContent" in json) || typeof json.editorContent !== "object" || !json.editorContent || - !isValidEditorContent(json.editorContent) + !isValidProject(json.editorContent) ) { throw new Error(intl.formatMessage({ id: "code-format-error" })); } From 7fa21b2b53e1e1a59fed4993a81946bef75f98f7 Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Wed, 16 Oct 2024 09:51:57 +0100 Subject: [PATCH 20/23] Add timestamp on loading a project --- src/store.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/store.ts b/src/store.ts index 2c0c97717..3a863aca1 100644 --- a/src/store.ts +++ b/src/store.ts @@ -414,6 +414,7 @@ export const useStore = create()( set(({ projectEdited, gestures: prevGestures }) => { const newGestures = getGesturesFromProject(project, prevGestures); return { + timestamp: Date.now(), gestures: newGestures, model: undefined, ...updateProject(project, projectEdited, newGestures, undefined), From 628faf2af76f4f2b7e71b110c1fd861baaee4865 Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Wed, 16 Oct 2024 09:52:57 +0100 Subject: [PATCH 21/23] Comment --- src/store.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/store.ts b/src/store.ts index 3a863aca1..ed4eb73d9 100644 --- a/src/store.ts +++ b/src/store.ts @@ -410,6 +410,10 @@ export const useStore = create()( }); }, + /** + * Generally project loads go via MakeCode as it reads the hex but when we open projects + * from microbit.org we have the JSON already and use this route. + */ loadProject(project: Project) { set(({ projectEdited, gestures: prevGestures }) => { const newGestures = getGesturesFromProject(project, prevGestures); From b7f5b13c8fb99c398a931fcf5357b95565e1face Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Wed, 16 Oct 2024 10:01:18 +0100 Subject: [PATCH 22/23] Share code to get gestures; loadProject as a new session --- src/store.ts | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/store.ts b/src/store.ts index becc44fd6..cdbb12ac3 100644 --- a/src/store.ts +++ b/src/store.ts @@ -416,13 +416,16 @@ export const useStore = create()( * from microbit.org we have the JSON already and use this route. */ loadProject(project: Project) { - set(({ projectEdited, gestures: prevGestures }) => { - const newGestures = getGesturesFromProject(project, prevGestures); + set(() => { + const timestamp = Date.now(); return { - timestamp: Date.now(), - gestures: newGestures, + gestures: getGesturesFromProject(project), model: undefined, - ...updateProject(project, projectEdited, newGestures, undefined), + project, + projectEdited: true, + appEditNeedsFlushToEditor: true, + timestamp, + projectLoadTimestamp: timestamp, }; }); }, @@ -564,11 +567,6 @@ export const useStore = create()( // It's a new project. Thanks user. We'll update our state. // This will cause another write to MakeCode but that's OK as it gives us // a chance to validate/update the project - const datasetString = newProject.text?.[filenames.datasetJson]; - const dataset = datasetString - ? (JSON.parse(datasetString) as DatasetEditorJsonFormat) - : { data: [] }; - const timestamp = Date.now(); return { project: newProject, @@ -576,7 +574,7 @@ export const useStore = create()( timestamp, // New project loaded externally so we can't know whether its edited. projectEdited: true, - gestures: dataset.data, + gestures: getGesturesFromProject(newProject), model: undefined, isEditorOpen: false, }; @@ -783,17 +781,14 @@ const gestureIcon = ({ return useableIcons[0]; }; -const getGesturesFromProject = ( - project: Project, - prevGestures: GestureData[] -): GestureData[] => { +const getGesturesFromProject = (project: Project): GestureData[] => { const { text } = project; if (text === undefined || !("dataset.json" in text)) { - return prevGestures; + return []; } const dataset = JSON.parse(text["dataset.json"]) as object; if (typeof dataset !== "object" || !("data" in dataset)) { - return prevGestures; + return []; } return dataset.data as GestureData[]; }; From 04c8ef9c584de6fa69b88feb195f628fcc2300db Mon Sep 17 00:00:00 2001 From: Matt Hillsdon Date: Wed, 16 Oct 2024 10:12:42 +0100 Subject: [PATCH 23/23] Lint --- src/store.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/store.ts b/src/store.ts index cdbb12ac3..2f39596d7 100644 --- a/src/store.ts +++ b/src/store.ts @@ -11,7 +11,6 @@ import { } from "./makecode/utils"; import { trainModel } from "./ml"; import { - DatasetEditorJsonFormat, DownloadState, DownloadStep, Gesture,