๐ŸณFermentation Calculator

Calculate ABV, gravity conversions, calories, and fermentation metrics for beer, wine, mead, and cider brewing with precision accuracy and AI assistance

๐Ÿค” What Is Fermentation Calculator?

Think of a brewing scientist in your pocket - that's the Fermentation Calculator! Calculate ABV, gravity readings, calories, and fermentation metrics for beer, wine, mead, and cider with precision. Get AI brewing assistance from ChatGPT and Claude for perfect batches every time!

๐Ÿบ Alcohol by Volume (ABV) Calculator

๐Ÿบ Enter your gravity readings to calculate ABV and fermentation metrics

โš–๏ธ Gravity & Unit Converter

โš–๏ธ Enter specific gravity to convert between Brix, Plato, and other units

๐Ÿ”ฅ Calorie & Carb Calculator

๐Ÿ”ฅ Enter gravity readings to calculate calories and carbohydrates

๐Ÿงช Yeast Pitch Rate Calculator

๐Ÿงช Enter batch details to calculate optimal yeast pitch rate

๐Ÿ“Š Attenuation Calculator

๐Ÿ“Š Enter gravity readings to calculate apparent and real attenuation

๐ŸŽฏ Try Sample Calculations

๐Ÿบ IPA Beer
OG: 1.065, FG: 1.012 โ†’ 7.0% ABV
๐Ÿท Red Wine
OG: 1.095, FG: 0.995 โ†’ 13.3% ABV
๐Ÿป Lager
OG: 1.048, FG: 1.008 โ†’ 5.3% ABV
๐Ÿฏ Mead
OG: 1.120, FG: 1.020 โ†’ 13.4% ABV
๐ŸŽ Cider
OG: 1.055, FG: 1.000 โ†’ 7.2% ABV
๐Ÿ–ค Stout
OG: 1.072, FG: 1.018 โ†’ 7.1% ABV
`; } function displayGravityResults(data) { const container = document.getElementById('gravityResult'); container.innerHTML = `
SG: ${data.correctedSG.toFixed(4)}
โœ… Temperature corrected from ${data.temperature}ยฐF
Specific Gravity (Corrected)
${data.correctedSG.toFixed(4)}
Brix
${data.brix.toFixed(1)}ยฐBx
Plato
${data.plato.toFixed(1)}ยฐP
Oechsle
${data.oechsle.toFixed(0)}ยฐOe
Baumรฉ
${data.baume.toFixed(1)}ยฐBรฉ
Potential Alcohol
${data.potentialAlcohol.toFixed(1)}%
`; } function displayCalorieResults(data) { const container = document.getElementById('calorieResult'); container.innerHTML = `
${data.totalCalories.toFixed(0)} calories
โœ… Per ${data.servingSize} oz serving (${data.abv.toFixed(1)}% ABV)
Total Calories
${data.totalCalories.toFixed(0)}kcal
From Alcohol
${data.alcoholCalories.toFixed(0)}kcal
From Carbs
${data.carbCalories.toFixed(0)}kcal
Carbohydrates
${data.carbGrams.toFixed(1)}g
Alcohol Content
${data.abv.toFixed(1)}% ABV
Serving Size
${data.servingSize}oz
`; } function displayPitchResults(data) { const container = document.getElementById('pitchResult'); // Calculate number of yeast packets needed (assuming 100 billion cells per packet) const packetsNeeded = data.totalCells / 100000000000; container.innerHTML = `
${data.pitchRate.toFixed(1)} M cells/mL/ยฐP
โœ… Optimal pitch rate calculated for ${data.plato.toFixed(1)}ยฐP wort
Pitch Rate
${data.pitchRate.toFixed(1)}M/mL/ยฐP
Cells per mL
${data.cellsPerMl.toFixed(1)}M
Total Cells Needed
${(data.totalCells / 1000000000).toFixed(0)}B
Yeast Packets
${packetsNeeded.toFixed(1)}packs
Wort Gravity
${data.plato.toFixed(1)}ยฐP
Recommendation
${Math.ceil(packetsNeeded)}packs
`; } function displayAttenuationResults(data) { const container = document.getElementById('attenuationResult'); container.innerHTML = `
${data.apparentAttenuation.toFixed(1)}% AA
โœ… Fermentation efficiency analysis completed
Apparent Attenuation
${data.apparentAttenuation.toFixed(1)}%
Real Attenuation
${data.realAttenuation.toFixed(1)}%
Alcohol Content
${data.abv.toFixed(1)}% ABV
Real Extract
${data.realExtract.toFixed(1)}ยฐP
Original Gravity
${data.og.toFixed(3)}
Final Gravity
${data.fg.toFixed(3)}
`; } // ========== COPY FUNCTIONS ========== function copyABVResults(abv, type) { const text = `${type.charAt(0).toUpperCase() + type.slice(1)} Analysis:\nABV: ${abv}%\nCalculated with WIA Pin Code Fermentation Calculator`; copyToClipboard(text); } function copyGravityResults(sg, brix, plato) { const text = `Gravity Conversion:\nSG: ${sg}\nBrix: ${brix}ยฐBx\nPlato: ${plato}ยฐP\nCalculated with WIA Pin Code Fermentation Calculator`; copyToClipboard(text); } function copyCalorieResults(calories, carbs, serving) { const text = `Nutrition Facts (${serving} oz):\nCalories: ${calories} kcal\nCarbohydrates: ${carbs}g\nCalculated with WIA Pin Code Fermentation Calculator`; copyToClipboard(text); } function copyPitchResults(rate, packets) { const text = `Yeast Pitch Rate:\n${rate} M cells/mL/ยฐP\nRecommended: ${packets} yeast packets\nCalculated with WIA Pin Code Fermentation Calculator`; copyToClipboard(text); } function copyAttenuationResults(apparent, real) { const text = `Attenuation Analysis:\nApparent: ${apparent}%\nReal: ${real}%\nCalculated with WIA Pin Code Fermentation Calculator`; copyToClipboard(text); } // ========== SAMPLE USAGE FUNCTIONS ========== function useSample(sampleId) { const samples = { 'ipa': { og: 1.065, fg: 1.012, type: 'beer' }, 'wine': { og: 1.095, fg: 0.995, type: 'wine' }, 'lager': { og: 1.048, fg: 1.008, type: 'beer' }, 'mead': { og: 1.120, fg: 1.020, type: 'mead' }, 'cider': { og: 1.055, fg: 1.000, type: 'cider' }, 'stout': { og: 1.072, fg: 1.018, type: 'beer' } }; const sample = samples[sampleId]; if (!sample) return; // Switch to ABV tab if not active if (currentTab !== 'abv') { switchTab('abv'); } // Fill in the values document.getElementById('originalGravity').value = sample.og; document.getElementById('finalGravity').value = sample.fg; document.getElementById('beverageType').value = sample.type; // Auto-calculate setTimeout(() => { calculateABV(); }, 100); // Highlight button const btn = document.getElementById('abvBtn'); btn.style.animation = 'pulse 0.5s ease-in-out'; setTimeout(() => btn.style.animation = '', 500); } // ========== UTILITY FUNCTIONS ========== // Copy to clipboard function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { showNotification('Copied to clipboard!', 'success'); }).catch(() => { // Fallback for older browsers const textArea = document.createElement('textarea'); textArea.value = text; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); showNotification('Copied to clipboard!', 'success'); }); } // Show error function showError(elementId, message) { const errorElement = document.getElementById(elementId); if (errorElement) { errorElement.textContent = message; errorElement.style.display = 'block'; } } // Clear errors function clearErrors(errorIds) { errorIds.forEach(id => { const element = document.getElementById(id); if (element) { element.textContent = ''; element.style.display = 'none'; } }); } // Clear all errors function clearAllErrors() { document.querySelectorAll('.error').forEach(el => { el.textContent = ''; el.style.display = 'none'; }); } // Show notification toast function showNotification(message, type = 'success') { const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.remove(); }, 3000); } // Show OTA section (dynamic) function showOTA() { const otaContainer = document.getElementById('otaContainer'); if (otaContainer && (otaContainer.style.display === 'none' || !otaContainer.style.display)) { otaContainer.style.display = 'block'; // Attention-grabbing pulse effect setTimeout(() => { const otaHeader = document.querySelector('.ota-header h3'); if (otaHeader) { otaHeader.style.animation = 'pulse 1s ease-in-out'; } }, 100); } } // Analytics tracking function trackEvent(eventName, data = {}) { if (typeof gtag !== 'undefined') { gtag('event', eventName, { 'event_category': TOOL_CONFIG.category, 'event_label': TOOL_CONFIG.name, ...data }); } } // ========== AI ASSISTANT FUNCTIONS ========== // AI ๋ชจ๋‹ฌ ์—ด๊ธฐ function openAIModal() { const modal = document.getElementById('aiModal'); if(modal) modal.classList.add('show'); // ํ˜„์žฌ ์ƒํƒœ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ํ™”๋ฉด ํ‘œ์‹œ if (aiModalState.apiKey && aiModalState.currentView === 'gemini') { showGeminiChat(); } else { showAISelector(); } updateAPIKeyStatus(); } // AI ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ function closeAIModal() { const modal = document.getElementById('aiModal'); if(modal) modal.classList.remove('show'); // 300ms ํ›„ ์ƒํƒœ ๋ฆฌ์…‹ (์• ๋‹ˆ๋ฉ”์ด์…˜ ์™„๋ฃŒ ํ›„) setTimeout(() => { aiModalState.currentView = 'selector'; showAISelector(); }, 300); } // AI ์„ ํƒ ํ™”๋ฉด ํ‘œ์‹œ function showAISelector() { document.getElementById('aiModalTitle').textContent = 'Choose Your AI Assistant'; document.getElementById('aiSelector').style.display = 'flex'; document.getElementById('geminiChat').style.display = 'none'; document.getElementById('apiKeySetup').style.display = 'none'; aiModalState.currentView = 'selector'; } // Gemini ์ฑ„ํŒ… ํ™”๋ฉด ํ‘œ์‹œ function showGeminiChat() { document.getElementById('aiModalTitle').innerHTML = 'โœจ Gemini AI Assistant'; document.getElementById('aiSelector').style.display = 'none'; document.getElementById('geminiChat').style.display = 'flex'; document.getElementById('apiKeySetup').style.display = 'none'; aiModalState.currentView = 'gemini'; // ์ดˆ๊ธฐ ๋ฉ”์‹œ์ง€๊ฐ€ ์—†์œผ๋ฉด ์ถ”๊ฐ€ const chatMessages = document.getElementById('chatMessages'); if (!chatMessages.innerHTML.trim()) { addMessage('assistant', `Hello! I can help you with: โ€ข ABV and gravity calculations โ€ข Fermentation troubleshooting โ€ข Yeast pitch rate optimization โ€ข Calorie and nutrition analysis โ€ข Converting between brewing units What brewing question can I help you with?`); } } // API ํ‚ค ์„ค์ • ํ™”๋ฉด ํ‘œ์‹œ function showAPIKeySetup() { document.getElementById('aiModalTitle').textContent = 'Setup Gemini API'; document.getElementById('aiSelector').style.display = 'none'; document.getElementById('geminiChat').style.display = 'none'; document.getElementById('apiKeySetup').style.display = 'block'; aiModalState.currentView = 'setup'; } // AI ์„ ํƒ ์ฒ˜๋ฆฌ function selectAI(aiType) { switch(aiType) { case 'chatgpt': const toolContext = `I need help with fermentation calculations and brewing. I'm using the WIA Pin Code Fermentation Calculator tool to calculate ABV, gravity conversions, calories, yeast pitch rates, and attenuation for beer, wine, mead, and cider.`; const chatUrl = `https://chat.openai.com/?q=${encodeURIComponent(toolContext)}`; window.open(chatUrl, '_blank'); closeAIModal(); trackEvent('ai_selection', { ai_type: 'chatgpt' }); break; case 'claude': const claudeContext = `I need help with fermentation calculations and brewing. I'm using the WIA Pin Code Fermentation Calculator tool to calculate ABV, gravity conversions, calories, yeast pitch rates, and attenuation for beer, wine, mead, and cider.`; const claudeUrl = `https://claude.ai/chat?q=${encodeURIComponent(claudeContext)}`; window.open(claudeUrl, '_blank'); closeAIModal(); trackEvent('ai_selection', { ai_type: 'claude' }); break; case 'gemini': if (!aiModalState.apiKey) { showAPIKeySetup(); } else { showGeminiChat(); } trackEvent('ai_selection', { ai_type: 'gemini' }); break; } } // API ํ‚ค ์ €์žฅ function saveGeminiApiKey() { const apiKey = document.getElementById('geminiApiKeyInput').value.trim(); if (apiKey) { localStorage.setItem('geminiApiKey', apiKey); aiModalState.apiKey = apiKey; showGeminiChat(); updateAPIKeyStatus(); } else { alert('Please enter a valid API key'); } } // API ํ‚ค ์ƒํƒœ ์—…๋ฐ์ดํŠธ function updateAPIKeyStatus() { const statusEl = document.getElementById('apiKeyStatus'); if (aiModalState.apiKey) { statusEl.innerHTML = 'Change API Key'; } else { statusEl.textContent = 'No API key set'; } } // ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ function addMessage(type, content) { const chatMessages = document.getElementById('chatMessages'); const messageDiv = document.createElement('div'); messageDiv.className = `message ${type}`; if (type === 'user') { messageDiv.innerHTML = `You: ${content}`; } else { messageDiv.innerHTML = `โœจ Gemini:
${content.replace(/\n/g, '
')}`; } chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; } // Gemini์— ๋ฉ”์‹œ์ง€ ์ „์†ก async function sendToGemini() { const input = document.getElementById('geminiInput'); const message = input.value.trim(); if (!message) return; // ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ addMessage('user', message); input.value = ''; // ๋กœ๋”ฉ ํ‘œ์‹œ const loadingMsg = document.createElement('div'); loadingMsg.className = 'message assistant'; loadingMsg.innerHTML = 'โœจ Gemini:
Thinking...'; loadingMsg.id = 'loading-message'; document.getElementById('chatMessages').appendChild(loadingMsg); try { const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${aiModalState.apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: `Context: User is using the WIA Pin Code Fermentation Calculator tool for brewing calculations including ABV, gravity conversions, calories, yeast pitch rates, and attenuation for beer, wine, mead, and cider. Current tab: ${currentTab} User question: ${message} Please provide accurate brewing and fermentation advice. Include specific gravity calculations when relevant.` }] }], generationConfig: { temperature: 0.7, maxOutputTokens: 1000 } }) }); const data = await response.json(); // ๋กœ๋”ฉ ๋ฉ”์‹œ์ง€ ์ œ๊ฑฐ document.getElementById('loading-message').remove(); if (data.candidates && data.candidates[0] && data.candidates[0].content) { const reply = data.candidates[0].content.parts[0].text; addMessage('assistant', reply); } else { addMessage('assistant', 'Sorry, I could not generate a response. Please try again.'); } } catch (error) { // ๋กœ๋”ฉ ๋ฉ”์‹œ์ง€ ์ œ๊ฑฐ document.getElementById('loading-message')?.remove(); if (error.message.includes('API key')) { addMessage('error', 'Invalid API key. Please check your API key and try again.'); showAPIKeySetup(); } else { addMessage('error', 'Failed to connect to Gemini. Please check your internet connection and try again.'); } } } // ========== EVENT LISTENERS ========== // DOM Content Loaded document.addEventListener('DOMContentLoaded', function() { // Enter key support for inputs document.querySelectorAll('.input-field').forEach(input => { input.addEventListener('keypress', function(e) { if (e.key === 'Enter') { const activeSection = document.querySelector('.calc-section.active'); const button = activeSection.querySelector('.btn'); if (button) button.click(); } }); }); // Clear errors on input document.querySelectorAll('.input-field').forEach(input => { input.addEventListener('input', clearAllErrors); }); // Handle custom serving size toggle document.getElementById('servingSize').addEventListener('change', function() { const customGroup = document.getElementById('customServingGroup'); if (this.value === 'custom') { customGroup.style.display = 'block'; } else { customGroup.style.display = 'none'; } }); // AI ๋ฒ„ํŠผ ์ด๋ฒคํŠธ document.getElementById('aiBtn').addEventListener('click', openAIModal); // ๋ชจ๋‹ฌ ์™ธ๋ถ€ ํด๋ฆญ์‹œ ๋‹ซ๊ธฐ document.getElementById('aiModal').addEventListener('click', function(e) { if (e.target === this) { closeAIModal(); } }); // ์—”ํ„ฐ ํ‚ค ์ง€์› ๋ฐ ESC ํ‚ค๋กœ ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ document.addEventListener('keydown', function(e) { if (e.key === 'Enter') { const geminiInput = document.getElementById('geminiInput'); if (document.activeElement === geminiInput) { sendToGemini(); } } // ESC ํ‚ค๋กœ ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ if (e.key === 'Escape') { closeAIModal(); } }); // ์ดˆ๊ธฐ API ํ‚ค ์ƒํƒœ ์—…๋ฐ์ดํŠธ updateAPIKeyStatus(); updateCurrentYear(); updateToolCount(); }); // Track WIA Pin Code clicks for analytics document.querySelectorAll('a[href*="wia"]').forEach(link => { link.addEventListener('click', function() { trackEvent('wia_link_click', { link: link.textContent }); }); }); // ========== DYNAMIC TOOL COUNT ========== // Update tool count dynamically async function updateToolCount() { try { const response = await fetch('/api/tool-count.php'); const data = await response.json(); // Update dynamic tools description document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${data.count}+ free online tools in 211 languages. No signup, no fees, just tools that work.`; }); // Update "All X+ Tools" links document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${data.count}+ ${suffix}`; }); } catch (error) { // Fallback: use current actual count from server const fallbackCount = 333; document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${fallbackCount}+ free online tools in 211 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${fallbackCount}+ ${suffix}`; }); console.log('Tool count API not available, using current count:', fallbackCount); } } // Update current year dynamically function updateCurrentYear() { const currentYear = new Date().getFullYear(); document.querySelectorAll('.current-year').forEach(el => { el.textContent = currentYear; }); } // ========== ANALYTICS ========== // Google Analytics window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXX'); // Track page view trackEvent('page_view', { tool: TOOL_CONFIG.name, category: TOOL_CONFIG.category });