Getting environment variables into code in your web page

This is one of my “I’m putting something into the blog so that I can find it in a couple of years when I need to do this again” posts. I’m doing some work on the Connected Little Boxes website and I've been deploying the latest version. This one automatically configures a device by downloading setting information from the cloud. Code running inside the browser gets the settings from the server and then sends them into the device. To make this work the code in the browser needs to know the url of the server based data source. When I’m developing the program this will be on the localhost (my pc) and when the code is deployed the data source is the server in the cloud.

I’ve put this information in an environment variable. I have a local .env file that holds the local address. I’ve then put the deployed host address in the environment variable in the cloud. This works a treat, but I do have one problem. How do I get the value of this environment variable into the JavaScript code running in the browser? I’m using an Express web page to hold the web page source and I can embed JavaScript into the HTML but I don’t seem to be able to embed JavaScript elements into the <script> parts of the page. Probably because doing this kind if thing might disrupt the space-time continuum. So, I’ve done this… Below you can see the statement that renders the createDevice.ejs page. I pass this statement the HOST_ADDRESS environment variable that I want to feed into the JavaScript code in the createDevice.ejs page:

res.render("createDevice.ejs", { name: res.user.name, host: process.env.HOST_ADDRESS });

When the page is loaded the name and host variables are loaded with values supplied to the render method. Now, I pick those up inside the HTML and pass them into the page initialise function:

<body onload= "doStart('<%= host %>');" >

The HTML above specifies that a function called dostart will be called, and supplied with the value of host as a parameter. This is the environment variable that I want to use as the base url for my server requests.

function doStart(host) {
    console.log("starting");
    hostAddress = host;
    settingsURL = hostAddress + "createDevice/networkSettings.json"

    selectStage(stages.ConnectUSB);
  }

Above is the doStart function. It sets hostAddress with the base url for all requests and then uses this value to build the settingsURL that is used to fetch settings information from the host. It works a treat. When I run the application on my local PC the url is set to the local host and when it runs in the cloud the address is set to the cloud location. There is probably a much easier way of doing this which I don’t know about, but I’m still quite pleased with making this work myself.

Tricky Mine Finder

We’ve played a bit of “Mine Finder” now, and it turns out to be a bit too easy. Once you know the colours you can narrow down the mine position quite easily. So, today I present “tricky mine finder”. When the game starts you don’t know which colour represents which distance. In the screenshot above the squares one space from the mine are light blue. It took me 14 tries to get it. If you want to have a go yourself you can find the game here.

Welcome to Mine Finder

This is my first version of the “Mine Finder” application that I’m using as an example of programmatically made HTML elements. You click on a cell and it tells you how far the cell is from the mine. The idea is to either find the mine or take it in turns to try and avoid it. The game is quite fun to play.

Each of the cells in the grid is an HTML button which is created by a nested for loop in the program. I’m quite pleased with the code that makes the grid:

let container = document.getElementById("buttonPar");

  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      let newButton = document.createElement("button");
      newButton.className = "upButton";
      newButton.setAttribute("x", x);
      newButton.setAttribute("y", y);
      newButton.textContent = "X";
      newButton.setAttribute("onClick", "doButtonClicked(this);");
      container.appendChild(newButton);
    }
    let lineBreak = document.createElement("br");
    container.appendChild(lineBreak);
  }

All the buttons are assigned to the same event handler and each button is given attributes that give the position of the button in the grid. I like this because we can make the grid any size that we want and the program still works. It’s probably not the best way to make a game like this, you should really use a canvas I guess, but it was quite fun to write.

JavaScript code answer

if (x!=x) console.log("Wahay!");

A while back I posed a little JavaScript question: When would the above JavaScript statement print “Wahay"?

This provoked a storm of apathy on the internet, but I’m going to tell you the answer anyway. You use the above test to detect a variable which is not a number (NaN).

JavaScript is a bit strange when it comes to handling errors.

x =  1/"fred";

Some languages would not even compile the above statement. Some languages would stop the program at this statement. JavaScript does something different. It says “Dividing a number by a string is silly, I’m going to set the value of x to a special value which means “Not a number”. JavaScript has other special values too. If you divide any number by 0 you get a special value called Infinity, which behaves like infinity. Add a number to infinity and you get infinity as a result. Divide any number by infinity and you get zero. Divide infinity by infiniuty and you get Not a Number - which is also right.

But I digress. What would the statement at the top do? Well, it is how you test for Not a Number in a JavaScript program. Suppose you want to check if x contains NaN. You might think that you do this:

if (x==NaN) console.log("Not a number!");

However, this statement will not work, because something which is not a number is not equal to anything, including NaN. So the test always fails. Which is why you sometimes see NaN in JavaScript forms because the programmer didn’t know this or test it.

However, a value which is not a number isn’t even equal to itself, which is why the test is so useful.

