From e9f95a333de8424bad1f74435b5ae2b905588b29 Mon Sep 17 00:00:00 2001 From: yoshi Date: Mon, 5 May 2025 10:05:48 -0700 Subject: [PATCH 01/10] modifired CodeEditor --- src/pages/CodeEditor.jsx | 196 +++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 99 deletions(-) diff --git a/src/pages/CodeEditor.jsx b/src/pages/CodeEditor.jsx index 7c0ea3c..4bdcda2 100644 --- a/src/pages/CodeEditor.jsx +++ b/src/pages/CodeEditor.jsx @@ -2,20 +2,38 @@ import { useEffect, useState } from "react"; import EditorPanel from "../components/EditorPanel"; const PageCodeEditor = () => { - const [code, setCode] = useState(`# Write your Battlesnake code here\ndef move(board):\n return { 'move': 'up' }`); + const [code, setCode] = useState( + `# NOW LOADING` + ); + const appName = "snakeapi-demo-001"; useEffect(() => { document.title = "Snake Brain Editor"; + + fetch(`https://assignment-service.fly.dev/notebook/${appName}`) + .then((res) => { + if (!res.ok) throw new Error("Network response was not ok"); + return res.json(); + }) + .then((notebook) => { + // extract code cell sources and join them + const combined = notebook.cells + .filter((cell) => cell.cell_type === "code") + .map((cell) => cell.source.join("")) + .join("\n\n"); + setCode(combined); + }) + .catch((err) => console.error("Failed to fetch notebook:", err)); }, []); return ( -
+
@@ -24,29 +42,21 @@ const PageCodeEditor = () => { className="box-panel" style={{ flex: 2, - background: 'linear-gradient(145deg, #0d0221, #1a1a1a)', - borderRadius: '12px', - boxShadow: '0 0 15px #05d9e8, 0 0 30px #ff2a6d', - border: '1px solid #ff2a6d', - padding: '1rem', - color: '#eee', + background: "linear-gradient(145deg, #0d0221, #1a1a1a)", + borderRadius: "12px", + padding: "1rem", + color: "#eee", + minHeight: "80vh", + overflow: "auto", }} > -

🐍 Snake Brain (Python) @@ -59,75 +69,65 @@ const PageCodeEditor = () => { className="box-panel" style={{ flex: 1, - background: '#1a1a1a', - borderRadius: '12px', - boxShadow: '0 0 15px #d300c5, 0 0 25px #ff2a6d', - border: '1px solid #d300c5', - padding: '1rem', - color: '#eee', + background: "#1a1a1a", + borderRadius: "12px", + padding: "1rem", + color: "#eee", + minHeight: "80vh", }} > -

🎯 Live Arena Output

-

+

Battlesnake Preview

- {/* game url*/} + {/* game url */}
- {/* API server URL */} -
- setSnakeApiUrl(e.target.value)} - style={{ flex: 1 }} - /> - -
- {/* Test Move */}
+ {/*
+ +
*/} + + {/* live arena */}
{
- {/* snake api */} -
- - -
- {/* test move button */}
Date: Mon, 5 May 2025 14:51:13 -0700 Subject: [PATCH 03/10] submit assignment now creates a fly machine --- src/pages/AssignmentPage.jsx | 66 +++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/src/pages/AssignmentPage.jsx b/src/pages/AssignmentPage.jsx index d8b5941..e0bec79 100644 --- a/src/pages/AssignmentPage.jsx +++ b/src/pages/AssignmentPage.jsx @@ -5,10 +5,12 @@ const AssignmentPage = () => { const [studentName, setStudentName] = useState(""); const [campID, setCampID] = useState(""); const [programID, setProgramID] = useState(""); + const [appName, setAppName] = useState(""); + const [qrCodeNumber, setQrCodeNumber] = useState(""); const [password, setPassword] = useState(""); - const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [file, setFile] = useState(null); + const [projects, setProjects] = useState([]); const [showModal, setShowModal] = useState(false); const [editingIndex, setEditingIndex] = useState(null); @@ -44,7 +46,6 @@ const AssignmentPage = () => { setCampID(""); setProgramID(""); setPassword(""); - setTitle(""); setDescription(""); setFile(null); setEditingIndex(null); @@ -56,12 +57,48 @@ const AssignmentPage = () => { const newProject = { studentname: studentName, campid: campID, + appname: appName, + qrcodenumber: qrCodeNumber, + passwordhash: password, programid: programID, - title, description, - fileName: file ? file.name : null, + file: file, + intructorid: 9, }; + //callt the api to upload a new assignment + const formData = new FormData(); + formData.append("studentname", studentName); + formData.append("campid", campID); + formData.append("programid", programID); + formData.append("appname", appName); + formData.append("qrcodenumber", qrCodeNumber); + formData.append("password", password); + formData.append("description", description); + formData.append("intructoid", 9); + if (file) { + formData.append("file", file, file.name); + } + + fetch("http://localhost:8082/instructor/create", { + method: "POST", + body: formData, + }) + .then((response) => { + if (!response.ok) { + throw new Error("Failed to submit assignment"); + } + return response.json(); + }) + .then((data) => { + console.log("Assignment submitted successfully:", data); + fetchAssignments(); // Refresh the assignments list + }) + .catch((error) => { + console.error("Error submitting assignment:", error); + alert("Failed to submit assignment. Please try again."); + }); + if (editingIndex !== null) { const updatedProjects = [...projects]; updatedProjects[editingIndex] = newProject; @@ -80,7 +117,6 @@ const AssignmentPage = () => { setStudentName(project.studentname || project.studentName || ""); setCampID(project.campid || project.campID || ""); setProgramID(project.programid || project.programID || ""); - setTitle(project.title || ""); setDescription(project.description || ""); setFile(null); setEditingIndex(index); @@ -111,12 +147,23 @@ const AssignmentPage = () => {
- setCampID(e.target.value)} required /> + setCampID(e.target.value)} required />
- setProgramID(e.target.value)} required /> + setProgramID(e.target.value)} required /> +
+ +
+ + setAppName(e.target.value)} required /> +
+ + +
+ + setQrCodeNumber(e.target.value)} required />
@@ -124,11 +171,6 @@ const AssignmentPage = () => { setPassword(e.target.value)} required />
-
- - setTitle(e.target.value)} required /> -
-
From 262ad031ac06301667dc25757ba3c2a623c5c0c6 Mon Sep 17 00:00:00 2001 From: yoshi Date: Mon, 5 May 2025 16:00:55 -0700 Subject: [PATCH 04/10] modified editor.jsx --- src/components/EditorPanel.jsx | 13 +-- src/components/PreviewPanel.jsx | 185 ++++++++++++++++---------------- src/pages/CodeEditor.jsx | 158 ++++++++++++--------------- 3 files changed, 166 insertions(+), 190 deletions(-) diff --git a/src/components/EditorPanel.jsx b/src/components/EditorPanel.jsx index fadcc5d..d96b02e 100644 --- a/src/components/EditorPanel.jsx +++ b/src/components/EditorPanel.jsx @@ -4,12 +4,13 @@ import Editor from '@monaco-editor/react'; export default function EditorPanel({ code, onChange }) { return (
onChange(v || '')} theme="vs-dark" options={{ - fontSize: 16, + fontSize: 20, padding: { top: 10, bottom: 10 }, minimap: { enabled: false }, scrollbar: { - verticalScrollbarSize: 8, - horizontalScrollbarSize: 8, + verticalScrollbarSize: 12, + horizontalScrollbarSize: 12 }, lineNumbers: 'on', - scrollBeyondLastLine: false, + scrollBeyondLastLine: false }} />
diff --git a/src/components/PreviewPanel.jsx b/src/components/PreviewPanel.jsx index afec57f..3e66bd7 100644 --- a/src/components/PreviewPanel.jsx +++ b/src/components/PreviewPanel.jsx @@ -3,124 +3,119 @@ import React, { useState } from 'react'; export default function PreviewPanel({ code }) { const [gameUrl, setGameUrl] = useState(''); const [settings, setSettings] = useState(null); - const [moveRes, setMoveRes] = useState(null); const [loadingSetup, setLoadingSetup] = useState(false); - const [loadingMove, setLoadingMove] = useState(false); - - const fetchSetup = async (e) => { - e.preventDefault(); - setLoadingSetup(true); - try { - const res = await fetch( - `/api/fetch-board?url=${encodeURIComponent(gameUrl.trim())}` - ); - setSettings(await res.json()); - setMoveRes(null); - } catch (err) { - console.error(err); - } - setLoadingSetup(false); - }; - - const testMove = async (e) => { - e.preventDefault(); - if (!settings) return; - setLoadingMove(true); + const fetchBoard = async () => { + if (!gameUrl.trim()) return; + setLoadingSetup(true); try { - const res = await fetch('/api/move', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ code, boardState: settings }) - }); - setMoveRes(await res.json()); + const res = await fetch( + `/api/fetch-board?url=${encodeURIComponent(gameUrl.trim())}` + ); + if (!res.ok) throw new Error('Fetch board failed'); + setSettings(await res.json()); } catch (err) { console.error(err); + } finally { + setLoadingSetup(false); } - setLoadingMove(false); }; const gameId = gameUrl.trim().split('/').pop(); return ( -
-

Battlesnake Preview

+
+
+

+ 🎯 Live Arena Output +

- {/* game board URL */} -
+
setGameUrl(e.target.value)} - style={{ flex: 1 }} + onChange={e => setGameUrl(e.target.value)} + style={{ + width: '100%', + padding: '0.5rem', + marginBottom: '0.75rem', + border: 'none', + borderRadius: 4, + background: 'transparent', + color: '#fff', + outline: 'none' + }} /> - - - - {/* Test Move */} -
-
- {settings && gameId && ( -
+ {/*
+
*/} + +
+ {settings && gameId && (