# Project export: Simplicity

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Put in any topic/assignment, or even your syllabus, and get whole lessons on all prior knowledge and exactly what you need to know for your class. No more missing information or resource searching.
- Devpost: https://devpost.com/software/simplicity-yg6a7i
- GitHub: https://github.com/vishruthb/simplicity
- Demo: http://its12amandiwanttolearnsomething.com/
- Video: https://www.youtube.com/embed/WQvfau_W9D0?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Vishruth Bharath (12 commits)

## Devpost submission (written by the team)

### Inspiration

Have you ever gone to start a new assignment or learn a new coding framework but felt like you were missing gaps from prior knowledge that you saw years ago? How about trying to follow YouTube videos and not being sure if they are covering the correct part of the topic? This VS Code extension allows you to take any assignments, and then provides all knowledge needed to fill in the gaps and completely understand the assignment. No more wondering if you are missing required prior knowledge or unnecessarily complicated YouTube videos, learn exactly what you need through practice tailored directly to your necessities.

### What it does

Simplicity is an intelligent, project-based learning platform built directly into Visual Studio Code. It allows users to automatically generate tailored, hands-on learning plans for various programming languages. These learning plans focus on milestone-driven progress, with each step presented as a commented-out instructional guide within a generated playground file. Simplicity helps developers quickly ramp up on new languages or deepen their expertise by guiding them through real-world projects without ever leaving their coding environment.

### How we built it

We built Simplicity using TypeScript and integrated it as a VS Code extension. The extension interacts with the GROQ SDK to fetch dynamic learning content via the LLaMA 3 large language model, which generates comprehensive, language-specific milestones and instructional comments. We implemented file handling, workspace management, and automated content generation through the VS Code API, ensuring seamless integration with the developer’s workflow. The extension also dynamically comments out all instructional content to prevent code execution errors, utilizing specific syntax for any programming language.

### Challenges we ran into

A key challenge was efficiently managing workspace folders and file creation within the VS Code environment. Handling the creation of files in various languages while ensuring no raw code would lead to execution errors required carefully designing how comments were inserted based on language syntax. The prompt does not need to specify a language, but if one is specified the entire environment shifts around that language. Additionally, integrating the GROQ API for dynamic content generation while maintaining performance and responsiveness within the IDE was challenging, especially with rate limits and token size constraints in the model responses.

### Accomplishments we're proud of

We’re proud of successfully embedding a powerful learning tool directly into the VS Code ecosystem, enabling real-time, interactive project-based learning without leaving the editor. The seamless integration of the GROQ API and the efficient handling of multi-language support in a single extension is a major technical accomplishment. We also managed to optimize the extension’s performance to ensure minimal overhead on the developer’s environment, making it both practical and easy to use.

### What we learned

Through this project, we deepened our knowledge of the VS Code API, particularly in managing workspaces, files, and dynamically generated content. We gained experience with API rate limiting and learned best practices for leveraging large language models in real-time developer tools. Additionally, we learned how to make project-based learning more intuitive and developer-friendly by focusing on automated content generation that respects the user's coding workflow.

### What's next

Next, we plan to extend Simplicity’s functionality by introducing collaborative learning environments where multiple users can generate shared learning plans. We aim to enhance the generated content by integrating more detailed project blueprints, covering advanced programming paradigms such as concurrency, distributed systems, and machine learning. We also plan to incorporate more granular control over milestones, allowing users to set learning objectives based on specific technologies or frameworks.

## README (from the GitHub repository)

# Simplicity Extension for VS Code

Simplicity is an intelligent, project-based learning platform built directly into Visual Studio Code. It allows users to automatically generate personalized, hands-on learning plans for various programming languages. With milestone-driven progress, each step is presented as a commented-out instructional guide inside a generated playground file, making it easy to learn or deepen expertise without leaving the coding environment.

## Features

- Automatically generates learning plans based on user-defined goals.
- Supports multiple programming languages with smart inference from user prompts.
- Provides milestone-based challenges that increase in difficulty.
- Allows code evaluation and feedback directly in the playground file.
- Offers an additional feature to generate detailed explanations of topics or code snippets.

## Table of Contents

