aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/FuncExpectedAnswer.tsx
blob: f412ba5bce6686fc8a19e1b95a9387dfad7ac3f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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;