Skip to content

Commit 9792ffa

Browse files
committed
separated output into its own component
1 parent dcae481 commit 9792ffa

6 files changed

Lines changed: 129 additions & 146 deletions

File tree

public/glorpcat.png

68.9 KB
Loading

src/components/LevelComponent.tsx

Lines changed: 47 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,63 @@
11
import React, { useState, useEffect, useRef } from 'react'
2+
import OutputComponent from './OutputComponent'
23

34
export default function LevelComponent() {
4-
const [code, setCode] = useState("")
5-
const [output, setOutput] = useState("")
6-
const [pyodideReady, setPyodideReady] = useState(false)
7-
const pyodideRef = useRef<any>(null)
8-
9-
useEffect(() => {
10-
const loadPyodide = async () => {
11-
// @ts-ignore
12-
pyodideRef.current = await window.loadPyodide()
13-
setPyodideReady(true)
14-
}
15-
loadPyodide()
16-
}, [])
17-
18-
const runCode = async () => {
19-
if (!pyodideRef.current) return
20-
await pyodideRef.current.runPythonAsync(`
21-
import sys, io
22-
sys.stdout = io.StringIO()
23-
`)
24-
try {
25-
await pyodideRef.current.runPythonAsync(code)
26-
const result = await pyodideRef.current.runPythonAsync(`sys.stdout.getvalue()`)
27-
setOutput(result)
28-
} catch (err: any) {
29-
setOutput(err.message)
30-
}
31-
}
32-
33-
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
34-
if (e.key === "Tab") {
35-
e.preventDefault()
36-
const el = e.target as HTMLTextAreaElement
37-
const { selectionStart, selectionEnd } = el
38-
const newValue = code.slice(0, selectionStart) + " " + code.slice(selectionEnd)
39-
setCode(newValue)
40-
requestAnimationFrame(() => {
41-
el.selectionStart = el.selectionEnd = selectionStart + 4
42-
})
43-
}
44-
}
455

