# Homebrew Tools: Force Carb Calculator and Web Coding Techniques

Last week, in my Beer and Coding at Two post, I stated that I would have the first in a series of Homebrew Tools done this week. I am happy to report that I have actually managed to meet a deadline. Albeit a self imposed deadline, but when the norm is deadlines coming and going, while your projects sit in committee hell, you take a win when you can get one. The force carb calculator can be found under the Homebrew Tools tab at the top of the page.

So, why this calculator? Well, a couple reasons. First, I picked a force carb calculator because, unlike most beer related formulas, this is one I am not able to do on my fingers (or toes, or with a relatively small number of button presses for that matter). The formula for determining required PSI is:

P = -16.6999 – 0.0101059 T + 0.00116512 T^2 + 0.173354 T V
+ 4.24267 V – 0.0684226 V^2

P = PSI
T = Temperature
V = Desired Volumes of Carbonation

The second part of the ‘why?’ is that it gives me an opportunity to talk about coding design. Most of the force carb calculators available on the interwebs, use a Javascript Get/Post method, which reloads the entire page to display the results. There is nothing wrong with this design (and it does drive up the ad views – Beer and Coding Monetization Editor), but it is a little clunky, and with tools like JQuery, completely unnecessary. Now, before I delve any further into my web programming philosophies and techniques, you get the disclaimer.

While I write software for a living, I am by no means a web programmer. My opinions about web programming design and technique should be taken for what they are, my opinions.

Ok, with that out of the way, we can get started. As I stated above, I like to avoid using Get/Post within the Javascript if I am working within a single page. Instead, I like to leverage the jQuery Post method to fetch PHP/HTML from an external file and insert in onto the current page. This not only keeps the entire page from reloading every time the code fires, but it makes to code much more streamlined. The entire code for the Homebrew Tools page is:

<?php

echo “<p>”;
echo “<p>”;
echo “<div id=\”carb_calc\”>”;
echo “</div>”;

\$initialize = 0;
if (\$initialize == 0) {
echo “<script>init_page();</script>”;
\$initialize = 1;
}

?>

Sexy, right? Along with this we also have the Javascript function init_page(), to initialize the page and place some PHP in the carb_calc <DIV>. The code for the Javascript header and init_page() function is:

<script type=”text/javascript”>

var \$j = jQuery.noConflict();

function init_page() {
\$j(‘#carb_calc’).html(‘<input type=”button”
onclick=”show_tool(\’carb_calc\’);” value=”Force
Carbonation Calculator”></input>’);
}
.
.
.
.
</script>

Defining the carb_calc button in the init_page() function was another design choice. It could just as easily have been defined directly within the carb_calc <DIV> in the PHP, but by placing the code in the Javascript function, we can more easily control whether or not a button is loaded. Not so important in this example, where the carb_calc button is immediately loaded, but it could prove helpful down the road, if I want to suppress certain buttons, depending on how the user arrives at the page.

Another technique I like to use is passing the name of the <DIV> to my Javascript functions. This allows me to write very light, modular Javascript functions, eliminating long If/Else statements. The code for the show_tool() function is:

