From fe685a65b1cf253c4d16d59844900cd88f912b13 Mon Sep 17 00:00:00 2001 From: bhnuka <01bhanukaekanayake@gmail.com> Date: Sun, 3 Nov 2024 12:55:54 +0800 Subject: [PATCH] working judge0 api for code execution --- .../CollabServiceIntegratedView.tsx | 109 +++++++++++++++--- 1 file changed, 96 insertions(+), 13 deletions(-) diff --git a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx index 41de4eb3c1..8ba7c6d93a 100644 --- a/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx +++ b/peerprep/frontend/src/views/CollabServiceViews/CollabServiceIntegratedView.tsx @@ -4,18 +4,19 @@ import { useParams, useNavigate } from 'react-router-dom'; import 'codemirror/lib/codemirror.css'; import 'codemirror/theme/material.css'; import 'codemirror/mode/javascript/javascript'; +import axios from 'axios'; import * as Y from 'yjs'; import { WebsocketProvider } from 'y-websocket'; - -// @ts-check import { CodemirrorBinding } from 'y-codemirror'; const CollaborationServiceIntegratedView: React.FC = () => { const { topic, difficulty, questionId, sessionId } = useParams<{ topic: string; difficulty: string; questionId: string; sessionId: string; }>(); - const [code, setCode] = useState('// Start coding here...\n'); + const [output, setOutput] = useState(null); + const [language, setLanguage] = useState(63); // Default to JavaScript (Node.js) const editorRef = useRef(null); const navigate = useNavigate(); + const [yText, setYText] = useState(null); useEffect(() => { console.log(`Session ID: ${sessionId}, Topic: ${topic}, Difficulty: ${difficulty}`); @@ -32,26 +33,86 @@ const CollaborationServiceIntegratedView: React.FC = () => { useEffect(() => { const ydoc = new Y.Doc(); const provider = new WebsocketProvider('ws://localhost:1234/' + sessionId, 'collaborative-doc', ydoc); - const yText = ydoc.getText('codemirror'); + const newYText = ydoc.getText('codemirror'); + setYText(newYText); if (editorRef.current) { - const binding = new CodemirrorBinding(yText, editorRef.current.editor, provider.awareness); + const binding = new CodemirrorBinding(newYText, editorRef.current.editor, provider.awareness); + return () => { binding.destroy(); provider.destroy(); ydoc.destroy(); }; } - }, []); - - const handleBeforeCodeChange = (editor: any, data: any, value: string) => { - //setCode(value); - }; + }, [sessionId]); const handleLeaveSession = () => { navigate('/matching'); }; + const handleRunCode = async () => { + try { + if (!yText) { + console.error('Error: Yjs text instance is not available'); + setOutput('Error: Yjs text instance is not available'); + return; + } + + const currentCode = yText.toString(); + console.log('Submitting code for execution:', currentCode); + + // Base64 encode the source code if required by the API + const base64EncodedCode = btoa(currentCode); // `btoa()` encodes a string to base64 + + // Make a POST request to Judge0 API for code execution + const response = await axios.post('https://judge0-ce.p.rapidapi.com/submissions?base64_encoded=true&wait=false&fields=*', { + language_id: language, // Ensure `language` is set correctly in your component + source_code: base64EncodedCode, + stdin: '', // Add input if necessary + }, { + headers: { + 'Content-Type': 'application/json', + 'x-rapidapi-host': 'judge0-ce.p.rapidapi.com', + 'x-rapidapi-key': 'f5d59ce024msha6cd5fccde3d182p14459fjsn8a83590f92b4' + } + }); + + console.log('Submission response:', response.data); + + // Polling for the result of the code execution + const token = response.data.token; + let result = null; + + while (!result || result.status.id <= 2) { + console.log(`Polling result for token: ${token}`); + const statusResponse = await axios.get(`https://judge0-ce.p.rapidapi.com/submissions/${token}?base64_encoded=true&fields=*`, { + headers: { + 'x-rapidapi-host': 'judge0-ce.p.rapidapi.com', + 'x-rapidapi-key': 'f5d59ce024msha6cd5fccde3d182p14459fjsn8a83590f92b4' + } + }); + + result = statusResponse.data; + + // Decode the output if it's base64-encoded + const decodedOutput = result.stdout ? atob(result.stdout) : (result.stderr ? atob(result.stderr) : 'No output'); + console.log('Polling response:', result); + + // Wait for a short duration before the next poll (e.g., 1 second) + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Set the output only when status is finished + if (result.status.id > 2) { + setOutput(decodedOutput); + } + } + } catch (error) { + console.error('Error executing code:', error); + setOutput('Error executing code'); + } + }; + return (
@@ -64,18 +125,40 @@ const CollaborationServiceIntegratedView: React.FC = () => {
{ + // Let Yjs handle all updates; do not use setCode here + }} />
+ + + + + + +

Output

+
+
{output}
+
); }; -export default CollaborationServiceIntegratedView; \ No newline at end of file +export default CollaborationServiceIntegratedView;