<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sambhav Tawar</title>
    <description>The latest articles on DEV Community by Sambhav Tawar (@sambhav_tawar).</description>
    <link>https://dev.to/sambhav_tawar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3392995%2F1d59644a-8336-4e5c-a45d-28e94f4e0fd1.jpg</url>
      <title>DEV Community: Sambhav Tawar</title>
      <link>https://dev.to/sambhav_tawar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sambhav_tawar"/>
    <language>en</language>
    <item>
      <title>I Built a Subway Nutrition Calculator</title>
      <dc:creator>Sambhav Tawar</dc:creator>
      <pubDate>Sat, 04 Apr 2026 09:16:17 +0000</pubDate>
      <link>https://dev.to/sambhav_tawar/i-built-a-subway-nutrition-calculator-1108</link>
      <guid>https://dev.to/sambhav_tawar/i-built-a-subway-nutrition-calculator-1108</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4kq90vy6tbkmcbq7dns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb4kq90vy6tbkmcbq7dns.png" alt=" " width="800" height="312"&gt;&lt;/a&gt;&lt;br&gt;
A few months ago, I got tired of clicking through Subway’s website to figure out what I was actually eating. Their PDFs are fine if you want to look up one thing. But if you want to build a custom sandwich—add this bread, skip that cheese, double the chicken, then see how it fits into your daily calories good luck.&lt;/p&gt;

&lt;p&gt;So, I built this &lt;a href="https://subway-calorie-calculator.com/" rel="noopener noreferrer"&gt;calorie calculator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not a fancy app with a backend. Just a single HTML file with a ton of JavaScript, a massive JSON‑like data structure, and a stubborn refusal to let a bad UI ruin my lunch.&lt;/p&gt;

&lt;p&gt;I’m going to walk you through how I built it, what broke along the way, and what I’d do differently next time.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You’d have to manually add bread calories + meat calories + veggie calories (most are zero, but olives and avocado aren’t) + sauce calories. Then double it for footlong. Then remember that cheese adds fat and sodium. Then realize you forgot the salt and pepper.&lt;/p&gt;

&lt;p&gt;It’s tedious and error‑prone. And it’s exactly the kind of problem a simple web tool can solve.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Collecting the Data
&lt;/h2&gt;

&lt;p&gt;I needed a complete, consistent dataset. Every bread, every protein, every cheese, vegetable, condiment, seasoning, side, soup, dessert, and pre‑made sandwich. Plus, salads, wraps, protein pockets, and No Bready Bowls.&lt;/p&gt;

&lt;p&gt;I started with Subway’s official US &lt;a href="https://www.subway.com/en-us/-/media/northamerica/usa/nutrition/nutritiondocuments/2026/us_nutrition_en_1-2026.pdf" rel="noopener noreferrer"&gt;nutrition PDF&lt;/a&gt; (2026 version). Then I cross‑referenced with their online menu, third‑party aggregators, and even some store‑level ingredient sheets.&lt;/p&gt;

&lt;p&gt;Total items ended up at around 300+.&lt;br&gt;
Here’s the rough breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breads: 12&lt;/li&gt;
&lt;li&gt;Pre‑made sandwiches: 30+&lt;/li&gt;
&lt;li&gt;Proteins (a la carte): 20+&lt;/li&gt;
&lt;li&gt;Cheeses: 5&lt;/li&gt;
&lt;li&gt;Vegetables: 15&lt;/li&gt;
&lt;li&gt;Condiments: 25+ (each with Normal and Light versions)&lt;/li&gt;
&lt;li&gt;Seasonings: 3&lt;/li&gt;
&lt;li&gt;Sides: 2&lt;/li&gt;
&lt;li&gt;Salads: 25+&lt;/li&gt;
&lt;li&gt;Wraps: 25+&lt;/li&gt;
&lt;li&gt;No Bready Bowls: 25+&lt;/li&gt;
&lt;li&gt;Protein Pockets: 4&lt;/li&gt;
&lt;li&gt;Soups: 3&lt;/li&gt;
&lt;li&gt;Desserts: 7&lt;/li&gt;
&lt;li&gt;Sidekicks: 8
Each item needed the same set of nutrition fields:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calories, total fat, saturated fat, trans fat, cholesterol, sodium, Total carbs, dietary fiber, sugars, added sugars, Protein, Vitamin A (mcg), Vitamin C (mg), Calcium (mg), Iron (mg).&lt;/p&gt;

