From ac0d321f968c570bdeefef565812689499f05005 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Thu, 6 Feb 2025 03:05:13 +0530 Subject: [PATCH 01/10] resizable chatwidget --- src/resources/chat-widget/src/index.ts | 86 +++++++++++++++++++++++- src/resources/chat-widget/src/widget.css | 2 +- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/resources/chat-widget/src/index.ts b/src/resources/chat-widget/src/index.ts index 2fbdd15f..742206a1 100644 --- a/src/resources/chat-widget/src/index.ts +++ b/src/resources/chat-widget/src/index.ts @@ -117,7 +117,9 @@ function addMessageToHistory(role: string, content: string, uid: string=UID): vo // update editors content to msg history everytime user writes/sends message conversationHistory[NUM_MANDATORY_ENTRIES-1] = { role: "system", - content: "Openrepl IDE/Editor Code Content: "+ fetchEditorContent(), + content: `Openrepl IDE/Editor real-time Code Content user is working on, + (refer this code whenever user ask to debug editor/ide + code without providing any code in message): `+ fetchEditorContent(), } } } @@ -256,6 +258,87 @@ const trap = createFocusTrap(containerElement, { allowOutsideClick: true, }); +function makeResizable(containerElement: HTMLElement, target: HTMLElement) { + // Create a resizer div + const resizer = document.createElement("div"); + resizer.innerHTML = ` + + + + + `; + resizer.style.position = "absolute"; + resizer.style.left = "5px"; + resizer.style.top = "5px"; + resizer.style.cursor = "nwse-resize"; + resizer.style.opacity = "0.7"; + resizer.style.transition = "opacity 0.2s"; + resizer.style.display = "flex"; + resizer.style.alignItems = "center"; + resizer.style.justifyContent = "center"; + resizer.style.width = "15px"; + resizer.style.height = "15px"; + + // Style the container for a modern feel + Object.assign(containerElement.style, { + position: "absolute", + borderRadius: "10px", + boxShadow: "0 4px 10px rgba(0, 0, 0, 0.2)", + overflow: "hidden", + resize: "none", // Disable native resize + transition: "width 0.2s ease, height 0.2s ease", + }); + + containerElement.appendChild(resizer); + + let isResizing = false; + + resizer.addEventListener("mousedown", (e) => { + e.preventDefault(); + isResizing = true; + + const startX = e.clientX; + const startY = e.clientY; + const startWidth = containerElement.offsetWidth; + const startHeight = containerElement.offsetHeight; + + function resize(e: MouseEvent) { + if (!isResizing) return; + const newWidth = Math.max(150, startWidth + (startX - e.clientX)); // Min width: 150px + const newHeight = Math.max(100, startHeight + (startY - e.clientY)); // Min height: 100px + containerElement.style.width = `${newWidth}px`; + containerElement.style.height = `${newHeight}px`; + + // Recompute floating position to keep alignment + updatePosition(); + } + + function stopResize() { + isResizing = false; + document.removeEventListener("mousemove", resize); + document.removeEventListener("mouseup", stopResize); + } + + document.addEventListener("mousemove", resize); + document.addEventListener("mouseup", stopResize); + }); + + function updatePosition() { + computePosition(target, containerElement, { + placement: "top-start", + middleware: [flip(), shift({ crossAxis: true, padding: 8 })], + strategy: "fixed", + }).then(({ x, y }) => { + Object.assign(containerElement.style, { + left: `${x}px`, + top: `${y}px`, + }); + }); + } + + return updatePosition; // Return the function so it can be used if needed +} + function open(e: Event) { if (config.closeOnOutsideClick) { document.body.appendChild(optionalBackdrop); @@ -293,6 +376,7 @@ function open(e: Event) { }); }); + makeResizable(containerElement, target); trap.activate(); if (config.closeOnOutsideClick) { diff --git a/src/resources/chat-widget/src/widget.css b/src/resources/chat-widget/src/widget.css index c7c74e93..ccdfebf3 100644 --- a/src/resources/chat-widget/src/widget.css +++ b/src/resources/chat-widget/src/widget.css @@ -166,7 +166,7 @@ width: 100%; height: 100%; background-image: url('images/genie-large.png'); /* Path to your animated GIF */ - background-size: cover; /* Make the background cover the entire container */ + background-size: contain; /* Make the background contained */ background-position: center; /* Center the background image */ background-repeat: no-repeat; /* Prevent the background image from repeating */ opacity: 0.5; /* Adjust opacity as needed */ From cb9e61012e7e52f64b8cabf1616c80a53f46734c Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Wed, 12 Feb 2025 18:09:41 +0530 Subject: [PATCH 02/10] dsa practice page --- src/Makefile | 3 +- src/resources/chat-widget/src/index.ts | 35 ++- src/resources/css/scribbler-global.css | 35 ++- src/resources/css/scribbler-landing.css | 27 -- src/resources/css/scribbler-misc.css | 197 ++++++++++++++ src/resources/editblog.html | 2 +- src/resources/index.html | 264 ++++++++++++++++++ src/resources/js/chatgpt_plugin.js | 36 +-- src/resources/js/common.js | 346 ++++++++++++++++++++++++ src/resources/js/scribbler-misc.js | 230 ++++++++++++++++ src/resources/js/scribbler.js | 7 +- src/resources/practice.html | 150 ++++++++++ src/server/db.go | 34 +++ src/server/server.go | 3 +- src/server/utils.go | 8 +- 15 files changed, 1308 insertions(+), 69 deletions(-) create mode 100644 src/resources/css/scribbler-misc.css create mode 100644 src/resources/js/scribbler-misc.js create mode 100644 src/resources/practice.html diff --git a/src/Makefile b/src/Makefile index 9eed528a..15a1b015 100755 --- a/src/Makefile +++ b/src/Makefile @@ -33,9 +33,10 @@ bindata: bindata/static: bindata mkdir bindata/static -bindata/static/index.html: bindata/static resources/index.html resources/profile.html resources/robots.txt jsconsole/build/static/jsconsole.html +bindata/static/index.html: bindata/static resources/index.html resources/profile.html resources/practice.html resources/robots.txt jsconsole/build/static/jsconsole.html cp resources/index.html bindata/static/index.html cp resources/profile.html bindata/static/profile.html + cp resources/practice.html bindata/static/practice.html cp resources/robots.txt bindata/static/robots.txt cp jsconsole/build/static/jsconsole.html bindata/static/jsconsole.html diff --git a/src/resources/chat-widget/src/index.ts b/src/resources/chat-widget/src/index.ts index 742206a1..c30d754f 100644 --- a/src/resources/chat-widget/src/index.ts +++ b/src/resources/chat-widget/src/index.ts @@ -13,6 +13,29 @@ const WIDGET_MESSAGES_HISTORY_CONTAINER_ID = const WIDGET_THINKING_BUBBLE_ID = "chat-widget__thinking_bubble"; const CHAT_LIST_KEY = "chat-list" +const interviewPrompt = ` +You are an expert coding interviewer conducting a technical interview. Your goal is to assess the candidate's ability to solve a coding problem independently. + +### Interview Process: +1. Start by presenting the problem statement and constraints clearly from IDE. +2. Do NOT give the solution or direct hints unless the user explicitly asks for help or is stuck. +3. Encourage the candidate to **think aloud** and explain their approach. +4. If the candidate provides an incorrect approach, ask **clarifying questions** to guide them. +5. Only give small hints when necessary, helping them think in the right direction without revealing the full solution. +6. Use Socratic questioning to probe their understanding: + - "What data structure might be useful for this problem?" + - "Can you optimize your current approach?" + - "What are the edge cases you need to consider?" +7. If the candidate asks for a full solution, politely **decline** and encourage them to try again. +8. If they are truly stuck (e.g., multiple failed attempts), provide a **small hint** to unblock them. +9. Once they reach a correct approach, let them implement it and provide constructive feedback. + +### Response Guidelines: +- Be professional and supportive but **not too helpful**. +- Encourage the user to debug their code rather than fixing it for them. +- Give feedback in a way that promotes learning and problem-solving skills. +` + function generateFiveCharUUID(): string { // Generate a UUID and extract the first 5 characters const uuid: string = crypto.randomUUID(); @@ -227,8 +250,16 @@ async function init() { ); open({ target } as Event); } - addMessageToHistory("system", "welcome to openrepl.com!! I am Genie. your OpenRepl AI assistant."); - addMessageToHistory("system", "documentation: "+documentation); + + let welcomeprompt = "welcome to openrepl.com!! you are Genie. An OpenRepl AI"; + // only four permanent prompts + if (window.location.pathname.includes("practice")) { + addMessageToHistory("system", welcomeprompt+" Interviewer."); + addMessageToHistory("system", interviewPrompt); + } else { + addMessageToHistory("system", welcomeprompt+" Assistant."); + addMessageToHistory("system", "documentation: "+documentation); + } addMessageToHistory("system", "keywords: "+ keywords); addMessageToHistory("system", "Openrepl IDE/EditorCodeContent: "+ fetchEditorContent()); setupFBListener(); diff --git a/src/resources/css/scribbler-global.css b/src/resources/css/scribbler-global.css index 92a5ecf6..694480fb 100755 --- a/src/resources/css/scribbler-global.css +++ b/src/resources/css/scribbler-global.css @@ -23,6 +23,10 @@ --terminal-bg-color: black; --gutter-rotate: 90deg; /* Initial rotation angle */ --gutter-right: 3px; + --modal-duration: 1s; + --clear-color: #ebebec; + --shadow-color: rgba(0, 0, 0, 0.3); + --overlay-color: rgba(0, 0, 0, 0.6); } /* normalized */ @@ -506,4 +510,33 @@ input[type=text],[type=email], select, textarea, email { .rev-accent-background { background: var(--rev-accent-color); } -/* them classes ends */ \ No newline at end of file +/* them classes ends */ + +/* loaders */ +.loader, #loader { + position: absolute; + left: 50%; + top: 50%; + z-index: 11; + width: 150px; + height: 150px; + margin: -75px 0 0 -75px; + border: 16px solid #f3f3f3; + border-radius: 50%; + border-top: 16px solid #64CEAA; + width: 80px; + height: 80px; + -webkit-animation: spin 1s linear infinite; + animation: spin 1s linear infinite; +} + +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} +/* loader ends */ \ No newline at end of file diff --git a/src/resources/css/scribbler-landing.css b/src/resources/css/scribbler-landing.css index 7ae77d05..05a385f0 100755 --- a/src/resources/css/scribbler-landing.css +++ b/src/resources/css/scribbler-landing.css @@ -771,33 +771,6 @@ h2 { padding-right:10px; } -#loader { - position: absolute; - left: 50%; - top: 50%; - z-index: 11; - width: 150px; - height: 150px; - margin: -75px 0 0 -75px; - border: 16px solid #f3f3f3; - border-radius: 50%; - border-top: 16px solid #64CEAA; - width: 80px; - height: 80px; - -webkit-animation: spin 1s linear infinite; - animation: spin 1s linear infinite; -} - -@-webkit-keyframes spin { - 0% { -webkit-transform: rotate(0deg); } - 100% { -webkit-transform: rotate(360deg); } -} - -@keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - /* tooltip */ .tooltip { diff --git a/src/resources/css/scribbler-misc.css b/src/resources/css/scribbler-misc.css new file mode 100644 index 00000000..551a3408 --- /dev/null +++ b/src/resources/css/scribbler-misc.css @@ -0,0 +1,197 @@ +.wrapper .wrapper-body { + padding: 10px; + width: 100%; + background-color: #f5f5f5; +} +.toolbar { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + background: #fff; + padding: 10px 15px; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); +} +.toolbar select, .toolbar input { + padding: 7px; + border: 1px solid #ccc; + border-radius: 4px; + font-size: 14px; +} +#newQuestionBtn, #randomQuestionBtn, #completeBtn { + background-color: #007bff; + color: white; + border: none; + padding: 10px 15px; + border-radius: 6px; + cursor: pointer; + font-size: 14px; + transition: background 0.3s; +} +#newQuestionBtn:hover, #randomQuestionBtn:hover, #completeBtn:hover { + background-color: #0056b3; +} + +.question-link { + text-decoration: none; + color: #007bff; + font-weight: bold; +} +.question-link:hover { + text-decoration: underline; +} +.bookmarked-row { + background-color: #d1ffd1 !important; +} + +.bookmark { + appearance: none; /* Remove default checkbox */ + width: 18px; + height: 18px; + border: 2px solid #ccc; + border-radius: 5px; + cursor: pointer; + display: inline-block; + position: relative; +} + +.bookmark:checked::before { + content: "βœ…"; /* Unicode checkmark */ + font-size: 18px; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.delete-btn { + background: #dc3545; + color: white; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + font-size: 12px; +} +.delete-btn:hover { + background: #b02a37; +} + +/* modal */ +.select2-container { + min-width: 200px !important; /* Adjust as needed */ + width: 100% !important; /* Ensure it takes full available space */ +} + +.modal-container { + background-color: var(--overlay-color); + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + display: none; +} + +.modal-container.show-modal { + display: block; + z-index: 100; +} + +.modal { + background-color: var(--clear-color); + border-radius: 5px; + box-shadow: 0 0 10px var(--shadow-color); + position: absolute; + overflow: hidden; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + max-width: 100%; + width: 400px; + animation-name: modalopen; + animation-duration: var(--modal-duration); +} + +.modal-header { + background: var(--primary-color); + color: var(--clear-color); + padding: 15px; +} + +.modal-header h3 { + margin: 0; +} + +.modal-content { + padding: 20px; +} + +.modal-form div { + margin: 15px 0; +} + +.modal-form label { + display: block; + margin-bottom: 5px; +} + +.modal-form .form-input { + padding: 8px; + width: 100%; +} + +.modal-rows { + display: flex; + align-items: center; + gap: 10px; /* Adjust spacing */ +} + +.close-btn { + background: transparent; + font-size: 25px; + position: absolute; + top: 0; + right: 0; +} + +@keyframes modalopen { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +/* question table */ +#questionsTable { + width: 100% !important; +} + +#questionsTable th, +#questionsTable td { + overflow: hidden; + white-space: nowrap; /* Prevent text wrapping */ + text-overflow: ellipsis; /* Truncate long text with '...' */ +} + +/* Bookmark column (smallest width, checkbox) */ +#questionsTable th:nth-child(1), +#questionsTable td:nth-child(1) { + width: 5% !important; + text-align: center; +} + +/* Name column (widest) */ +#questionsTable th:nth-child(2), +#questionsTable td:nth-child(2) { + width: 35% !important; +} + +/* Other columns (equal distribution) */ +#questionsTable th:nth-child(n+3), +#questionsTable td:nth-child(n+3) { + width: 15% !important; +} diff --git a/src/resources/editblog.html b/src/resources/editblog.html index 70e1f94b..23becd14 100644 --- a/src/resources/editblog.html +++ b/src/resources/editblog.html @@ -162,6 +162,7 @@


