diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-03-17 22:19:18 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-03-17 22:19:18 +0900 |
| commit | facdf9357e576f6d47e7dd23f4f7b2b34f6a8d30 (patch) | |
| tree | 21c6aee60b3ddc26ff88ee3273c887125bb5828f /src/components/FuncExpectedAnswer.tsx | |
| parent | c739bbfa7cbb68a51755254d59abf15e514795ca (diff) | |
| download | PHPerKaigi2025-tokens-facdf9357e576f6d47e7dd23f4f7b2b34f6a8d30.tar.gz PHPerKaigi2025-tokens-facdf9357e576f6d47e7dd23f4f7b2b34f6a8d30.tar.zst PHPerKaigi2025-tokens-facdf9357e576f6d47e7dd23f4f7b2b34f6a8d30.zip | |
commit files
Diffstat (limited to 'src/components/FuncExpectedAnswer.tsx')
| -rw-r--r-- | src/components/FuncExpectedAnswer.tsx | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/components/FuncExpectedAnswer.tsx b/src/components/FuncExpectedAnswer.tsx new file mode 100644 index 0000000..f412ba5 --- /dev/null +++ b/src/components/FuncExpectedAnswer.tsx @@ -0,0 +1,59 @@ +import type { Quiz } from "../quiz"; +import { execPHP } from "../exec_php"; +import React, { useState, useEffect } from "react"; +import { useDebounce } from "use-debounce"; + +type Props = { + quiz: Quiz; +}; + +function FuncExpectedAnswer({ quiz }: Props) { + const [argument, setArgument] = useState<string>("123"); + const [debouncedArgument] = useDebounce(argument, 1000); + const [result, setResult] = useState<string>(""); + const [loading, setLoading] = useState<boolean>(true); + + const handleArgumentChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setArgument(e.target.value); + }; + + useEffect(() => { + if (debouncedArgument === "") { + setResult("<empty>"); + return; + } + + setLoading(true); + setResult(""); + + const code = ` + function f($x) { + return ${quiz.func}($x); + } + try { + var_dump(f(${debouncedArgument})); + } catch (\\Throwable $e) { + echo $e->getMessage(), PHP_EOL; + } + `; + + execPHP(code).then((result) => { + const output = result.stdout + result.stderr; + setResult(output.replaceAll(quiz.func, "<answer is masked>")); + setLoading(false); + }); + }, [debouncedArgument, quiz.func]); + + return ( + <div> + <code> + {`f(`} + <input type="text" value={argument} onChange={handleArgumentChange} /> + {`)`} + </code> + は <code>{loading ? "running..." : result}</code> を返す。 + </div> + ); +} + +export default FuncExpectedAnswer; |
