microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
source/playground/src/kata.tsx
216lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | import { useState } from "preact/hooks"; |
| 5 | import { QscEventTarget } from "qsharp-lang"; |
| 6 | import { Editor } from "./editor.js"; |
| 7 | import { OutputTabs } from "./tabs.js"; |
| 8 | import { Markdown } from "qsharp-lang/ux"; |
| 9 | |
| 10 | import type { |
| 11 | CompilerState, |
| 12 | ICompilerWorker, |
| 13 | ILanguageServiceWorker, |
| 14 | VSDiagnostic, |
| 15 | } from "qsharp-lang"; |
| 16 | |
| 17 | import type { |
| 18 | ExplainedSolution, |
| 19 | Kata, |
| 20 | Question, |
| 21 | KataSection, |
| 22 | } from "qsharp-lang/katas"; |
| 23 | |
| 24 | type Props = { |
| 25 | kata: Kata; |
| 26 | compiler: ICompilerWorker; |
| 27 | compiler_worker_factory: () => ICompilerWorker; |
| 28 | compilerState: CompilerState; |
| 29 | onRestartCompiler: () => void; |
| 30 | languageService: ILanguageServiceWorker; |
| 31 | }; |
| 32 | |
| 33 | function ExplainedSolutionElem(props: { solution: ExplainedSolution }) { |
| 34 | return ( |
| 35 | <details> |
| 36 | <summary>{"💡 Solution"}</summary> |
| 37 | {props.solution.items.map((item) => { |
| 38 | switch (item.type) { |
| 39 | case "example": |
| 40 | case "solution": |
| 41 | return ( |
| 42 | <pre> |
| 43 | <code>{item.code}</code> |
| 44 | </pre> |
| 45 | ); |
| 46 | case "text-content": |
| 47 | return <Markdown markdown={item.content}></Markdown>; |
| 48 | } |
| 49 | })} |
| 50 | </details> |
| 51 | ); |
| 52 | } |
| 53 | |
| 54 | function QuestionElem(props: { question: Question }) { |
| 55 | return ( |
| 56 | <> |
| 57 | <h2>{"❓ Question:"}</h2> |
| 58 | <Markdown markdown={props.question.description.content}></Markdown> |
| 59 | <details> |
| 60 | <summary> |
| 61 | <strong>{"💡 Answer"}</strong> |
| 62 | </summary> |
| 63 | {props.question.answer.items.map((item) => { |
| 64 | switch (item.type) { |
| 65 | case "example": |
| 66 | return ( |
| 67 | <pre> |
| 68 | <code>{item.code}</code> |
| 69 | </pre> |
| 70 | ); |
| 71 | case "text-content": |
| 72 | return <Markdown markdown={item.content}></Markdown>; |
| 73 | } |
| 74 | })} |
| 75 | </details> |
| 76 | </> |
| 77 | ); |
| 78 | } |
| 79 | |
| 80 | function LessonElem(props: Props & { section: KataSection }) { |
| 81 | if (props.section.type !== "lesson") throw "Invalid section type"; |
| 82 | const lesson = props.section; |
| 83 | |
| 84 | const [shotError, setShotError] = useState<VSDiagnostic>(); |
| 85 | const [evtHandler] = useState(() => new QscEventTarget(true)); |
| 86 | |
| 87 | return ( |
| 88 | <div> |
| 89 | <div class="section-title"> |
| 90 | <h1> |
| 91 | {"📖 Lesson: "} |
| 92 | <u>{lesson.title}</u> |
| 93 | </h1> |
| 94 | </div> |
| 95 | <div class="kata-text-content"> |
| 96 | {lesson.items.map((item) => { |
| 97 | switch (item.type) { |
| 98 | case "example": |
| 99 | return ( |
| 100 | <> |
| 101 | <Editor |
| 102 | code={item.code} |
| 103 | compiler={props.compiler} |
| 104 | compiler_worker_factory={props.compiler_worker_factory} |
| 105 | compilerState={props.compilerState} |
| 106 | onRestartCompiler={props.onRestartCompiler} |
| 107 | kataSection={lesson} |
| 108 | evtTarget={evtHandler} |
| 109 | defaultShots={1} |
| 110 | showShots={false} |
| 111 | showExpr={false} |
| 112 | shotError={shotError} |
| 113 | setAst={() => ({})} |
| 114 | setHir={() => ({})} |
| 115 | setRir={() => ({})} |
| 116 | setQir={() => ({})} |
| 117 | activeTab="results-tab" |
| 118 | languageService={props.languageService} |
| 119 | ></Editor> |
| 120 | <OutputTabs |
| 121 | evtTarget={evtHandler} |
| 122 | showPanel={false} |
| 123 | kataMode={true} |
| 124 | onShotError={(diag?: VSDiagnostic) => setShotError(diag)} |
| 125 | ast="" |
| 126 | hir="" |
| 127 | rir={["", ""]} |
| 128 | qir="" |
| 129 | activeTab="results-tab" |
| 130 | setActiveTab={() => undefined} |
| 131 | ></OutputTabs> |
| 132 | </> |
| 133 | ); |
| 134 | case "text-content": |
| 135 | return <Markdown markdown={item.content}></Markdown>; |
| 136 | case "question": |
| 137 | return <QuestionElem question={item}></QuestionElem>; |
| 138 | } |
| 139 | })} |
| 140 | </div> |
| 141 | </div> |
| 142 | ); |
| 143 | } |
| 144 | |
| 145 | function ExerciseElem(props: Props & { section: KataSection }) { |
| 146 | if (props.section.type !== "exercise") throw "Invalid section type"; |
| 147 | const exercise = props.section; |
| 148 | |
| 149 | const [shotError, setShotError] = useState<VSDiagnostic>(); |
| 150 | const [evtHandler] = useState(() => new QscEventTarget(true)); |
| 151 | |
| 152 | return ( |
| 153 | <div> |
| 154 | <div class="section-title"> |
| 155 | <h1> |
| 156 | {"⌨ Exercise: "} |
| 157 | <u>{exercise.title}</u> |
| 158 | </h1> |
| 159 | </div> |
| 160 | <Markdown |
| 161 | className="excercise-description" |
| 162 | markdown={exercise.description.content} |
| 163 | /> |
| 164 | <div> |
| 165 | <Editor |
| 166 | defaultShots={1} |
| 167 | showExpr={false} |
| 168 | showShots={false} |
| 169 | shotError={shotError} |
| 170 | evtTarget={evtHandler} |
| 171 | compiler={props.compiler} |
| 172 | compilerState={props.compilerState} |
| 173 | compiler_worker_factory={props.compiler_worker_factory} |
| 174 | onRestartCompiler={props.onRestartCompiler} |
| 175 | code={exercise.placeholderCode} |
| 176 | kataSection={exercise} |
| 177 | setAst={() => ({})} |
| 178 | setHir={() => ({})} |
| 179 | setRir={() => ({})} |
| 180 | setQir={() => ({})} |
| 181 | activeTab="results-tab" |
| 182 | languageService={props.languageService} |
| 183 | ></Editor> |
| 184 | <OutputTabs |
| 185 | evtTarget={evtHandler} |
| 186 | showPanel={false} |
| 187 | kataMode={true} |
| 188 | onShotError={(diag?: VSDiagnostic) => setShotError(diag)} |
| 189 | ast="" |
| 190 | hir="" |
| 191 | rir={["", ""]} |
| 192 | qir="" |
| 193 | activeTab="results-tab" |
| 194 | setActiveTab={() => undefined} |
| 195 | ></OutputTabs> |
| 196 | </div> |
| 197 | <ExplainedSolutionElem |
| 198 | solution={exercise.explainedSolution} |
| 199 | ></ExplainedSolutionElem> |
| 200 | </div> |
| 201 | ); |
| 202 | } |
| 203 | |
| 204 | export function Kata(props: Props) { |
| 205 | return ( |
| 206 | <div class="markdown-body kata-override"> |
| 207 | {props.kata.sections.map((section) => |
| 208 | section.type === "lesson" ? ( |
| 209 | <LessonElem {...props} section={section}></LessonElem> |
| 210 | ) : ( |
| 211 | <ExerciseElem {...props} section={section}></ExerciseElem> |
| 212 | ), |
| 213 | )} |
| 214 | </div> |
| 215 | ); |
| 216 | } |
| 217 | |