@@ -2,159 +2,17 @@ import React, { useState, useEffect, useRef, useMemo } from "react";
22import OutputComponent from './OutputComponent'
33import InfoComponent from './InfoComponent'
44
5- export default function LevelComponent ( ) {
6- const [ code , setCode ] = useState ( "" )
7- const [ output , setOutput ] = useState ( "" )
8- const [ translatedPython , setTranslatedPython ] = useState ( "" ) ;
9- const [ exampleAst , setExampleAst ] = useState < ProgramNode | null > ( null ) ;
10- const [ exampleAlien , setExampleAlien ] = useState ( "" ) ;
11- const [ exampleError , setExampleError ] = useState ( "" ) ;
12- const [ pyodideReady , setPyodideReady ] = useState ( false )
13- const pyodideRef = useRef < any > ( null )
14- const sourcePython = `
15- nums = [1,2,3]
16- sum = 0
17- for i in nums:
18- sum += i
19- print(sum)
20- ` . trim ( ) ;
21-
22-
23- // Use a fixed seed for this level for now
24- const lang = useMemo ( ( ) => generatePlanetLanguage ( 2 ) , [ ] ) ;
25-
26- useEffect ( ( ) => {
27- const loadPyodide = async ( ) => {
28- // @ts -ignore
29- pyodideRef . current = await window . loadPyodide ( )
30- setPyodideReady ( true )
31- }
32- loadPyodide ( )
33- } , [ ] )
34-
35- useEffect ( ( ) => {
36- let cancelled = false ;
37-
38- const parseExample = async ( ) => {
39- try {
40- setExampleError ( "" ) ;
41-
42- const ast = await parsePythonWithTreeSitter ( sourcePython ) ;
43- if ( cancelled ) return ;
44-
45- setExampleAst ( ast ) ;
46- setExampleAlien ( renderAlien ( ast , lang ) ) ;
47- } catch ( err ) {
48- if ( cancelled ) return ;
49- setExampleError ( err instanceof Error ? err . message : String ( err ) ) ;
50- }
51- } ;
52-
53- parseExample ( ) ;
54-
55- return ( ) => {
56- cancelled = true ;
57- } ;
58- } , [ sourcePython , lang ] ) ;
59-
60- const runCode = async ( ) => {
61- if ( ! pyodideRef . current ) return
62- if ( ! pyodideRef . current ) return ;
63-
64- const validation = validateAlienSource ( code , lang ) ;
65-
66- if ( ! validation . isValid ) {
67- setTranslatedPython ( "" ) ;
68- setOutput (
69- validation . issues
70- . map (
71- ( issue ) =>
72- `Line ${ issue . line } , Col ${ issue . column } : ${ issue . message } ` ,
73- )
74- . join ( "\n" ) ,
75- ) ;
76- return ;
77- }
78- try {
79- // 1. Alien -> AST
80- const ast = parseAlien ( code , lang ) ;
81- console . log ( ast ) ;
82- // 2. AST -> Python
83- const pythonCode = renderPython ( ast ) ;
84- setTranslatedPython ( pythonCode ) ;
85-
86-
87- // 3. Reset stdout
88- await pyodideRef . current . runPythonAsync ( `
89- import sys, io
90- sys.stdout = io.StringIO()
91- ` ) ;
92-
93- // 4. Run translated Python
94- await pyodideRef . current . runPythonAsync ( pythonCode ) ;
95-
96- // 5. Get output
97- const result = await pyodideRef . current . runPythonAsync ( `sys.stdout.getvalue()` ) ;
98- setOutput ( String ( result ) ) ;
99- } catch ( err : any ) {
100- setOutput ( err ?. message ?? String ( err ) ) ;
101- }
102- } ;
103-
104- const handleKeyDown = ( e : React . KeyboardEvent < HTMLTextAreaElement > ) => {
105- if ( e . key === "Tab" ) {
106- e . preventDefault ( )
107- const el = e . target as HTMLTextAreaElement
108- const { selectionStart, selectionEnd } = el
109- const newValue = code . slice ( 0 , selectionStart ) + " " + code . slice ( selectionEnd )
110- setCode ( newValue )
111- requestAnimationFrame ( ( ) => {
112- el . selectionStart = el . selectionEnd = selectionStart + 4
113- } )
114- }
115- }
116-
5+ export default function LevelComponent ( { lvl } : { lvl : number } ) {
6+ const seed = lvl * 71 - 10 ;
1177 return (
118- // <div className="w-screen h-screen flex gap-10 p-4 font-mono overflow-hidden">
119- // <div className="flex gap-4 p-4 w-6/7 mx-auto">
8+ < div className = "w-screen h-screen flex gap-10 p-4 font-mono overflow-hidden" >
9+ < div className = "flex gap-4 p-4 w-6/7 mx-auto" >
12010
121- // <div className="flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3">
122- // <InfoComponent />
123- < div className = "w-screen h-screen flex gap-4 p-4 bg-[#0a0f2e] font-mono overflow-hidden" >
124-
125- { /* Left panel */ }
126- < div className = "flex-1 bg-[#2a2a2a] rounded-2xl p-5 flex flex-col gap-4" >
127-
128- { /* Title */ }
129- < h1 className = "text-center text-2xl font-black tracking-widest text-green-400"
130- style = { { textShadow : "2px 2px 0px #166534, -1px -1px 0px #166534, 1px -1px 0px #166534, -1px 1px 0px #166534" } } >
131- ALIEN PYTHON
132- </ h1 >
133-
134- { /* Code panels */ }
135- < div className = "flex gap-3" >
136- { /* Python */ }
137- < div className = "flex-1 bg-[#3a7bd5] rounded-2xl overflow-hidden" >
138- < div className = "bg-[#2d5fa8] text-white text-xs text-center py-2 tracking-widest font-bold" >
139- *** PYTHON CODE ***
140- </ div >
141- < div className = "bg-[#4a8be0] m-2 rounded-xl p-3" >
142- < pre className = "text-white text-xs leading-relaxed m-0" > { sourcePython } </ pre >
143- </ div >
144- </ div >
145-
146- { /* Alien */ }
147- < div className = "flex-1 bg-[#2d7a3a] rounded-2xl overflow-hidden" >
148- < div className = "bg-[#1f5c29] text-white text-xs text-center py-2 tracking-widest font-bold" >
149- *** ALIEN CODE ***
150- </ div >
151- < div className = "bg-[#3a9447] m-2 rounded-xl p-3" >
152- < pre className = "text-white text-xs leading-relaxed m-0" > { exampleError ? `Error: ${ exampleError } ` : exampleAlien || "Loading..." } </ pre >
153- </ div >
154- </ div >
11+ < div className = "flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3" >
12+ < InfoComponent seed = { seed } />
15513 </ div >
15614 < div className = "flex-1 bg-[#2a2a2a] rounded-2xl p-3 flex flex-col gap-3" >
157- < OutputComponent />
15+ < OutputComponent seed = { seed } />
15816 </ div >
15917 </ div >
16018
0 commit comments