Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Problem Solver

A full-stack application designed to test kids and adults on mathematical problem-solving skills. The app presents math problems and allows users to ask clarifying questions via an OpenAI-powered chat interface to gather the necessary data before attempting a solution.

🏗 Architecture

The project is divided into two main parts: a Frontend client and a Backend API.

  • Frontend: A Single Page Application (SPA) built with Vue 3, Vite, Vue Router, and Pinia for state management. Styling is handled with SCSS and FontAwesome icons.
  • Backend: A Python Flask REST API utilizing uv for fast dependency management. It handles game logic, session progress, and integrates with the OpenAI API for answering user queries.
  • Database: PostgreSQL is used to persist game sessions, uploaded questions, and the chat history between users and the AI.

Data Flow

  1. A new game session is created via the backend (/api/game).
  2. The UI fetches the current math problem (/api/start), which may include text and images.
  3. Users can ask questions about the problem (/api/chat). The backend limits the AI to only provide short facts and explicitly forbids it from doing calculations for the user.
  4. The user submits their final answer (/api/answer). Correct answers progress the game, while incorrect answers may provide clues.

🚀 Running Locally

Prerequisites

1. Environment Variables

Create a .env file in the root of the project:

OPENAI_API_KEY=sk-...
# If running manually without Docker, also include:
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname

2. Start the Application

The easiest way to run the application seamlessly is using Docker Compose. It will spin up the frontend, backend, and PostgreSQL database automatically.

docker compose up --build

3. Database Initialization

Once the containers are running, open a new terminal and initialize the local database (this will drop existing tables and seed the initial questions):

./reset-database.sh

(This script runs docker compose exec backend uv run python3 -c "from src.database import *; reset_database(); upload_questions()". It will drop existing tables!)


🌍 Deploying to Heroku

This project is configured for automated deployment to Heroku using GitHub Actions. The application is built as a single Docker container (using Dockerfile.heroku) where the Flask backend also serves the compiled Vue frontend.

1. GitHub Secrets

To enable the CI/CD pipeline, add the following secrets to your GitHub repository (Settings > Secrets and variables > Actions > New repository secret):

  • HEROKU_API_KEY: Your Heroku API key (found in your Heroku Account Settings).
  • HEROKU_APP_NAME: The exact name of your Heroku app.

2. Heroku Configuration

Ensure your Heroku app has the following Config Vars set in the dashboard (Settings > Reveal Config Vars):

  • OPENAI_API_KEY: Your OpenAI API key.
  • DATABASE_URL: This will be automatically injected if you provision the Heroku Postgres add-on under the Resources tab.

3. Automatic Deployment

Every time you push or merge code to the main branch, the GitHub Actions workflow (.github/workflows/ci.yml) will:

  1. Check the code formatting and lint both the frontend and backend.
  2. Build the production Docker image.
  3. Push the image to the Heroku Container Registry and release it.

4. Initializing the Heroku Database

After your first deployment finishes successfully, you need to initialize the production database. You can do this using the Heroku CLI:

heroku run "uv run python3 -c \"from src.database import *; reset_database(); upload_questions()\"" -a <your-heroku-app-name>

Todo

  • Go through frontend, fix any obvious issues, inconsistencies or layout problems
  • Type Safety: Migrate the Vue frontend JavaScript files to TypeScript for enhanced developer experience and error checking.

Possible future ideas

  • Authentication & User Accounts: Allow users to create accounts to save their progress across multiple devices and sessions.
  • Internationalization (i18n): The system prompts in chat.py are currently hardcoded in Swedish. Extracting text strings and adding multi-language support would significantly broaden the audience.
  • Testing: Introduce unit and integration tests (e.g., pytest for the backend, and Vitest for the frontend).
  • Model Configuration: Update the OpenAI API model string. It currently points to a theoretical gpt-5-mini. This should be mapped to an existing model like gpt-4o-mini or pulled from environment variables.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages