DEV Community

Paulo Ricardo Engcompaulo
Paulo Ricardo Engcompaulo

Posted on

Trigonometry Visualizer

This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend

What I Built

I built Trigonometry Visualizer, a small Flask web app for my friend Marina, who recently went back to school and has been struggling to connect the trigonometry formulas in her textbook to what they actually look like. She kept telling me that y = sin(x) was just a string of symbols until someone drew the curve for her.

So the app does exactly that. The Learner picks one of five concepts — sine, cosine, tangent, right triangle, or unit circle — either from a dropdown or by typing it in, and the app renders a matplotlib figure with the mathematical formula embedded right in the picture. She can download any figure as a PNG to paste into her notes, and she can ask for a plain-English explanation of the concept generated by a local AI model. The whole thing is intentionally minimal and English-only, built to be genuinely useful for one person learning the basics rather than a sprawling math suite.

The core promise is graceful degradation: the figure, formula, and download always work even when the AI explainer is slow or offline, so a flaky model never gets in the way of studying.

Demo

Run it locally with Docker:

docker compose up
Enter fullscreen mode Exit fullscreen mode

Then open http://localhost:5000, choose a concept (try "sine" or " Unit Circle " — input is case- and whitespace-insensitive), view the figure and formula, click Download to save the PNG, and click Explain for a plain-English walkthrough.

A short screen recording of the render → download → explain flow will be attached to the DEV post.

Code

The full source lives in the desafio1/ project folder:

  • app.py — Flask routes: GET / (page), GET /render?concept=X[&download=1] (PNG), GET /explain?concept=X (JSON explanation)
  • concepts.py — the five-concept registry with normalization and validation
  • renderer.py — matplotlib Agg draw functions that embed each formula in the figure
  • explainer.py — the Ollama client that degrades gracefully on any failure
  • docs.py — validator for this very submission file
  • templates/, static/ — the HTML/CSS/JS frontend
  • Dockerfile, docker-compose.yml — the two-service (web + ollama) stack
SUPPORTED = ["sine", "cosine", "tangent", "right triangle", "unit circle"]
Enter fullscreen mode Exit fullscreen mode

The GitHub repository can be embedded directly in the DEV post.

How I Built It

The explanation feature is powered entirely by open-source AI: a local Ollama service running the open-weight llama3.2 model. The Flask web service talks to the ollama service over the docker-compose network at http://ollama:11434, posting the selected concept and its formula to /api/generate with stream: false.

Everything runs on your own machine — no third-party API keys, no cloud calls, no data leaving the container network. The explainer.py module wraps the call with a 30-second timeout and catches every failure mode (timeout, connection error, non-200 status, malformed JSON), returning a friendly "explanation unavailable" message instead of ever crashing. That way the open model enriches the experience when it's up, and the app stays fully usable when it isn't.

The rest of the stack is deliberately lean: Python 3.12, Flask for routing, matplotlib (Agg backend) for headless figure rendering, and requests for the Ollama client — all wired together bottom-up so each module is independently testable.

Why Does Open Innovation Matter?

Open innovation is what made this project possible as a weekend build for a single friend. Using an open-weight model through Ollama meant I could ship an AI tutor that costs nothing to run, needs no API key, and keeps a student's questions entirely on her own machine. A closed API would have added a billing account, rate limits, and a privacy footprint — all overkill for one person learning trig at her kitchen table.

More than cost, open models let me design for graceful degradation on my own terms: because the model runs locally and is swappable, I control the timeout, the fallback behavior, and even which model to pull. If llama3.2 is too heavy on an older laptop, swapping in a smaller open model is a one-line change. That kind of transparency and substitutability is exactly what open innovation unlocks — the app belongs to the people running it, not to a vendor's roadmap.

My Agent Session

I built this spec-first with Kiro: requirements → design → tasks, then implemented each module in dependency-wave order. The agent session covering the build will be linked from the DEV post.

Result: GITHUB

Prize Categories

  • Build for a Friend
  • Best use of a local, open-weight model (Ollama / llama3.2)

Top comments (0)