466
return (
47-
<div className="w-screen h-screen flex gap-4 p-4 bg-[#0a0f2e] font-mono overflow-hidden">
48-
49-
{/* Left panel */}
50-
<div className="flex-1 bg-[#2a2a2a] rounded-2xl p-5 flex flex-col gap-4">
51-
52-
{/* Title */}
53-
<h1 className="text-center text-2xl font-black tracking-widest text-green-400"
54-
style={{ textShadow: "2px 2px 0px #166534, -1px -1px 0px #166534, 1px -1px 0px #166534, -1px 1px 0px #166534" }}>
55-
ALIEN PYTHON
56-
</h1>
57-
58-
{/* Code panels */}
59-
<div className="flex gap-3">
60-
{/* Python */}
61-
<div className="flex-1 bg-[#3a7bd5] rounded-2xl overflow-hidden">
62-
<div className="bg-[#2d5fa8] text-white text-xs text-center py-2 tracking-widest font-bold">
63-
*** PYTHON CODE ***
7+
<div className="w-screen h-screen flex gap-10 p-4 font-mono overflow-hidden">
8+
<div className="flex gap-4 p-4 w-6/7 mx-auto">
9+
{/* Left panel */}
10+
<div className="flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3">
11+
12+
{/* Title */}
13+
<h1 className="text-center text-5xl tracking-widest text-green-400">
14+
GLORPYTHON
15+
</h1>
16+
17+
{/* Code panels */}
18+
<div className="flex gap-3">
19+
{/* Python */}
20+
<div className="m-5 flex-1 bg-[#3a7bd5] rounded-2xl overflow-hidden">
21+
<div className="bg-[#2d5fa8] text-white text-s text-center py-2 tracking-widest font-bold">
22+
*** PYTHON CODE ***
23+
</div>
24+
<div className="bg-[#4a8be0] m-2 rounded-xl p-3">
25+
<pre className="text-white text-xs leading-relaxed m-0">{`nums = [1,2,3]
26+
sum = 0
27+
for i in nums:
28+
sum += i
29+
print(sum)`}</pre>
30+
</div>
6431
</div>
65-
<div className="bg-[#4a8be0] m-2 rounded-xl p-3">
66-
<pre className="text-white text-xs leading-relaxed m-0">{`nums = [1,2,3]
67-
sum = 0
68-
for i in nums:
69-
sum += i
70-
print(sum)`}</pre>
32+
33+
{/* Alien */}
34+
<div className="m-5 flex-1 bg-[#2d7a3a] rounded-2xl overflow-hidden">
35+
<div className="bg-[#1f5c29] text-white text-s text-center py-2 tracking-widest font-bold">
36+
*** ALIEN CODE ***
37+
</div>
38+
<div className="bg-[#3a9447] m-2 rounded-xl p-3">
39+
<pre className="text-white text-xs leading-relaxed m-0">{`nums eats [1,2,3]
40+
sum eats 0
41+
i eats nums slowly:
42+
sum eats more i
43+
print eats sum`}</pre>
44+
</div>
7145
</div>
7246
</div>
7347

74-
{/* Alien */}
75-
<div className="flex-1 bg-[#2d7a3a] rounded-2xl overflow-hidden">
76-
<div className="bg-[#1f5c29] text-white text-xs text-center py-2 tracking-widest font-bold">
77-
*** ALIEN CODE ***
78-
</div>
79-
<div className="bg-[#3a9447] m-2 rounded-xl p-3">
80-
<pre className="text-white text-xs leading-relaxed m-0">{`nums eats [1,2,3]
81-
sum eats 0
82-
i eats nums slowly:
83-
sum eats more i
84-
print eats sum`}</pre>
85-
</div>
48+
{/* Goal text */}
49+
<div className="text-gray-300 text-m leading-relaxed text-center" >
50+
<p className="mb-2">The code above are equivalent.</p>
51+
<p className="mb-2">YOUR GOAL: Write a program in ALIEN CODE that outputs the<br />
52+
SQUARE OF THE LENGTH OF nums.</p>
53+
<p className="mb-2">Assume nums is already defined.</p>
54+
<p>(Hint: you cannot use any +-*/ or **)</p>
8655
</div>
87-
</div>
8856

89-
{/* Goal text */}
90-
<div className="text-gray-300 text-xs leading-relaxed">
91-
<p className="mb-2">The code above are equivalent.</p>
92-
<p className="mb-2">YOUR GOAL: Write a program in<br />
93-
ALIEN CODE that outputs the<br />
94-
SQUARE OF THE LENGTH OF nums.</p>
95-
<p className="mb-2">Assume nums is already defined.</p>
96-
<p>(Hint: you cannot use any +-*/ or **)</p>
9757
</div>
98-
99-
</div>
100-
101-
{/* Right panel */}
102-
<div className="flex-1 bg-[#2a2a2a] rounded-2xl p-5 flex flex-col gap-3">
103-
104-
{/* Editor */}
105-
<textarea
106-
value={code}
107-
onChange={(e) => setCode(e.target.value)}
108-
onKeyDown={handleKeyDown}
109-
spellCheck={false}
110-
placeholder="write code here!"
111-
className="flex-1 bg-[#3a3a3a] text-gray-300 text-sm font-mono p-4 rounded-xl resize-none outline-none placeholder-gray-500"
112-
/>
113-
114-
{/* Submit button */}
115-
<button
116-
onClick={runCode}
117-
disabled={!pyodideReady}
118-
className="bg-green-600 hover:bg-green-500 disabled:bg-gray-600 text-white font-bold py-2 px-6 rounded-lg text-sm w-fit"
119-
>
120-
{pyodideReady ? "submit" : "loading python..."}
121-
</button>
122-
123-
{/* Output */}
124-
<div className="text-gray-300 text-sm font-bold tracking-widest">OUTPUT:</div>
125-
<div className="bg-[#3a3a3a] rounded-xl p-4 text-gray-400 text-sm font-mono min-h-[60px]">
126-
{output || <span className="text-gray-600">output</span>}
58+
<div className="flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3">
59+
<OutputComponent />
12760
</div>
128-
12961
</div>
13062

13163
</div>

src/components/OutputComponent.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React, { useState, useEffect, useRef } from 'react'
2+
3+
const OutputComponent = () => {
4+
const [code, setCode] = useState("")
5+
const [output, setOutput] = useState("")
6+
const [pyodideReady, setPyodideReady] = useState(false)
7+
const pyodideRef = useRef<any>(null)
8+
const outputExpected = "5"
9+
useEffect(() => {
10+
const loadPyodide = async () => {
11+
// @ts-ignore
12+
pyodideRef.current = await window.loadPyodide()
13+
setPyodideReady(true)
14+
}
15+
loadPyodide()
16+
}, [])
17+
18+
const runCode = async () => {
19+
if (!pyodideRef.current) return
20+
await pyodideRef.current.runPythonAsync(`
21+
import sys, io
22+
sys.stdout = io.StringIO()
23+
`)
24+
try {
25+
await pyodideRef.current.runPythonAsync(code)
26+
const result = await pyodideRef.current.runPythonAsync(`sys.stdout.getvalue()`)
27+
setOutput(result)
28+
} catch (err: any) {
29+
setOutput(err.message)
30+
}
31+
}
32+
33+
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
34+
if (e.key === "Tab") {
35+
e.preventDefault()
36+
const el = e.target as HTMLTextAreaElement
37+
const { selectionStart, selectionEnd } = el
38+
const newValue = code.slice(0, selectionStart) + " " + code.slice(selectionEnd)
39+
setCode(newValue)
40+
requestAnimationFrame(() => {
41+
el.selectionStart = el.selectionEnd = selectionStart + 4
42+
})
43+
}
44+
}
45+
46+
return (
47+
<div className="flex-1 p-3 flex flex-col gap-3">
48+
{/* Editor */}
49+
<textarea
50+
value={code}
51+
onChange={(e) => setCode(e.target.value)}
52+
onKeyDown={handleKeyDown}
53+
spellCheck={false}
54+
placeholder="write code here!"
55+
className=" bg-[#3a3a3a] text-gray-300 text-sm font-mono p-4 rounded-xl resize-none outline-none placeholder-gray-500 flex-1"
56+
/>
57+
58+
{/* Submit button */}
59+
<button
60+
onClick={runCode}
61+
disabled={!pyodideReady}
62+
className="bg-green-600 hover:bg-green-500 disabled:bg-gray-600 text-white font-bold py-2 px-6 rounded-lg text-sm w-fit"
63+
>
64+
{pyodideReady ? "submit" : "loading python..."}
65+
</button>
66+
67+
{/* Output */}
68+
<div className="text-gray-300 text-sm font-bold tracking-widest">OUTPUT:</div>
69+
<div className="bg-[#3a3a3a] rounded-xl p-4 text-gray-100 text-sm font-mono min-h-10">
70+
{output || <span className="text-gray-100">output appears here</span>}
71+
</div>
72+
73+
<div className="text-gray-300 text-sm font-bold tracking-widest">EXPECTED OUTPUT:</div>
74+
<div className="bg-[#3a3a3a] rounded-xl p-4 text-sm font-mono min-h-10">
75+
<span className="text-gray-100">{outputExpected}</span>
76+
</div>
77+
</div>
78+
)
79+
}
80+
81+
export default OutputComponent
82+

src/components/button/Button.module.css

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/components/button/Button.tsx

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/pages/home/Home.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import Button from "../../components/button/Button";
21
import styles from "./Home.module.css";
32
import {useState} from "react";
43
import LevelComponent from "../../components/LevelComponent";

0 commit comments

Comments
 (0)