- [Setup](#setup)
- [Prerequisites](#prerequisites)
- [Configuring the Extension](#configuring-the-extension)
- [Usage](#usage)
- [Commands](#commands)
- [Technologies Used](#technologies-used)
- [How it Works](#how-it-works)

## Setup

### Prerequisites

Before using Simplicity, ensure you have the following installed and/or set-up:

- Groq API Key*
- Node.js (v14 or higher)
- npm

### Configuring the Extension

1. Clone the repository:

```bash
git clone https://github.com/vishruthb/simplicity/
cd simplicity
```

OR

Download the binary .vsix file from releases and install using command palette in VS Code.

2. Create the `config.json` file:
```json
{
  "groqApiKey": "<YOUR_GROQ_API_KEY>"
}
```

3. Install dependencies: `npm install`

4. Compile typescript to check for any errors: `npm run compile`

## Usage

### Commands

All interactions with the Simplicity extension are done via the Visual Studio Code Command Palette (`Ctrl + Shift + P` or `Cmd + Shift + P` on macOS). Below are the available commands:

- Simplicity: Initialize Learning Path
     - Starts the learning plan creation process.
- Simplicity: Validate User Code
    - Evaluates your code to see if it passes the current milestone’s test cases.
- Simplicity: Explain Topic
    - Generates a Markdown file that explains a programming topic or code snippet.

### Learning Path Workflow
1. Initialize Learning Path:
- Use `Simplicity: Initialize Learning Path` from the Command Palette.
- You will be prompted to describe what you'd like to learn, such as:
    - "Learning object-oriented programming in Java"
    - "Master data structures in Python"
Based on your prompt, Simplicity will infer the programming language and create the first milestone in a playground file (`playground.<language>`). Each milestone is a mini-task that helps you work towards your goal.

2. Work through Milestones:
- Each milestone is a new challenge or task that builds on the previous one.
- The playground file will contain commented-out instructions, including:
    - A problem description
    - Function signatures to implement
    - Test cases to pass

3. Evaluate Your Code:
- After completing the task in the playground file, use the `Simplicity: Validate User Code` command to check if your solution works.
- If successful, the next milestone will be automatically generated.
- If not, you’ll receive feedback to help debug your solution.

### Explanation Workflow
- Explain a Topic:
    - Use the `Simplicity: Explain Topic` command.
    - Enter a programming topic or code snippet that you want to understand better (e.g., "recursion in Python" or "how to use promises in JavaScript").
    - Simplicity will generate a detailed Markdown (.md) file with a concise explanation, a simple example, and a more advanced example. The examples are designed to teach the topic progressively.

## How it Works
### Intelligent Project-Based Learning
Simplicity’s core feature is its intelligent learning path generation. It creates personalized learning plans for various programming topics by:
- Understanding User Goals: You enter a natural-language prompt, and the extension uses Groq to infer the appropriate language and create milestones.
- Step-by-Step Progress: Milestones are designed to increase in difficulty, guiding users from beginner-level tasks to more complex challenges. Each task is provided with clear instructions, function signatures, and test cases.
- Adaptive Learning Experience: With all milestones and evaluations occurring within the VS Code playground file, users never have to leave their development environment to learn.

### Developer Tool Integration
Simplicity is designed as a developer tool for learning new languages or sharpening existing skills directly in VS Code. It integrates deeply with the IDE:
- Command Palette Integration: All interactions are done via the command palette, keeping the workflow simple and IDE-centric.
- Real-Time Code Evaluation: Once you’ve completed a milestone task, you can immediately test your solution by running the `Simplicity: Validate User Code` command, providing immediate feedback.
- Markdown Documentation: The `Explain Topic` command generates Markdown files, which are easy to read, edit, and share.

*Integrations for other providers coming soon! :)

## Detected evidence (automated analysis)

Indexed codebase: 6 recognized source files, 21 KB.
- JavaScript (language) — detected in the code
- TypeScript (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (15 of 15)

```
.gitignore
.vscode-test.mjs
.vscode/launch.json
.vscode/tasks.json
.vscodeignore
CHANGELOG.md
esbuild.js
eslint.config.mjs
LICENSE
media/main.js
package.json
README.md
src/extension.ts
src/test/extension.test.ts
tsconfig.json
```

### Dependencies

- package.json: @types/mocha@^10.0.9, @types/node@^14.17.0, @types/vscode@^1.60.0, esbuild@^0.12.29, eslint@^7.32.0, groq-sdk@^0.7.0, mocha@^10.7.3, typescript@^4.4.3

### Recent commits (newest first)

- update readme
- update readme
- added readme, quickfixes
- added new 'explain' command, fixed past issues
- added specified langs and env shifts
- added leveling
- revert changes
- stash for now
- saving progress for now, added icon lol
- update configs
- init
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### CHANGELOG.md

```markdown
# Change Log

All notable changes to the "simplicity" extension will be documented in this file.

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

## [Unreleased]

- Initial release
```

### package.json

```
{
  "name": "simplicity",
  "displayName": "Simplicity",
  "description": "learn simply",
  "version": "0.0.1",
  "publisher": "your-publisher-name",
  "engines": {
    "vscode": "^1.60.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "onCommand:simplicity.initLearningPath",
    "onCommand:simplicity.evaluateUserCode",
    "onCommand:simplicity.explainTopic"
  ],
  "main": "./dist/extension.js",
  "scripts": {
    "vscode:prepublish": "npm run package",
    "compile": "tsc -p ./",
    "package": "esbuild src/extension.ts --outdir=dist --bundle --platform=node --external:vscode",
    "watch": "esbuild src/extension.ts --outfile=dist/extension.js --bundle --watch --platform=node --external:vscode",
    "test": "npm run compile && node ./out/test/runTest.js"
  },
  "devDependencies": {
    "@types/mocha": "^10.0.9",
    "@types/node": "^14.17.0",
    "@types/vscode": "^1.60.0",
    "esbuild": "^0.12.29",
    "eslint": "^7.32.0",
    "mocha": "^10.7.3",
    "typescript": "^4.4.3"
  },
  "contributes": {
    "commands": [
      {
        "command": "simplicity.initLearningPath",
        "title": "Simplicity: Initialize Learning Path"
      },
      {
        "command": "simplicity.evaluateUserCode",
        "title": "Simplicity: Validate User Code"
      },
      {
        "command": "simplicity.explainTopic",
        "title": "Simplicity: Explain Topic"
      }
    ]
  },
  "dependencies": {
    "groq-sdk": "^0.7.0"
  }
}

```

### media/main.js

```javascript
const vscode = acquireVsCodeApi();

document.getElementById('submitText').addEventListener('click', () => {
  const text = document.getElementById('textInput').value;
  vscode.postMessage({ command: 'processInput', text });
});

document.getElementById('submitFile').addEventListener('click', () => {
  const fileInput = document.getElementById('fileInput');
  const file = fileInput.files[0];
  if (file) {
    const reader = new FileReader();
    reader.onload = (event) => {
      const fileData = event.target.result;
      vscode.postMessage({ command: 'processFile', fileData });
    };
    reader.readAsArrayBuffer(file);
  }
});

```

### esbuild.js

```javascript
const esbuild = require('esbuild');

esbuild.build({
  entryPoints: ['src/extension.ts'],
  bundle: true,
  outfile: 'dist/extension.js',
  platform: 'node',
  external: ['vscode'],
  format: 'cjs',
  sourcemap: true,
  watch: process.argv.includes('--watch'),
}).catch(() => process.exit(1));

```

### src/extension.ts

```typescript
import * as vscode from 'vscode';
import Groq from 'groq-sdk';
import * as path from 'path';
import * as fs from 'fs';

let groq: Groq | null = null;
let milestoneCounter = 1;  // Milestone counter, reset on extension restart
let inferredLanguage: string | null = null;  // Store inferred language globally

export function activate(context: vscode.ExtensionContext) {
  console.log('Simplicity extension is now active!');

  // Initialize Groq client using config.json
  const configPath = path.join(context.extensionPath, 'config.json');
  if (!fs.existsSync(configPath)) {
    vscode.window.showErrorMessage('config.json file not found. Please create a config.json file with your GROQ API key.');
    return;
  }

  let config: any;
  try {
    const configContent = fs.readFileSync(configPath, 'utf8');
    config = JSON.parse(configContent);
  } catch (error) {
    vscode.window.showErrorMessage('Failed to read config.json. Please ensure it is valid JSON.');
    return;
  }

  const groqApiKey = config.groqApiKey;
  if (!groqApiKey) {
    vscode.window.showErrorMessage('GROQ API Key is not set in config.json. Please add your API key.');
    return;
  }

  groq = new Groq({ apiKey: groqApiKey });

  // Register command for initializing the learning path
  let initLearningPathCmd = vscode.commands.registerCommand('simplicity.initLearningPath', async () => {
    milestoneCounter = 1; // Reset milestone counter on new start
    await initializeLearningPath();
  });

  // Register command for evaluating the user's solution
  let evaluateUserCodeCmd = vscode.commands.registerCommand('simplicity.evaluateUserCode', async () => {
    await evaluateUserCode();
  });

  // Register command for explaining a topic
  let explainTopicCmd = vscode.commands.registerCommand('simplicity.explainTopic', async () => {
    await explainTopic();
  });

    context.subscriptions.push(initLearningPathCmd, evaluateUserCodeCmd, explainTopicCmd);
  }

// Initialize learning path based on user prompt
async function initializeLearningPath() {
  const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
  if (!workspaceFolder) {
    vscode.window.showErrorMessage('No workspace folder found. Please open a folder in the workspace.');
    return;
  }

  // Prompt for the learning goal or topic in natural language
  const userPrompt = await vscode.window.showInputBox({
    prompt: 'What would you like to learn? Describe your goal.',
    placeHolder: 'e.g., Learning Data Structures and Algorithms in Python',
    validateInput: (text) => {
      return text ? null : 'Please enter a goal or topic.';
    },
  });

  if (!userPrompt) {
    vscode.window.showWarningMessage('No input was entered.');
    return;
  }

  // Infer the programming language from the user prompt
  inferredLanguage = await inferLanguageFromPrompt(userPrompt);  // Store the inferred language globally

  // Generate the first milestone based on the inferred language and user-provided topic
  await generateMilestone(inferredLanguage, milestoneCounter, userPrompt);
}

// Infer the programming language from the user's prompt using Groq
async function inferLanguageFromPrompt(prompt: string): Promise<string> {
  try {
    const messages = [
      { role: 'user', content: `Analyze this prompt and determine the programming language being referenced or implied: ${prompt}. With nothing else, just response with the one word name of the language BY ITSELF (e.g. c) or, if none is able to be determined, just responsd with "python".` }
    ];

    const response = await groq?.chat.completions.create({
      model: 'llama3-groq-8b-8192-tool-use-preview',
      messages: messages as any,
      temperature: 0.0, // Deterministic response
      max_tokens: 2500,
    });
    if (response?.choices && response.choices.length > 0) {
      const inferredLanguage = response.choices[0]?.message?.content?.trim().toLowerCase();
      console.log(`Inferred language: ${inferredLanguage}`);
      return inferredLanguage || 'python';
    }
    return 'python'; // Default to Python if language cannot be determined
  } catch (error) {
    console.error('Error inferring language from prompt:', error);
    return 'python'; // Fallback to Python
  }
}

// Generate or update the milestone in `playground.[extension]`
async function generateMilestone(language: string, milestoneNumber: number, topic: string) {
  const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
  if (!workspaceFolder) {
    vscode.window.showErrorMessage('No workspace folder found. Please open a folder in the workspace.');
    return;
  }

  // Generate content from Groq, passing the user topic for the milestone creation
  const milestoneContent = await generateMilestoneContent(language, milestoneNumber, topic);
  if (!milestoneContent) {
    vscode.window.showErrorMessage('Failed to generate the milestone.');
    return;
  }

  // Ensure the correct extension is used based on the inferred language
  const extension = getFileExtension(language) || 'py'; // Default to 'py' if language can't be determined
  const fileName = `playground.${extension}`;
  const filePath = path.join(workspaceFolder.uri.fsPath, fileName);
  const fileUri = vscode.Uri.file(filePath);

  // Comment out the content using language-specific syntax
  const commentedContent = commentOutContent(milestoneContent, language);

  try {
    // Delete the old file first before generating a new one
    await Promise.resolve(vscode.workspace.fs.delete(fileUri, { useTrash: false })).catch(() => {
      console.log(`File does not exist: ${fileName}, skipping deletion.`);
    });

    // Write the new milestone content to the playground file
    await vscode.workspace.fs.writeFile(fileUri, Buffer.from(commentedContent, 'utf8'));

    // Open the new file
    const document = await vscode.workspace.openTextDocument(fileUri);
    await vscode.window.showTextDocument(document);
  } catch (error) {
    vscode.window.showErrorMessage('Failed to create or open the 
[truncated — 8891 more characters]
```

### src/test/extension.test.ts

```typescript
import * as assert from 'assert';
import * as vscode from 'vscode';

suite('Extension Test Suite', () => {
  vscode.window.showInformationMessage('Start all tests.');

  test('Sample test', () => {
    assert.strictEqual(-1, [1, 2, 3].indexOf(5));
    assert.strictEqual(-1, [1, 2, 3].indexOf(0));
  });
});

```