Open
REPL

©OpenREPL + - diff --git a/src/resources/index.html b/src/resources/index.html index 3ffea830..65202c14 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -46,6 +46,8 @@ + + @@ -197,6 +199,7 @@ + @@ -653,6 +656,7 @@

Share/Collaborate

+ + + diff --git a/src/resources/js/chatgpt_plugin.js b/src/resources/js/chatgpt_plugin.js index 894f75df..3d0dd393 100644 --- a/src/resources/js/chatgpt_plugin.js +++ b/src/resources/js/chatgpt_plugin.js @@ -1,5 +1,4 @@ /* global tinymce */ - tinymce.PluginManager.add('chatgpt', function (editor) { const OPENAI = editor.getParam('openai') @@ -74,7 +73,12 @@ tinymce.PluginManager.add('chatgpt', function (editor) { let prompt = data.prompt ?? '' prompt += input // Get response from OpenAI - getResponseFromOpenAI(prompt) + getResponseFromOpenAI(OPENAI.api_key, prompt, { + baseUri: OPENAI.baseUri, + model: OPENAI.model, + temperature: OPENAI.temperature, + max_tokens: OPENAI.max_tokens, + }) .then((res) => { if (!res.ok) { throw new Error(`Request failed with status ${res.status}`); @@ -129,34 +133,6 @@ tinymce.PluginManager.add('chatgpt', function (editor) { }) } - /** - * Get the current selection and set it as the default input - * @param prompt - * @returns {Promise} - */ - function getResponseFromOpenAI (prompt) { - const baseUri = OPENAI.baseUri || 'https://api.openai.com/v1/chat/completions' - - const requestBody = { - model: OPENAI.model, - messages: [{ - role: 'user', - content: prompt - }], - temperature: OPENAI.temperature, - max_tokens: OPENAI.max_tokens - } - - return fetch(baseUri, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: 'Bearer ' + OPENAI.api_key - }, - body: JSON.stringify(requestBody) - }) - } - /* Add a chatgpt icon */ editor.ui.registry.addIcon( 'chatgpt', diff --git a/src/resources/js/common.js b/src/resources/js/common.js index 923fad83..2f6a75d0 100644 --- a/src/resources/js/common.js +++ b/src/resources/js/common.js @@ -9,7 +9,353 @@ var getAll = function (selector, scope) { return scope.querySelectorAll(selector); }; +var globaltemperature = localStorage.getItem("temperature"); +globaltemperature = isNaN(parseFloat(globaltemperature)) ? 0.3 : parseFloat(globaltemperature); +const topics = [ + "Two Pointers", + "Hash Maps and Sets", + "Linked Lists", + "Fast and Slow Pointers", + "Sliding Windows", + "Binary Search", + "Stacks", + "Heaps", + "Intervals", + "Prefix Sums", + "Trees", + "Tries", + "Graphs", + "Recursion", + "Backtracking", + "Dynamic Programming", + "Greedy", + "Sort and Search", + "Bit Manipulation", + "Math and Geometry", + "Divide and Conquer", // Essential for algorithms like merge sort, quicksort + "String Manipulation", // Covers regex, pattern matching, etc. + "Combinatorics", // Helps in counting and probability problems + "Game Theory", // Useful for AI-based problems and decision making + "Number Theory", // Covers prime numbers, GCD/LCM, modular arithmetic + "Network Flow", // Advanced graph algorithm topic + "Topological Sorting", // Used in scheduling problems and dependency resolution + "Fenwick Trees & Segment Trees", // Advanced data structures + "Union-Find & Disjoint Sets", // Used in Kruskal’s algorithm and connectivity problems + "Monotonic Stack/Queue", // Used in problems like Next Greater Element + "Reservoir Sampling", // Used for sampling large streams of data + "System Design", + "Operating Systems", + "Databases", + "Concurrency and Multithreading", + "Networking", + "Compilers and Interpreters", + "Memory Management", + "Cryptography and Security", + "Artificial Intelligence & Machine Learning" + ]; +/** + * Extracts and sanitizes the JSON string from extra text before/after it. + * @param {string} text - The raw text containing JSON and possibly extra text. + * @returns {string|null} - The extracted JSON string or null if not found. + */ +function sanitizeJSONString(text) { + if (!text) return null; + + // Find the first occurrence of '{' and last occurrence of '}' + const startIndex = text.indexOf('{'); + const endIndex = text.lastIndexOf('}'); + + if (startIndex !== -1 && endIndex !== -1 && startIndex < endIndex) { + return text.substring(startIndex, endIndex + 1); // Extract valid JSON part + } + + return null; // Return null if no valid JSON is found +} + +/** + * Get the response from OpenAI API + * @param {string} api_key - The API key (mandatory) + * @param {string} prompt - The prompt to send to OpenAI + * @param {object} options - Optional parameters + * @param {string} [options.baseUri='https://api.openai.com/v1/chat/completions'] - The OpenAI API endpoint + * @param {string} [options.model='gpt-3.5-turbo'] - The model to use + * @param {number} [options.temperature=0.5] - Sampling temperature + * @param {number} [options.max_tokens=800] - Maximum number of tokens + * @returns {Promise} - The API response as a Promise + */ +async function getResponseFromOpenAI(api_key, prompt, options = {}) { + if (!api_key) { + throw new Error("API key is required"); + } + + const { + baseUri = 'https://api.openai.com/v1/chat/completions', + model = 'gpt-4o-mini', + temperature = globaltemperature, + max_tokens = 800 + } = options; + + const requestBody = { + model, + messages: [{ role: 'user', content: prompt }], + temperature, + max_tokens + }; + + return fetch(baseUri, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${api_key}` + }, + body: JSON.stringify(requestBody) + }); +} + +// Save questions, ensuring a maximum of 100 entries. +function saveNewQuestions(newQuestion) { + let storedQuestions = JSON.parse(localStorage.getItem('questions')) || []; + let exists = storedQuestions.some(q => q.nameHyphenated === newQuestion.nameHyphenated); + + if (exists) { + return { error: "This question already exists.", storedQuestions }; + } + + storedQuestions.push(newQuestion); + + // Keep only the latest 100 entries + if (storedQuestions.length > 100) { + storedQuestions = storedQuestions.slice(-100); + } + + localStorage.setItem('questions', JSON.stringify(storedQuestions)); + + return { error: null, storedQuestions }; +} + +/** + * @typedef {Object} Question + * @property {string} id - Unique identifier (timestamp-based). + * @property {string} name - The generated question name. + * @property {string} nameHyphenated - Hyphenated version of the question name for URLs. + * @property {string} topic - The topic of the question. + * @property {"Easy" | "Medium" | "Hard"} difficulty - The difficulty level. + * @property {string} language - The programming language. + * @property {number} added - Timestamp of when the question was created. + * @property {string} delimeter - Delimeter string that separates problem description section to code. + */ + +/** + * Generates a new question object. + * @param {string} topic - The topic of the question. + * @param {"Easy" | "Medium" | "Hard"} difficultyLevel - The difficulty level. + * @param {string} [language="General"] - The programming language (default is "General"). + * @returns {Question | null} The new question object if valid, otherwise null. + */ +async function generateNewQuestion(topic, difficultyLevel, customPrompt, language = "c,cpp,go,python") { + let israndomtopic = false; + // Validate topic and difficultyLevel + if (!topic) { + topic = "Any one Random topic form "+topics.slice(0, -1).join(", "); + israndomtopic = true; + } + if (!["Easy", "Medium", "Hard"].includes(difficultyLevel)) { + alert("Invalid difficulty level! Must be one of: Easy, Medium, Hard."); + return null; + } + + let storedQuestions = JSON.parse(localStorage.getItem('questions')) || []; + // Extract the list of previous question names + let previousTitles = storedQuestions.map(q => q.name).join(", "); + + const prompt = `Generate a unique data structure and algorithm coding question based on these criteria: + +- **Topic:** ${topic} +- **Difficulty Level:** ${difficultyLevel} +- **Programming Languages:** ${language} + +### **Question Requirements**: +1. The question should be a real-world problem related to the given topic. +2. The problem should have a **clear problem statement** with necessary constraints. +3. **Do not explicitly mention the topic** in the title or description. The user should figure it out after reading. +4. Strictly Format the description so that **no line exceeds 100 characters** for better readability. +5. Use **stick figure drawings** whenever necessary to visually explain the problem. +6. Provide at least **two sample test cases** in the question description. +7. Ensure the problem is suitable for implementation in these languages(comma separated): ${language}. +8. **Do NOT generate a question with any of these already generated questions(comma separated):** + ${previousTitles ? previousTitles : ""} +${customPrompt ? customPrompt : ""} + +### **Output Format**: +\`\`\`json +{ + "title": "Title of the problem", + "description": "Detailed problem description with sample test cases...", + "code_templates": { // generate template for each language in ${language} + "language name": { + "template": "Provide a function signature and a main function to verify the solution.", + "multiline_comment_start": "String for multiline comment start.", + "multiline_comment_end": "String for multiline comment end." + } + } +} +\`\`\` +**Ensure that the output strictly follows the JSON format above** +`; + + // Create a loader element and add it to the page + const loader = document.createElement("div"); + loader.classList.add("loader"); + + const modal = document.getElementById("modal"); + modal?.appendChild(loader); // Appends only if modal exists + + try { + const response = await getResponseFromOpenAI(openai_access_token, prompt, {baseUri: "/chat/completions"}); + + if (!response.ok) { + throw new Error(`API request failed with status ${response.status}: ${response.statusText}`); + } + + const data = await response.json(); + + if (data.choices?.length > 0 && data.choices[0].message?.content) { + const sanitizedJSON = sanitizeJSONString(data.choices[0].message.content); + if (!sanitizedJSON) { + throw new Error("invalid response json"); + } + const generatedQuestion = JSON.parse(sanitizedJSON); // Parse the response as JSON + const name = generatedQuestion.title.trim(); + // Generate a unique ID based on the current timestamp + let addedEpoch = Date.now(); + let nameHyphenated = name.toLowerCase().replace(/\s+/g, "-"); + let id = addedEpoch.toString(); // Unique ID + if (israndomtopic) { + topic = "Random Topic"; + } + // Create new question object and return + return { + id, + name, + nameHyphenated, + topic, + difficulty: difficultyLevel, + description: generatedQuestion.description, + code_templates: generatedQuestion.code_templates, + added: addedEpoch, + delimeter: " Welcome to OpenREPL!! you can start coding here. ", + }; + } else { + throw new Error("No content returned from OpenAI API."); + } + } catch (error) { + console.error("Error fetching new question:", error); + alert("Error fetching new question, error:"+error.message); + return null; + } finally { + // Remove the loader after completion (success or failure) + loader.remove(); + } +} + +/** + * Retrieves a code template for a given problem and language. + * @param {string} nameHyphenated - The hyphenated name of the problem. + * @param {string} language - The programming language. + * @returns {Object|null} The code template for the given language or null if not found. + */ +async function getCodeTemplate(nameHyphenated, language) { + // Fetch stored questions + let storedQuestions = JSON.parse(localStorage.getItem("questions")) || []; + + // Find the question by nameHyphenated + let question = storedQuestions.find(q => q.nameHyphenated === nameHyphenated); + + if (!question) { + console.error("Question not found: ", nameHyphenated); + alert("Question not found: "+nameHyphenated+", Cick on 'New Question' to Add a new question.") + return null; + } + + // Check if the code template already exists for the given language + if (question.code_templates && question.code_templates[language]) { + return question.code_templates[language]; + } + + // Construct OpenAI prompt + const prompt = `Generate a code template for solving the following problem: + +### **Problem Title**: ${question.name} + +### **Problem Description**: +${question.description} + +### **Output Format**: +The output should be a valid JSON object containing a code template for **${language}**. + +Ensure that: +1. The template includes a function signature. don't implement it. +2. It contains a main function that demonstrates how to call the function. +3. Use the correct comment syntax for the given language. +4. Do not repeat the prompt text in the output. +5. The response must be in **valid JSON format**. + +### **Output Format**: // generate only json part only +\`\`\`json +{ + "${language}": { + "template": "", + "multiline_comment_start": "", + "multiline_comment_end": "" + } +} +\`\`\` +**Ensure that the output strictly follows the JSON format above, with "${language}" as the key.** +`; + + try { + const response = await getResponseFromOpenAI(openai_access_token, prompt, {baseUri: "/chat/completions"}); + + if (!response.ok) { + throw new Error(`API request failed with status ${response.status}: ${response.statusText}`); + } + + const data = await response.json(); + if (data.choices?.length > 0 && data.choices[0].message?.content) { + console.log("unsanitized json: ", data.choices[0].message?.content); + const sanitizedJSON = sanitizeJSONString(data.choices[0].message.content); + + if (!sanitizedJSON) { + throw new Error("Invalid JSON response from OpenAI."); + } + + console.log("sanitized json: ", sanitizedJSON); + const generatedTemplate = JSON.parse(sanitizedJSON); + + // Ensure the response contains the expected structure + if (!generatedTemplate[language]) { + throw new Error(`No template found for language: ${language}`); + } + + // Update the stored question with the new template + question.code_templates[language] = generatedTemplate[language]; + + // Save the updated questions list back to localStorage + localStorage.setItem("questions", JSON.stringify(storedQuestions)); + + return generatedTemplate[language]; + } else { + throw new Error("No valid content returned from OpenAI API."); + } + } catch (error) { + console.error("Error fetching code template:", error); + return null; + } +} + + +// common App (function commonApp() { // body... var topNav = get('.menu'); diff --git a/src/resources/js/scribbler-misc.js b/src/resources/js/scribbler-misc.js new file mode 100644 index 00000000..2a8e7696 --- /dev/null +++ b/src/resources/js/scribbler-misc.js @@ -0,0 +1,230 @@ + +// other App +(function otherApp() { + $(document).ready(function() { + // update the modal topics + const $topicSelect = $("#topic"); + topics.forEach(topic => { + $topicSelect.append(``); + }); + + // Initialize DataTable. Column 4 (Last Added) is treated as number. + let table = $('#questionsTable').DataTable({ + "scrollX": true, // Enables horizontal scrolling + "columnDefs": [ + { targets: [0, 5], orderable: false }, + ], + order: [[4, 'desc']], // Default sorting: Most recent questions first + "responsive": true, // Enable responsive behavior + "autoWidth": false, // Prevent automatic width expansion + "language": { + "emptyTable": "No coding questions available. Please click on 'New Question' to add new questions." + } + }); + + // Retrieve stored data from localStorage. + let bookmarkedRows = JSON.parse(localStorage.getItem('bookmarkedRows')) || []; + let storedQuestions = JSON.parse(localStorage.getItem('questions')) || []; + + // Update bookmark checkboxes and (in default mode) reorder rows so that pinned rows come first. + function updateBookmarks() { + let currentSort = $('#sortBy').val(); + let nonBookmarkedRows = []; + let bookmarkedRowsList = []; + + $('#questionsTable tbody tr').each(function() { + let rowId = $(this).attr('data-id'); + let checkbox = $(this).find('.bookmark'); + + if (bookmarkedRows.includes(rowId)) { + checkbox.prop('checked', true); + $(this).addClass('bookmarked-row'); + bookmarkedRowsList.push($(this)); // Collect bookmarked rows + } else { + checkbox.prop('checked', false); + $(this).removeClass('bookmarked-row'); + nonBookmarkedRows.push($(this)); // Collect non-bookmarked rows + } + }); + + // Sort non-bookmarked rows in descending order of `data-added` + nonBookmarkedRows.sort((a, b) => { + return parseInt($(b).attr('data-added')) - parseInt($(a).attr('data-added')); + }); + + // Append sorted non-bookmarked rows first + nonBookmarkedRows.forEach(row => $('#questionsTable tbody').append(row)); + + // Append bookmarked rows to the bottom + bookmarkedRowsList.forEach(row => $('#questionsTable tbody').append(row)); + } + + + // Load stored questions and add them to the table. + function loadStoredQuestions() { + storedQuestions.forEach(q => addQuestionRow(q)); + } + + // Add a question row to the DataTable. + function addQuestionRow(q) { + // The "Last Added" cell displays a human-readable date/time (using toLocaleString) + // and uses a data-order attribute (with the epoch timestamp) for sorting. + let newRow = ` + + ${q.name} + ${q.topic} + ${q.difficulty} + ${new Date(q.added).toLocaleString()} + + `; + table.row.add($(newRow)).draw(false); + // Move newly added rows to the top + let lastIndex = table.rows().count() - 1; + let newRowNode = table.row(lastIndex).node(); + $(newRowNode).prependTo('#questionsTable tbody'); + + updateBookmarks(); + + // Ensure the topic is added to the filter dropdown if it's new + if ($("#topicsFilter option[value='" + q.topic + "']").length === 0) { + $("#topicsFilter").append(``); + } + + // Ensure the difficulty level is added to the filter dropdown if it's new + if ($("#difficultyFilter option[value='" + q.difficulty + "']").length === 0) { + $("#difficultyFilter").append(``); + } + } + + // Handle bookmark checkbox changes. + $('#questionsTable tbody').on('change', '.bookmark', function() { + let row = $(this).closest('tr'); + let rowId = row.attr('data-id'); + if ($(this).prop('checked')) { + bookmarkedRows.push(rowId); + } else { + bookmarkedRows = bookmarkedRows.filter(id => id !== rowId); + } + localStorage.setItem('bookmarkedRows', JSON.stringify(bookmarkedRows)); + updateBookmarks(); + }); + + // Handle row deletion. + $('#questionsTable tbody').on('click', '.delete-btn', function() { + let row = $(this).closest('tr'); + let rowId = row.attr('data-id'); + storedQuestions = storedQuestions.filter(q => q.id !== rowId); + localStorage.setItem('questions', JSON.stringify(storedQuestions)); + bookmarkedRows = bookmarkedRows.filter(id => id !== rowId); + localStorage.setItem('bookmarkedRows', JSON.stringify(bookmarkedRows)); + table.row(row).remove().draw(); + updateBookmarks(); + }); + + // Handle sort/filter changes. + $('#sortBy').on('change', function() { + let selectedSort = $(this).val(); + if (selectedSort === "recent") { + // Sort by the epoch timestamp (descending). + table.order([4, 'desc']).draw(); + } else if (selectedSort === "") { + // Default case: clear filters and then move bookmarked rows to the top. + table.search('').columns().search('').draw(); + updateBookmarks(); + } else { + // Filter by difficulty level. + table.column(3).search(selectedSort).draw(); + } + }); + + // Handle random question button. + $('#randomQuestionBtn').click(function() { + if (storedQuestions.length === 0) { + alert("No questions available!"); + return; + } + let randomIndex = Math.floor(Math.random() * storedQuestions.length); + let randomQuestion = storedQuestions[randomIndex]; + window.open(`/practice?name=${randomQuestion.nameHyphenated}`, "_blank"); + }); + + // Initialize by loading stored questions. + loadStoredQuestions(); + updateBookmarks(); + $("#topic").select2({ + placeholder: "Search or Select a Topic", + allowClear: true + }); + + // Modal + const open = document.getElementById("newQuestionBtn"); + const close = document.getElementById("close"); + const modal = document.getElementById("modal"); + const button = document.getElementById("qsubmit-btn"); + open.addEventListener("click", () => modal.classList.add("show-modal")); + button.addEventListener("click", function(event) { + event.preventDefault(); // Prevent form submission + $("#temperature").val(globaltemperature); + + // Get values from form inputs + let topic = document.getElementById("topic").value.trim(); + let difficultyLevel = document.getElementById("difficulty").value.trim(); + let customPrompt = document.getElementById("customPrompt").value.trim(); + let tempValue = parseFloat($("#temperature").val()); + if (!isNaN(tempValue)) { + globaltemperature = tempValue; + localStorage.setItem("temperature", tempValue); // Save to localStorage + } + + // Call the function and handle the Promise + generateNewQuestion(topic, difficultyLevel, customPrompt) + .then(newQuestion => { + if (!newQuestion) { + return; + } + + // Store and display the new question + let result = saveNewQuestions(newQuestion); + + if (result.error === null) { + addQuestionRow(newQuestion); + console.log("New question added:", newQuestion); + storedQuestions = result.storedQuestions; + } else { + alert("Error occurred while saving new question: " + result.error); + } + modal.classList.remove("show-modal"); + }) + .catch(error => { + console.error("Error generating a new question:", error); + alert("An unexpected error occurred while generating a new question."); + }); + }); + + close.addEventListener("click", () => modal.classList.remove("show-modal")); + window.addEventListener("click", (e) => + e.target == modal ? modal.classList.remove("show-modal") : false + ); + + $('.filter-select').select2(); // Enhance dropdowns with search + + // Filtering logic + $(".filter-select").on("change", function () { + table.draw(); // Refresh table when dropdowns change + }); + + // Custom filtering for DataTables + $.fn.dataTable.ext.search.push(function (settings, rowData) { + let topicsFilter = $('#topicsFilter').val().toLowerCase(); + let difficultyFilter = $('#difficultyFilter').val().toLowerCase(); + + let topics = rowData[2].toLowerCase(); + let difficulty = rowData[3].toLowerCase(); + + return ( + (topicsFilter === "" || topics.includes(topicsFilter)) && + (difficultyFilter === "" || difficulty.includes(difficultyFilter)) + ); + }); + }); +})(); \ No newline at end of file diff --git a/src/resources/js/scribbler.js b/src/resources/js/scribbler.js index 7c50f462..b0135901 100755 --- a/src/resources/js/scribbler.js +++ b/src/resources/js/scribbler.js @@ -101,7 +101,7 @@ function getSelectValue() { return option.value; } } - return ''; + return 'c'; } function getjidstr() { @@ -786,7 +786,10 @@ function uploadFile() { i=0; }); setTimeout(PrintGithub, 200, obj["Demo"]["Github"]); - setTimeout(updateEditorContent, 200, cmd, obj["Demo"]["Content"]); + if (!window.location.pathname.includes("practice")) { + // don't override the questions + setTimeout(updateEditorContent, 200, cmd, obj["Demo"]["Content"]); + } setTimeout(PrintUsage, 400, obj["Demo"]["Usage"],obj["Demo"]["Doc"],cmd); } else { console.log("Error: Unable to render Demo and Usage"); diff --git a/src/resources/practice.html b/src/resources/practice.html new file mode 100644 index 00000000..3c0a1ac4 --- /dev/null +++ b/src/resources/practice.html @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + About OpenREPL - An online REPL/Interpreter Platform | OpenREPL + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Top Coding Interview Questions

+
+
+ + +
+
+ + +
+
+ + + + + + + + + + + + + +
Mark CompletedName + + + + Last AddedDelete
+
+
+ + + +
+ About + References + + + ©OpenREPL +
+ + + + diff --git a/src/server/db.go b/src/server/db.go index 0c70d220..0abd5ee4 100644 --- a/src/server/db.go +++ b/src/server/db.go @@ -396,3 +396,37 @@ func handleUserProfile(rw http.ResponseWriter, req *http.Request) { } +func handlePracticeQuestions(rw http.ResponseWriter, req *http.Request) { + log.Println("handlePracticeQuestions: method:", req.Method) + if req.Method == "GET" { + req.ParseForm() + for key, val := range req.Form { + log.Println("%s: %s", key, val); + } + + practiceData, err := Asset("static/practice.html") + if err != nil { + log.Println("Error : practice template not found") // must be in bindata + errorHandler(rw, req, "404 Page Not Found", http.StatusNotFound) + return + } + practiceTemplate, err := template.New("practice").Parse(string(practiceData)) + if err != nil { + log.Println("practice template parse failed") // must be valid + errorHandler(rw, req, "404 Page Not Found", http.StatusNotFound) + return + } + + // Render the template (pass data if needed, or nil for no data) + if err := practiceTemplate.Execute(rw, nil); err != nil { + log.Println("Error executing practice template:", err) + errorHandler(rw, req, "Internal Server Error", http.StatusInternalServerError) + return + } + } else if req.Method == "POST" { + log.Println("Error: invalid request type: POST") + errorHandler(rw, req, "Invalid Request Method", http.StatusBadRequest) + return + } +} + diff --git a/src/server/server.go b/src/server/server.go index f4f88379..9ef936bc 100755 --- a/src/server/server.go +++ b/src/server/server.go @@ -194,7 +194,8 @@ func (server *Server) setupHandlers(ctx context.Context, cancel context.CancelFu var siteMux = http.NewServeMux() siteMux.HandleFunc(pathPrefix, server.handleIndex) - //siteMux.HandleFunc(pathPrefix+"practice", server.handleIndex) + siteMux.HandleFunc(pathPrefix+"practice/dsa-questions", handlePracticeQuestions) + siteMux.HandleFunc(pathPrefix+"practice", server.handleIndex) siteMux.HandleFunc(pathPrefix+"feedback", handleFeedback) siteMux.HandleFunc(pathPrefix+"blog", handleBlog) siteMux.HandleFunc(pathPrefix+"demo", handleDemo) diff --git a/src/server/utils.go b/src/server/utils.go index 61a51d71..6d8554eb 100644 --- a/src/server/utils.go +++ b/src/server/utils.go @@ -174,11 +174,11 @@ var CommonTemplate = ` - - + + - + @@ -198,7 +198,7 @@ var CommonTemplate = ` ©OpenREPL - + ` From 843f28acb5fc1b9fac2a2947e59a5a3370bcae61 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Wed, 12 Feb 2025 18:26:20 +0530 Subject: [PATCH 03/10] introdoc for practice dsa --- src/resources/index.html | 2 +- src/resources/js/scribbler.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/resources/index.html b/src/resources/index.html index 65202c14..9ae1f39f 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -199,7 +199,7 @@ - + diff --git a/src/resources/js/scribbler.js b/src/resources/js/scribbler.js index b0135901..8ccf4b4c 100755 --- a/src/resources/js/scribbler.js +++ b/src/resources/js/scribbler.js @@ -432,6 +432,11 @@ function StartTour() { element: document.querySelector('#callout_doc'), intro: 'Documentation on current REPL used.' }, + { + title: 'Practice dsa with AI', + element: document.querySelector('#practice_dsa'), + intro: 'follow this page to practice dsa questions with AI.' + }, { title: 'Fork this REPL', element: document.querySelector('#fork-widget'), From f898d0ba4f39f2481aa63424bd60fb92442d6893 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Wed, 12 Feb 2025 18:33:51 +0530 Subject: [PATCH 04/10] some more --- src/resources/index.html | 2 +- src/resources/practice.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resources/index.html b/src/resources/index.html index 9ae1f39f..7263ed9b 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -768,7 +768,7 @@

Share/Collaborate

- +
diff --git a/src/resources/practice.html b/src/resources/practice.html index 3c0a1ac4..dbeebdb2 100644 --- a/src/resources/practice.html +++ b/src/resources/practice.html @@ -129,7 +129,7 @@

Top Coding Interview Questions

- +
From 153bdc565e65e755fcf4697ed0f43db645ae482e Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Wed, 12 Feb 2025 21:48:39 +0530 Subject: [PATCH 05/10] removed unwanted ide message --- src/resources/js/scribbler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resources/js/scribbler.js b/src/resources/js/scribbler.js index 8ccf4b4c..7762a41a 100755 --- a/src/resources/js/scribbler.js +++ b/src/resources/js/scribbler.js @@ -1354,7 +1354,7 @@ $(function() { if (window[CONTENT_KEY]) { initalcontent = window[CONTENT_KEY]; } else { - initalcontent = "/* Welcome to openrepl! */\n/* Editor underdevelopment! */"; + initalcontent = "/* Welcome to openrepl! */"; } //get language from optionmenu From e518b8d6b7c215a26c5c798cea84c6c4e45381cc Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Wed, 12 Feb 2025 23:04:18 +0530 Subject: [PATCH 06/10] selected language --- src/resources/index.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/resources/index.html b/src/resources/index.html index 7263ed9b..fc135b7f 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -946,7 +946,7 @@

Share/Collaborate

console.log("New question added:", newQuestion); nameHyphenatedlatest = newQuestion.nameHyphenated; // reload with new name - window.open(`/practice?name=${nameHyphenatedlatest}`, "_self"); + window.open(`/practice?${selectedLanguage}&name=${nameHyphenatedlatest}`, "_self"); } else { alert("Error occurred while saving new question: " + result.error); } @@ -987,7 +987,8 @@

Share/Collaborate

} let randomIndex = Math.floor(Math.random() * storedQuestions.length); let randomQuestion = storedQuestions[randomIndex]; - window.open(`/practice?name=${randomQuestion.nameHyphenated}`, "_self"); + let selectedLanguage = $("#optionlist option:selected").text(); + window.open(`/practice?${selectedLanguage}&name=${randomQuestion.nameHyphenated}`, "_self"); }); }); From e666ed6f3cb5638b58e177d7fa0c54e075901c53 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Thu, 13 Feb 2025 21:48:12 +0530 Subject: [PATCH 07/10] assembly x86 --- install_prerequisite.sh | 16 +++- src/containers/container.go | 1 + src/resources/index.html | 3 +- src/resources/js/scribbler.js | 3 +- src/resources/meta/demos.xml | 143 ++++++++++++++++++++++++++++++++++ 5 files changed, 163 insertions(+), 3 deletions(-) diff --git a/install_prerequisite.sh b/install_prerequisite.sh index 2ae3e5c8..c13f6256 100755 --- a/install_prerequisite.sh +++ b/install_prerequisite.sh @@ -137,7 +137,20 @@ else rm -rf evcxr-v0.17.0-x86_64-unknown-linux-gnu fi - +#install rappel, nasm and set all the required dependencies +if [ -e "/usr/local/bin/rappel" ]; then + echo "File /usr/local/bin/rappel exists." +else + echo "File /usr/local/bin/rappel does not exist. installing..." + apt-get install -y --no-install-recommends libedit-dev + apt-get install -y --no-install-recommends nasm + git clone https://github.com/yrp604/rappel.git + cd rappel + make + ln -s $GOTTY_DIR/rappel/bin/rappel /usr/local/bin/rappel + chmod 755 /usr/local/bin/rappel + cd .. +fi #install gointerpreter git clone https://github.com/vickeykumar/Go-interpreter.git @@ -236,6 +249,7 @@ if [ $run_tests -eq 1 ]; then "sqlite3 --version" "tsc --version" "ts-node --version" + "echo "nop" | rappel" ) diff --git a/src/containers/container.go b/src/containers/container.go index 27fa4706..e78833c1 100644 --- a/src/containers/container.go +++ b/src/containers/container.go @@ -35,6 +35,7 @@ var Commands2memLimitMap = map[string]int64{ "evcxr": 50, // rust REPL "sqlite3": 10, "ts-node": 50, + "rappel": 2, } var memLimitMutex sync.Mutex diff --git a/src/resources/index.html b/src/resources/index.html index fc135b7f..9909dee7 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -241,6 +241,7 @@

OpenTcl +
@@ -360,7 +361,7 @@

Welcome to OpenREPL

- + diff --git a/src/resources/js/scribbler.js b/src/resources/js/scribbler.js index 7762a41a..72f09868 100755 --- a/src/resources/js/scribbler.js +++ b/src/resources/js/scribbler.js @@ -1443,7 +1443,8 @@ $(function() { 'tcl': 'tcl', 'rs': 'rust', 'sql': 'sql', - 'ts': 'typescript' + 'ts': 'typescript', + 'asm': 'assembly_x86' }; const imageext = ['jpg', 'jpeg', 'gif', 'png', 'bmp', 'webp', 'svg', 'ico']; const archiveext = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2']; diff --git a/src/resources/meta/demos.xml b/src/resources/meta/demos.xml index 10472ae6..f9a8bfc9 100644 --- a/src/resources/meta/demos.xml +++ b/src/resources/meta/demos.xml @@ -2260,6 +2260,149 @@ if [ $? -eq 0 ] && [ -f "$WORKDIR/$FILE" ]; then fi fi printf "\n"; +sleep 0.05 + + + + + + rappel + https://github.com/yrp604/rappel + https://cs.lmu.edu/~ray/notes/nasmtutorial/ + + + > + .help + Commands: +.quit - quit +.help - display this help +.info - display registers +.begin - start a block, input will not be assembled/run until '.end' +.end - assemble and run the prior block +.showmap - shortcut for cat /proc/<pid>/maps +.allregs <on|off> - toggle all register display +.read <address> [amount] - read <amount> bytes of data from address using ptrace [16] +.write <address> <data> - write data starting at address using ptrace + + + + + + > + inc rax + rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000 +rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000 +rip=0000000000400004 rsp=00007ffdedb264a0 rbp=0000000000000000 + r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 +r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 +r14=0000000000000000 r15=0000000000000000 +[cf:0, zf:0, of:0, sf:0, pf:0, af:0, df:0] +cs=0033 ss=002b ds=0000 es=0000 fs=0000 gs=0000 efl=00000202 + + + > + push rax + rax=0000000000000001 rbx=0000000000000000 rcx=0000000000000000 +rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000 +rip=0000000000400002 rsp=00007ffdedb26498 rbp=0000000000000000 + r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 +r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 +r14=0000000000000000 r15=0000000000000000 +[cf:0, zf:0, of:0, sf:0, pf:0, af:0, df:0] +cs=0033 ss=002b ds=0000 es=0000 fs=0000 gs=0000 efl=00000202 + + + + + > + pop rbx + rax=0000000000000001 rbx=0000000000000001 rcx=0000000000000000 +rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000 +rip=0000000000400002 rsp=00007ffdedb264a0 rbp=0000000000000000 + r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 +r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 +r14=0000000000000000 r15=0000000000000000 +[cf:0, zf:0, of:0, sf:0, pf:0, af:0, df:0] +cs=0033 ss=002b ds=0000 es=0000 fs=0000 gs=0000 efl=00000202 + + + > + cmp rax, rbx + rax=0000000000000001 rbx=0000000000000001 rcx=0000000000000000 +rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000 +rip=0000000000400004 rsp=00007ffdedb264a0 rbp=0000000000000000 + r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 +r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 +r14=0000000000000000 r15=0000000000000000 +[cf:0, zf:1, of:0, sf:0, pf:1, af:0, df:0] +cs=0033 ss=002b ds=0000 es=0000 fs=0000 gs=0000 efl=00000246 + + + > + .quit + $ + + + + .help + Print command help + + + .quit + Quit evaluation and exit + + ;-------- Welcome to OpenREPL! --------- + +section .data + hello db 'Hello, World!', 0 + +section .text + global _start + +_start: + ; write Hello, World! to stdout + mov eax, 4 ; sys_write + mov ebx, 1 ; file descriptor 1 (stdout) + mov ecx, hello ; message to write + mov edx, 13 ; message length + int 0x80 ; call kernel + + ; exit the program + mov eax, 1 ; sys_exit + xor ebx, ebx ; exit code 0 + int 0x80 ; call kernel + + +COMPILER=nasm +FILE=test.asm +debug=false +WORKDIR=$HOME +if [ "$CompilerOption" = "debug" ]; then + debug=true; +fi + +if [ "$IdeFileName" != "" ]; then + WORKDIR=$(dirname "$IdeFileName"); + FILE=$(basename "$IdeFileName"); +else + echo $0|base64 --decode > "$WORKDIR/$FILE"; +fi + +cd $WORKDIR; +if [ $? -eq 0 ] && [ -f "$WORKDIR/$FILE" ]; then + $COMPILER -felf64 -o "$WORKDIR/$FILE".o "$WORKDIR/$FILE" $@; +fi + +if [ $? -eq 0 ] && [ -f "$WORKDIR/$FILE.o" ]; then + ld -o "$WORKDIR/$FILE".out "$WORKDIR/$FILE".o + if $debug; then + gdb "$WORKDIR/$FILE".out $@; + else + #second quoate with escape, as -c option takes a string argument. + $SHELL -c "\"$WORKDIR/$FILE\".out $@"; + fi +fi +printf "\n"; sleep 0.05 From 9757538a131be9743349ca4e1b5922c0597cf6e4 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Thu, 13 Feb 2025 23:15:48 +0530 Subject: [PATCH 08/10] chatwidget realtime ide content --- src/resources/chat-widget/src/index.ts | 19 ++++++++++++------- src/resources/index.html | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/resources/chat-widget/src/index.ts b/src/resources/chat-widget/src/index.ts index c30d754f..c44aef56 100644 --- a/src/resources/chat-widget/src/index.ts +++ b/src/resources/chat-widget/src/index.ts @@ -131,6 +131,16 @@ const MAX_HISTORY_SIZE = 20; // Initialize the conversationHistory array let conversationHistory: MessageType[] = []; +function getcurrentIDECode(): MessageType { + let idecodemsg = { + role: "system", + content: `Openrepl IDE/Editor real-time Code Content user is working on, + (refer this code whenever user ask to debug editor/ide + code without providing any code in message): `+ fetchEditorContent(), + } + return idecodemsg; +} + // Function to add a message to the conversation history function addMessageToHistory(role: string, content: string, uid: string=UID): void { if (role=="user") { @@ -138,12 +148,7 @@ function addMessageToHistory(role: string, content: string, uid: string=UID): vo content = `[${role}-${uid}] ` + content; if (conversationHistory.length >= NUM_MANDATORY_ENTRIES) { // update editors content to msg history everytime user writes/sends message - conversationHistory[NUM_MANDATORY_ENTRIES-1] = { - role: "system", - content: `Openrepl IDE/Editor real-time Code Content user is working on, - (refer this code whenever user ask to debug editor/ide - code without providing any code in message): `+ fetchEditorContent(), - } + conversationHistory[NUM_MANDATORY_ENTRIES-1] = getcurrentIDECode(); } } @@ -601,7 +606,7 @@ async function submit(e: Event) { const data = { ...config.user, model: config.model, - messages: conversationHistory, + messages: [...conversationHistory, getcurrentIDECode()], temperature: config.temperature, max_tokens: config.max_tokens, stream: config.responseIsAStream, diff --git a/src/resources/index.html b/src/resources/index.html index 9909dee7..b3666f64 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -902,9 +902,24 @@

Share/Collaborate

} } } + + // save current topic and difficultylevel + let topic = $("#topic").val().trim(); + let difficultyLevel = $("#difficulty").val().trim(); + + localStorage.setItem("topic", topic); + localStorage.setItem("difficultyLevel", difficultyLevel); } $(window).on("unload", SaveLastLanguageProgress); + const existingHandler = window.onbeforeunload; + window.onbeforeunload = function(event) { + // Call existing handler first (if any) + if (existingHandler) { + return existingHandler(event); + } + SaveLastLanguageProgress(); + }; $("#optionlist").on("change", function () { SaveLastLanguageProgress(lastSelectedLanguage); @@ -919,6 +934,11 @@

Share/Collaborate

const modal = document.getElementById("modal"); const button = document.getElementById("qsubmit-btn"); $("#temperature").val(globaltemperature); // one time init + + let savedTopic = localStorage.getItem("topic") || ""; + let savedDifficultyLevel = localStorage.getItem("difficultyLevel") || ""; + $("#topic").val(savedTopic).trigger('change'); + $("#difficulty").val(savedDifficultyLevel); button.addEventListener("click", function(event) { event.preventDefault(); // Prevent form submission From 15c5838c0fab6a6d3d10334c92ab90c494ff0b31 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Fri, 14 Feb 2025 15:19:39 +0530 Subject: [PATCH 09/10] load initial content --- src/resources/index.html | 48 +++++++++++++++-------------------- src/resources/js/scribbler.js | 12 ++++----- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/resources/index.html b/src/resources/index.html index b3666f64..941e905b 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -802,25 +802,21 @@

Share/Collaborate

} // Call getCodeTemplate to fetch the missing template - let editor = window["editor"]; - if( editor.env && editor.env.editor) { - editor = editor.env.editor; - getCodeTemplate(newQuestion.nameHyphenated, selectedLanguage, {temperature: globaltemperature}) - .then((language_template) => { - if (language_template) { - updateEditorContent(selectedLanguage, language_template.multiline_comment_start+"\n"+ - newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+newQuestion.description+"\n"+language_template.multiline_comment_end+"\n"+ - language_template.multiline_comment_start+"\n"+newQuestion.delimeter+"\n"+language_template.multiline_comment_end+"\n"+language_template.template+"\n\n\n\n", true); - } else { - console.error("Failed to fetch code template for:", selectedLanguage); - updateEditorContent(selectedLanguage, "/*\n"+newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+ newQuestion.description+"\n*/\n\n\n\n", true); - } - }) - .catch((error) => { - console.error("Error fetching code template:", error); - updateEditorContent(selectedLanguage, "/*\n"+newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+ newQuestion.description+"\n*/\n\n\n\n", true); - }); - } + getCodeTemplate(newQuestion.nameHyphenated, selectedLanguage, {temperature: globaltemperature}) + .then((language_template) => { + if (language_template) { + updateEditorContent(selectedLanguage, language_template.multiline_comment_start+"\n"+ + newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+newQuestion.description+"\n"+language_template.multiline_comment_end+"\n"+ + language_template.multiline_comment_start+"\n"+newQuestion.delimeter+"\n"+language_template.multiline_comment_end+"\n"+language_template.template+"\n\n\n\n", true); + } else { + console.error("Failed to fetch code template for:", selectedLanguage); + updateEditorContent(selectedLanguage, "/*\n"+newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+ newQuestion.description+"\n*/\n\n\n\n", true); + } + }) + .catch((error) => { + console.error("Error fetching code template:", error); + updateEditorContent(selectedLanguage, "/*\n"+newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+ newQuestion.description+"\n*/\n\n\n\n", true); + }); } // Get URL query parameters @@ -975,15 +971,11 @@

Share/Collaborate

let language_template = newQuestion.code_templates[selectedLanguage]; // update editor content - let editor = window["editor"]; - if( editor.env && editor.env.editor) { - editor = editor.env.editor; - if (language_template) { - updateEditorContent(language_template, language_template.multiline_comment_start+"\n"+newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+ newQuestion.description+"\n"+language_template.multiline_comment_end+"\n"+language_template.multiline_comment_start+"\n"+newQuestion.delimeter+"\n"+language_template.multiline_comment_end+"\n"+ - language_template.template+"\n\n\n\n", true); - } else { - fetchLanguageTmplAndSetEditorcode(newQuestion.nameHyphenated, selectedLanguage); - } + if (language_template) { + updateEditorContent(language_template, language_template.multiline_comment_start+"\n"+newQuestion.name+"\n\nDifficulty Level: "+ newQuestion.difficulty+ "\n\nProblem Description:\n"+ newQuestion.description+"\n"+language_template.multiline_comment_end+"\n"+language_template.multiline_comment_start+"\n"+newQuestion.delimeter+"\n"+language_template.multiline_comment_end+"\n"+ + language_template.template+"\n\n\n\n", true); + } else { + fetchLanguageTmplAndSetEditorcode(newQuestion.nameHyphenated, selectedLanguage); } }) .catch(error => { diff --git a/src/resources/js/scribbler.js b/src/resources/js/scribbler.js index 72f09868..e3d04103 100755 --- a/src/resources/js/scribbler.js +++ b/src/resources/js/scribbler.js @@ -1208,7 +1208,7 @@ $(function() { var openPageTimestamp = Date.now(); var editorInitialized = false; - const initializeEditorApp = (initalcontent="/* Welcome to openrepl! */") => { + const initializeEditorApp = (initialcontent) => { if (!editorInitialized) { //all init for editor goes here editorInitialized = true; @@ -1348,13 +1348,13 @@ $(function() { }); // If the editor doesn't exist already.... - if (initalcontent === null) { + if (!initialcontent) { // ...we will initialize a new one. // ...with this content: if (window[CONTENT_KEY]) { - initalcontent = window[CONTENT_KEY]; + initialcontent = window[CONTENT_KEY]; } else { - initalcontent = "/* Welcome to openrepl! */"; + initialcontent = "/* Welcome to openrepl! */"; } //get language from optionmenu @@ -1369,7 +1369,7 @@ $(function() { silent: true // trigger event only when told }, queue: {}, - content: initalcontent + content: initialcontent }); } @@ -1379,7 +1379,7 @@ $(function() { // ...then set the value // -1 will move the cursor at the begining of the editor, preventing // selecting all the code in the editor (which is happening by default) - editor.setValue(initalcontent, -1); + editor.setValue(initialcontent, -1); // ...then set applyingDeltas to false applyingDeltas = false; From 1b4b45ca2f2127ff2f25d3a6ad60edfc61804894 Mon Sep 17 00:00:00 2001 From: vickeykumar Date: Sat, 15 Feb 2025 18:52:49 +0530 Subject: [PATCH 10/10] save on run --- src/resources/index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/resources/index.html b/src/resources/index.html index 941e905b..30ca301c 100755 --- a/src/resources/index.html +++ b/src/resources/index.html @@ -916,6 +916,9 @@

Share/Collaborate

} SaveLastLanguageProgress(); }; + $("#play-button").on("click", function () { + SaveLastLanguageProgress(); + }); $("#optionlist").on("change", function () { SaveLastLanguageProgress(lastSelectedLanguage);