function show_tool(homebrew_tool) {
\$j.post(“../” + homebrew_tool + “.php”, function (data) {
if (data.length > 0) {
\$j(‘#’ + homebrew_tool).show();
\$j(‘#’ + homebrew_tool).html(data);
} else {
\$j(‘#’ + homebrew_tool).hide();
}
});
}

By using the same name for the PHP file as the <DIV>, in this case ‘carb_calc’, the name can be passed straight through to the jQuery Post method without any extra conversion or validation. And as long as I preserve this naming convention, I can continue creating tools that call the show_tool() function without ever adding code to the function itself. Instead, all the work is done in the PHP file. The code for the carb_calc.php file is:

<?php
echo “<b>Force Carbonation Calculator</b>”;
echo “<table>”;
echo “<tr>”;
echo “<td>Temperature</td>”;
echo “<td><input type=\”text\” id=\”temp\”
maxlength=\”3\” size=\”4\”/></td>”;
echo “<td>(°F)</td>”;
echo “</tr>”;
echo “<tr>”;
echo “<td>Volumes</td>”;
echo “<td><input type=\”text\” id=\”vol\”
maxlength=\”3\” size=\”4\”/></td>”;
echo “<td>Desired Volumes of CO2</td>”;
echo “</tr>”;
echo “<tr>”;
echo “<td>PSI</td>”;
echo “<td><input type=\”text\” id=\”psi1\”
maxlength=\”4\” size=\”4\”/></td>”;
echo “<td>Slow Force Carb (> 5 days @ PSI)</td>”;
echo “</tr>”;
echo “<tr>”;
echo “<td>PSI</td>”;
echo “<td><input type=\”text\” id=\”psi2\”
maxlength=\”4\” size=\”4\”/></td>”;
echo “<td>Fast Force Carb (24 hours @ PSI)</td>”;
echo “</tr>”;
echo “<tr>”;
echo “<td><input type=\”button\” onclick=\”calculate_psi()\”
value=\”Calculate\”/></td>”;
echo “<td></td>”;
echo “<td><input type=\”button\”
onclick=\”close_tool(‘carb_calc’,'Force Carbonation Calculator)\”
value=\”Close\”/></td>”;
echo “</tr>”;
echo “</table>”;
?>

The carb_calc.php file is where the actual defining of the tool occurs. The show_tool() function retrieves this file and posts the PHP code within to the carb_calc <DIV>, replacing the button that called show_tool(). By designing the tools to work this way, the code on the page stays light and the Javascript functions become very reusable. When it comes time to add, say, a gravity calculator, all I have to do is add a ’grav_calc’ <DIV> to the main PHP, initialize the tool’s button in init_page() and place the tool’s code in grav_calc.php. The close_tool() function, which (surprise, surprise), closes the tool, works in much the same manner as the  show_tool() function. The code for the close_tool() function is:

function close_tool(homebrew_tool,tool_name) {
\$j(‘#’ + homebrew_tool).html(‘<input type=”button”
onclick=”show_tool(\” + homebrew_tool + ‘\’);”
value=”‘ + tool_name + ‘”></input>’);
}

This function simply replaces all the carb_calc.php code in the carb_calc <DIV> with the tool’s button. Again, reusable by any future tools. Finally, we have the function calculate_psi(), where all the hard maths are performed:

function calculate_psi() {
var temp = document.getElementById(“temp”).value;
var vol = document.getElementById(“vol”).value;
var psi1 = -16.6999 – (0.0101059*temp) +
(0.00116512*(temp*temp)) + (0.173354*(temp*vol)) +
(4.24267*vol) – (0.0684226*(vol*vol));
var psi2 = psi1*3;
psi1 = Math.round(psi1*Math.pow(10,1))/Math.pow(10,1);
if (psi1 < 0.1) {
psi1 = ‘< 0′;
}
psi2 = Math.round(psi2*Math.pow(10,1))/Math.pow(10,1);
if (psi2 < 0.1) {
psi2 = ‘< 0′;
}
\$j(‘#psi1′).val(psi1);
\$j(‘#psi2′).val(psi2);
}

This function retrieves the temperature and volume values using the document.getElementById method. The maths are performed and the two PSI values are displayed in the input fields using jQuery. Since none of the input variables are being used in mySQL queries, I did not bothering to perform any validation on them. The lengths of the input values are controlled by the ‘maxlength’ attribute, set for each input field in carb_calc.php. If a non-numeric is entered in either field, NaN (Not a Number) will be returned. The only case I am trapping for is when the required PSI would be less the 0.1. In this case I am returning ‘ < 0′ in the PSI fields, rather than a negative number.

So, there you have it, a force carb calculator and a glimpse into the design decisions behind it. I still plan on adding a little polish to the calculator, like an option for Celcius and a warning if the determined PSI is over 60 (the limit of many homebrew CO2 regulators).

If anyone finds this kind of post useful, let me know and I will continue writing them as I code more tools for the Homebrew Tools page.

Cheers!
Kevin

### 1 comment to Homebrew Tools: Force Carb Calculator and Web Coding Techniques

• Jesse

Hey, nice to see the occasional coding post on here. Don’t get me wrong, beer is just as, if not more, important, but I’ll go ahead and put in my vote for finding this post useful.

Well, that’s enough comma abuse for one day,
Jesse