&lt;p&gt;I also tracked serving size in grams where available, though that’s mostly for reference.&lt;/p&gt;

&lt;p&gt;What I learned: Never trust a single source. Cross‑reference everything and if you’re building a public tool, be transparent about where the data comes from and what’s estimated.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Structuring the Data – The JavaScript Object That Runs Everything
&lt;/h2&gt;

&lt;p&gt;I built one massive JavaScript object called subwayMenu. It has arrays for each category: breads, proteins, cheeses, vegetables, condiments, etc.&lt;/p&gt;

&lt;p&gt;Here’s what a single bread item looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;javascript&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;artisan-italian-bread-6inch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6" Artisan Italian Bread&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;servingSize_g&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;calories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;210&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;totalFat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;saturatedFat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;transFat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;cholesterol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;sodium&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;380&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;totalCarbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;dietaryFiber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;sugars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;addedSugars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;protein&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;vitaminA_mcg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;vitaminC_mg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;calcium_mg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1040&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;iron_mg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;16.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bread&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every item follows the same structure. That’s critical because later I loop through these objects to calculate totals, display values, and filter by search.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The size multiplier logic:&lt;/strong&gt;&lt;br&gt;
For sandwiches, users can choose 6‑inch or footlong. The calculator multiplies bread, proteins, cheeses, vegetables, condiments, and seasonings by 2 when footlong is selected. Pre‑made sandwiches, salads, wraps, and bowls are already sized – they don’t get multiplied again. That logic lives in the calculateTotalNutrition function, where I check a sizeAffected flag for each category.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The quantity system:&lt;/strong&gt;&lt;br&gt;
Users can add multiple of the same item (e.g., double meat, extra cheese). I store quantities in a separate currentSelection object. For each category, it’s a dictionary mapping item IDs to integers. Zero means not selected.`&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;javascript&lt;br&gt;
let currentSelection = {&lt;br&gt;
    sandwichSize: '6inch',&lt;br&gt;
    bread: null,&lt;br&gt;
    proteins: {},&lt;br&gt;
    cheeses: {},&lt;br&gt;
    vegetables: {},&lt;br&gt;
    condiments: {},&lt;br&gt;
    // ... etc&lt;br&gt;
};&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
This structure makes it easy to add, remove, or adjust quantities without rebuilding the whole UI from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: The UI – Dropdowns, Tabs, and a Whole Lot of Dynamic Rendering
&lt;/h2&gt;

&lt;p&gt;I wanted the interface to be clean but powerful. No external libraries just plain HTML, CSS, and vanilla JavaScript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The layout:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Left side: Builder with collapsible categories (Bread, Proteins, Cheeses, etc.) and a tab switcher for different menu types (Sandwich, Salads, Wraps, etc.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w19lj2mp888p6qrpi3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w19lj2mp888p6qrpi3b.png" alt=" " width="646" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right side: Results section with a nutrition label, calorie progress bar, current selection list, and action buttons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fhparzpjh2gphaa37kz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fhparzpjh2gphaa37kz.png" alt=" " width="415" height="712"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tab system:&lt;/strong&gt;&lt;br&gt;
On mobile, tabs become a dropdown toggle. On desktop, they could have been buttons, but I kept the dropdown consistent across all devices to simplify CSS. The active tab determines which set of categories (sandwich builder vs. pre‑made salads vs. wraps) is visible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collapsible categories:&lt;/strong&gt;&lt;br&gt;
Each category (e.g., “Proteins”) is a &lt;/p&gt; with a header that toggles the content. I used a simple onclick handler (subwayToggleDropdown) that adds/removes an expanded class and rotates an SVG arrow.

&lt;p&gt;&lt;strong&gt;Search inside categories:&lt;/strong&gt;&lt;br&gt;
Every category has a search input that filters items client‑side. No backend calls. The subwaySearchCategory function reads the input, filters the items array, and calls populateCategory to re‑render only that section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The item list:&lt;/strong&gt;&lt;br&gt;
Each item is rendered as a row with a checkbox (or radio for bread), name, calories, and quantity controls (plus/minus buttons). The quantity buttons call subwayAdjustQuantity, which updates the currentSelection object and re‑renders the category and the current selection list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why re‑render instead of DOM manipulation?&lt;/strong&gt;&lt;br&gt;
Because it’s simpler, I rebuild the category HTML every time something changes. For a category with 20 items, that’s fine. For the whole page, I’d need to be more careful. But here, re‑rendering is fast enough that users don’t notice a delay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: The Nutrition Calculation
&lt;/h2&gt;

&lt;p&gt;The calculateTotalNutrition function is the heart of the tool.&lt;/p&gt;

&lt;p&gt;It does four things:&lt;/p&gt;

&lt;p&gt;Initializes a totals object with zeros for every nutrition field.&lt;/p&gt;

&lt;p&gt;Applies the size multiplier (2 for footlong) to categories that scale with sandwich size.&lt;/p&gt;

&lt;p&gt;Loops through every selected category – bread, proteins, cheeses, vegetables, condiments, etc. And adds the item’s nutrition multiplied by quantity and multiplier.&lt;/p&gt;

&lt;p&gt;Returns the final totals and a list of ingredients (for the ingredients section).&lt;/p&gt;

&lt;p&gt;The math is straightforward addition. No fancy rounding until the end, where I round to one decimal place to keep the display clean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tricky part:&lt;/strong&gt;&lt;br&gt;
Some items have tiny values (e.g., 0.5g fiber). When you multiply by quantity and size, you get fractions. I store everything as numbers and only round when displaying. That keeps internal calculations accurate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The FDA daily values:&lt;/strong&gt;&lt;br&gt;
I hardcoded a fdaDailyValues object based on a 2,000‑calorie diet. The nutrition label shows % Daily Value for each nutrient. I calculate that as (nutrient_value / fda_daily_value) * 100. For vitamins and minerals, I use the actual mcg/mg values and compare against the FDA standards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: The Current Selection Panel
&lt;/h2&gt;

&lt;p&gt;One thing I’ve always hated about other calculators: you add items, but you can’t see what you’ve added without scrolling back up.&lt;/p&gt;

&lt;p&gt;So, I added a “Current Selection” panel on the right side (bottom in mobile). It lists every item you’ve chosen, with quantity and calories. And here’s the kicker: each item has a small “X” button that removes it directly from the selection.&lt;/p&gt;

&lt;p&gt;That removal calls subwayRemoveItemFromSelection, which updates the currentSelection object, then re‑renders the affected category (to uncheck the item) and the selection panel itself.&lt;/p&gt;

&lt;p&gt;It’s a small quality‑of‑life feature, but it makes a huge difference when you’re tweaking a meal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: The Save Function
&lt;/h2&gt;

&lt;p&gt;I added a “Save Nutrition Data” button that exports everything as a plain text file.&lt;/p&gt;

&lt;p&gt;The subwaySaveNutritionInfo function:&lt;/p&gt;

&lt;p&gt;Calls calculateTotalNutrition to get current totals and ingredients.&lt;/p&gt;

&lt;p&gt;Builds a formatted string with meal details, ingredients, nutrition facts, and daily progress.&lt;/p&gt;

&lt;p&gt;Creates a Blob, generates a download link, and triggers a download.&lt;/p&gt;

&lt;p&gt;Shows a temporary “Saved!” feedback on the button.&lt;/p&gt;

&lt;p&gt;I chose plain text because it’s simple, works everywhere, and users can paste it into a note or spreadsheet. No external dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Broke (And How I Fixed It)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The bread radio group:&lt;/strong&gt;&lt;br&gt;
Originally, I used radio buttons (only one bread allowed). But dynamically re‑rendering radios with JavaScript and keeping their state was a nightmare. I switched to checkboxes but enforced “only one” in the selection logic. The UI still looks like radios, but under the hood, it’s a checkbox group with manual deselection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The footlong multiplier:&lt;/strong&gt;&lt;br&gt;
At first, I applied the multiplier to everything including pre‑made salads and wraps. That was wrong, Salads and wraps have their own fixed nutrition. I had to add a sizeAffected flag to each category and only multiply bread, proteins, cheeses, vegetables, condiments, and seasonings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Search resetting on item change:&lt;/strong&gt;&lt;br&gt;
Every time a user added or removed an item, the category would re‑render and lose the search term. I fixed that by storing the search term in a variable and re‑applying it after re‑render. The subwaySearchCategory function now caches the filtered results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The save button not working in some browsers:&lt;/strong&gt;&lt;br&gt;
Some browsers block programmatic clicks on download links. I switched to using a Blob and URL.createObjectURL, which works everywhere. Also added a fallback alert if something fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Building this calculator was a lesson in data wrangling, UI design for real‑world users, and the joy of solving your own problem.&lt;/p&gt;

&lt;p&gt;It’s not perfect and the code is a little messy. The data could be more complete, but it works. You can build a custom Subway meal, see exactly what you’re eating, and save it for later.&lt;/p&gt;

&lt;p&gt;If you’re a developer thinking about building a similar tool for another restaurant chain, here’s my advice:&lt;/p&gt;

&lt;p&gt;Start with the data: Clean, consistent data is 80% of the work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build the logic first then the UI:&lt;/strong&gt; Get the calculation engine working in the console before you worry about buttons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test with real users:&lt;/strong&gt; I handed this to a few friends and watched where they got confused. That’s how I learned about the footlong multiplier bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t overcomplicate it:&lt;/strong&gt; You don’t need a backend, a database, or a build system. A single HTML file with inline CSS and JS is fine for a tool like this.&lt;/p&gt;

&lt;p&gt;Now, whenever I walk into Subway, I know exactly what I’m ordering. And if I’m not sure, I open this calculator on my phone and build it before I get to the counter.&lt;/p&gt;

&lt;p&gt;That’s the whole point, tools should make your life easier, not harder.&lt;/p&gt;

&lt;p&gt;I hope this walkthrough helps someone else build something useful. And if you just wanted to use the calculator, well, now you know what’s under the hood.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Multi-Scale CGPA Calculator</title>
      <dc:creator>Sambhav Tawar</dc:creator>
      <pubDate>Mon, 28 Jul 2025 05:57:42 +0000</pubDate>
      <link>https://dev.to/sambhav_tawar/building-a-multi-scale-cgpa-calculator-208h</link>
      <guid>https://dev.to/sambhav_tawar/building-a-multi-scale-cgpa-calculator-208h</guid>
      <description>&lt;p&gt;As a developer passionate about creating tools that solve real-world problems, I recently built a comprehensive CGPA (Cumulative Grade Point Average) calculator. This project emerged from my own experience as a student struggling to calculate my academic performance accurately across different grading systems. In this article, I'll walk through the technical implementation, design decisions, and features of this open-source calculator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem Space&lt;/strong&gt;&lt;br&gt;
Academic grading systems vary significantly across institutions. While some universities use a 10-point scale, others use 4-point or 5-point systems. This creates confusion for students who need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculate their current semester GPA.&lt;/li&gt;
&lt;li&gt;Track cumulative performance (CGPA).&lt;/li&gt;
&lt;li&gt;Convert between different grading scales.&lt;/li&gt;
&lt;li&gt;Understand how specific courses impact their overall average.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Technical Stack
&lt;/h2&gt;

&lt;p&gt;The calculator is built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Vanilla HTML, CSS, and JavaScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Charts:&lt;/strong&gt; Chart.js for data visualization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Icons:&lt;/strong&gt; Font Awesome for UI elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics:&lt;/strong&gt; Google Analytics for usage tracking (non-intrusive)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; Static site deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Key Features Implemented
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Multi-Scale Support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gl0kttn04l06f0kol05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gl0kttn04l06f0kol05.png" alt="Multi scale support feature" width="639" height="273"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const gradeOptionsByScale = {
  10: [ 
* grade options */ ],
  4: [ /* grade options */ ],
  5: [ /* grade options */ ]
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The calculator dynamically adjusts its interface based on the selected grading scale (4.0, 5.0, or 10.0), ensuring accurate calculations regardless of the institution's system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. College-Specific Presets&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const colleges = [
  { name: "Delhi University", scale: 10, location: "Delhi" },
  { name: "Ashoka University", scale: 4, location: "Sonipat" },
  // 15+ other institutions
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By selecting their college, students get automatically configured with the correct grading scale and grade descriptors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Dynamic Course Management&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createCourseCard(index, scale) {
  // Dynamically generates course input fields
}

function addCourse() {
  // Adds new course fields on demand
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interface allows students to add or remove courses as needed, with real-time validation and course count tracking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Visual Data Representation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvaietcl4n1geir3voshp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvaietcl4n1geir3voshp.png" alt="Visual Data Representation" width="658" height="801"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createGaugeChart(ctx, value, maxScale, title) {
  return new Chart(ctx, {
    type: 'doughnut',
    // Chart configuration
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Chart.js, the calculator displays results through intuitive doughnut charts that visually represent academic performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Calculation Transparency&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function showCalculationBreakdown() {
  // Generates detailed HTML table showing the math
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A comprehensive breakdown section shows students exactly how their GPA was calculated, building trust through transparency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Responsive Design&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@media (max-width: 768px) {
  /* Mobile-specific styles */
  .course-grid {
    grid-template-columns: 1fr;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The calculator works seamlessly on all devices using CSS Grid, Flexbox, and responsive design principles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Challenges and Solutions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Challenge 1: Dynamic Form Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Generating course inputs dynamically while maintaining state was tricky. I solved this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a template-based card generation system&lt;/li&gt;
&lt;li&gt;Using event delegation for efficient handling&lt;/li&gt;
&lt;li&gt;Storing state in DOM elements with data attributes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Challenge 2: Cross-Scale Calculations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculateCGPA() {
  // Handles different scales and conversions
  const currentScale = parseInt(cgpaScale.value) || 10;
  // Calculation logic
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The algorithm needed to handle:&lt;/li&gt;
&lt;li&gt;Different grading scales&lt;/li&gt;
&lt;li&gt;Previous CGPA integration&lt;/li&gt;
&lt;li&gt;Credit-weighted calculations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The solution was a flexible calculation function that normalizes all inputs to a common base.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 3: Responsive Data Tables&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.table-responsive {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the detailed breakdown tables, I implemented horizontal scrolling containers that work smoothly on mobile devices while maintaining readability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenge 4: Performance Optimization&lt;/strong&gt;&lt;br&gt;
To ensure smooth performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chart instances are properly destroyed before recreation&lt;/li&gt;
&lt;li&gt;DOM operations are minimized through batch updates&lt;/li&gt;
&lt;li&gt;Event listeners are delegated where possible&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  User Experience Considerations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Progressive Disclosure:&lt;/strong&gt; Advanced options (previous CGPA) are available but don't clutter the main interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual Feedback:&lt;/strong&gt; Animations and color-coded results help users understand their performance at a glance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Educational Content:&lt;/strong&gt; Integrated articles explain grading systems to help students understand the calculations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error Prevention:&lt;/strong&gt; Real-time validation prevents invalid inputs and provides helpful messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project/
├── index.html
├── style.css
└── script.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application follows a simple yet effective structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTML:&lt;/strong&gt; Semantic markup with proper ARIA attributes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS:&lt;/strong&gt; Modular design with CSS variables for theming.
3.&lt;strong&gt;JavaScript:&lt;/strong&gt; Modular functions with clear separation of concerns.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Building this CGPA calculator was a rewarding experience that combined technical challenges with practical utility. The project demonstrates how vanilla web technologies can create powerful, accessible tools without heavy frameworks.&lt;/p&gt;

&lt;p&gt;The complete tool is available on our &lt;a href="https://cgpacalculator.in/" rel="noopener noreferrer"&gt;site&lt;/a&gt; for anyone who wants to examine and test the tool.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