Running Rollup on your PC

At the hardware meetup last night Lydia suggested that I get into Rollup. It’s a way of taking an npm project (which would normally run on a server) and packing it up so that it can be downloaded from a web site and run in a local browser. The rollup application runs on your PC and does the packaging. Which, if you have a PC, is a problem because Windows 10 is very unkeen to run programs that have been downloaded from the internets.

You can fix this, and get the program to work, by asking Windows to be a bit more relaxed for a while. The command to do that is:

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Enter the command into the terminal in your Visual Studio Code session and you should be good to go.

Putting JavaScript code into MarkDown pages

This is another of my posts to remind myself how to do something that I’m sure I’ll forget. It’s useful if you want to embed JavaScript (or perhaps any) code into a web page. If you use MarkDown to format the text you can mark the code by enclosing it in the sequences ```j and ```. In other words.

```j

var fred =99;

var jim = 100;

```

.. would be rendered as:

var fred =99;
var jim = 100;


Admittedly, this doesn’t look that different to the original, but if you remember that the line breaks in your text are properly respected so that it looks how it should. Remember to use the back single quote (it is on the top left hand corner of your PC keyboard) .

Makertober Day 4: Letter Tiles

In a change of plan, rather than making a box for my temperature sensor, today I’ve spent a bit of time picking random letters. Years ago I I had an idea for a tiny Windows Phone game in which the player flicked letter tiles at targets to build words. I’ve decided to finish this off using my new JavaScript Matter.js skills. The first step is to pick some letters to use in the game. I reckon I’ll need 100 or so tiles to make the game work.

Now I could just pick the letters on the tiles by getting a random number in the range 1-26 and then just match that to a letter. That would work, but it wouldn’t be fair on the player as they would get as many letter Es as Zs, and that is not how the English language works. We use a lot more Es than Zs. So I went online, found a letter frequency table and popped it into JavaScript:

this.letterList = [
    { letterChar: 'A', freq: 8.34 },
    { letterChar: 'B', freq: 1.54 },
    { letterChar: 'C', freq: 2.73 },
    { letterChar: 'D', freq: 4.14 },
    { letterChar: 'E', freq: 12.60 },
    { letterChar: 'F', freq: 2.03 },
    { letterChar: 'G', freq: 1.92 },
    { letterChar: 'H', freq: 6.11 },
    { letterChar: 'I', freq: 6.71 },
    { letterChar: 'J', freq: 0.23 },
    { letterChar: 'K', freq: 0.87 },
    { letterChar: 'L', freq: 4.24 },
    { letterChar: 'M', freq: 2.53 },
    { letterChar: 'N', freq: 6.80 },
    { letterChar: 'O', freq: 7.70 },
    { letterChar: 'P', freq: 1.66 },
    { letterChar: 'Q', freq: 0.09 },
    { letterChar: 'R', freq: 5.68 },
    { letterChar: 'S', freq: 6.11 },
    { letterChar: 'T', freq: 9.37 },
    { letterChar: 'U', freq: 2.85 },
    { letterChar: 'V', freq: 1.06 },
    { letterChar: 'W', freq: 2.34 },
    { letterChar: 'X', freq: 0.20 },
    { letterChar: 'Y', freq: 2.04 },
    { letterChar: 'Z', freq: 0.06 }];

This array contains an object that has a letterChar property (the char of the letter, and a freq property which gives the number of times that letter will appear in 100 letters. In other words, in 100 letters we should find around 12 Es, 1 V and not many Zs. I now want some JavaScript that will pick 120 tiles based on this distribution. To make the game seem more real, I also want to make sure that there is at least 1 of each character - even the one that mathematically should not be there. It turned out that the code to do this in one pass through the array of letters was a bit hard to do. In fact I didn’t manage to do it without a bit of cheating. What I came up with steals 1 tile from each calculated letter and then fills in the last few random tiles with randomly chosen tiles that have a uniform distribution over all 26. I’m kind of proud of this, until someone suggests a better way to do it…..

var createdTileCount = 0;

for (let letter of this.letterList) {
    let noOfThisLetter = Math.floor(tileCount * (letter.freq / 100))-1;
    if (noOfThisLetter < 1) {
        letter.number = 1;
    }
    else {
        letter.number = noOfThisLetter;
    }
    createdTileCount += letter.number;
}

// add in some spare random ones

while(createdTileCount<tileCount){
    let lett= this.getRandomInt(0,25);
    this.letterList[lett].number++;
    createdTileCount++;
}

Once I’d got my letters picked the next thing to do is display them. I’ve used my list of tile numbers to build all the tiles, given them some physics and then dropped them on the ground. Below you can see the result.

falling letters.png

I guess this is more of a “work in progress” than a finished item. But it is still something I’ve. I’ll put the code on GitHub when it is finished.