Weatherfire Update 2

Now that Weatherfire is feature-complete (at least for the first release), I just have some little things left to do.

The two biggest things from a user’s point of view is that the help needs to be written and the options screen still has to be implemented.  The only thing that’s going to be on the options screen to start with is a button to choose whether the metric or imperial units should be used, but that’s pretty important.

There are a handful of minor things that need to be done as well. For instance, currently if there is a decimal value for one of the info fields it will display the entire length. “2.66666666667” (or however many digits it is) doesn’t look very good, and instead the number of decimal places will probably be limited to two.

Also, I’m going to work on some optimizations. As the program is right now there are noticeable delays when switching to a new screen, in particular the info screens, as the app is processing a large amount of data and locks up the UI while it’s doing so. This isn’t that big of an issue if the user has only entered in a small amount of data, but as more and more is added the lag will become more obvious.

Some fixes:

  • I’ve just been trying to get this done quickly without really caring about optimizations so far, so there is plenty of redundant code that can be cut. There’s a lot of computing the same data repeatedly within the same functions, so I can remove all the duplicates.
  • I might move the data computing code into a separate worker so it doesn’t block the main thread. The UI would be created and displayed first, with the data filled in once the calculations are complete. I’m not certain that this is a good idea though, as it still makes the app look like it’s lagging.
  • Currently if the info screens are accessed multiple times without additional data being added, the info has to be calculated each time, despite that it will still be the same. It would reduce the delays further if the calculated info was cached, so then if the screen was accessed again the data could simply be taken from the cache.

Weatherfire Update

So it turns out that the name “Weatherfox” is already used, by another Firefox OS app. From now on my app will be called “Weatherfire” instead, or at least until I find that that is used as well.

Aside from that though, the app is progressing nicely. I’ve almost finished with completely implementing the features for version 0.1. The ability to add, view, delete, and clear data is done, and the general info screen is done. That only leaves the other info screens left to do, and now that I’ve got all the base code for those done it shouldn’t take too long. After that I have to write the help page(s), but that will be quick.

Weatherfox

New project!

Weatherfox is a mobile version of WeatherLog for Firefox OS devices. However, as Firefox OS apps are nothing more than web apps that appear to be running natively, Weatherfox should also run in just about any web browser that supports enough of the HTML5 and related specs.*

Weatherfox will work about the same as WeatherLog; it has a main screen for displaying data, the ability to add and remove data, and the ability to view information like averages, ranges, highs and lows, etc.

Some technical details: the interface uses HTML5 and CSS, with jQuery Mobile for the interactive components. The program code is all written in JavaScript, and the data is stored as JSON using localStorage.

Developing the app has been relatively easy so far. Porting the info code from Python to JavaScript was simple, but the UI has been frustrating. Partially due to having to make an interface easy to use on small touchscreens, but mostly trying to get jQuery Mobile to actually behave in a somewhat understandable way.

I’m aiming to have the nearly the same feature set for Weatherfox as Weatherlog has. The only exceptions are profiles and importing and exporting data. Profiles are planned for the second release though.

Weatherfox is still in a pre-alpha state. Currently the ability to add, remove, clear, and display data are implemented, but I haven’t started with the info screens yet. If you’re interested, the code is on GitHub, and I have the app up on GitHub Pages as well.

Here are some screenshots, using the simulator because it’s easier:

Main screen, no data
Main screen, no data
Adding some data
Adding some data
Main screen with data
Main screen with data
Removing data
Removing data
Clearing data
Clearing data
About screen
About screen

* The only exception to this is with the datepicker field in the Add screen. Weatherfox uses dates formatted as “dd/mm/yyyy”, and takes as input either the format “yyyy-mm-dd” (used by Firefox OS) or “Mmm dd, yyyy” (as in “Jan 1, 2014”, used in iOS). Any other format is currently not supported, but may be in the future.

extmath.js update 2

I added a lot more functions, and quite a few constants as well. In addition, I (finally) wrote up some basic documentation, so you no longer have to hunt through the code to find what something does.

Download

The JavaScript file can be downloaded here, and the documentation is available here.

New Functions

  • Math.midpoint3() – Finds the midpoint of two points in a three-dimensional space.
  • Math.distance3() – Finds the distance between two points in a three-dimensional space.
  • Math.areaSector() – Finds the area of a sector.
  • Math.areaHemi() – Finds the surface area of a hemisphere.
  • Math.volHemi() – Finds the volume of a hemisphere.
  • Math.areaPipe() – Finds the surface area of a pipe.
  • Math.volPipe() – Finds the volume of a pipe.
  • Math.areaKite() – Finds the area of a kite.
  • Math.areaKiteTrig() – Finds the area of a kite, but in a different way.
  • Math.volPyramid3() – Finds the volume of a regular triangular pyramid.
  • Math.volPyramid4()* – Finds the volume of a regular square pyramid.
  • Math.volPyramid5() – Finds the volume of a regular pentagonal pyramid.
  • Math.volPyramidAny() – Finds the volume of any pyramid.
  • Math.gcd() – Finds the greatest common divisor of two numbers.
  • Math.lcm() – Finds the least common multiple of two numbers.
  • Math.lcmArray() – Finds the least common multiple of numbers in an array.
  • Math.maxArray() – Finds the largest number in an array.
  • Math.minArray() – Finds the smallest number in an array.
  • Math.roundTo() – Rounds a number to the specified number of decimal places.
  • Math.deg2rad() – Converts radians to degrees.
  • Math.rad2deg() – Converts degrees to radians.
  • Math.imul() – Performs a C-like 32-bit integer multiplication.
  • Math.umul() – Performs a C-like 32-bit unsigned integer multiplication.
  • Math.toSource() – Returns “Math”.
  • Math.dividesEvenly() – Finds whether a number can be divided evenly by another.
  • Math.reverseFactorial() – Given a number finds what its factorial is.
  • Math.polygonAngles() – Finds the sum of the interior angles in a polygon.
  • Math.average() – This is the same as Math.mean().
  • Math.areaPyramid3() – Finds the surface area of a regular triangular pyramid.
  • Math.areaPyramid4()* – Finds the surface area of a regular square pyramid.
  • Math.areaPyramid5() – Finds the surface area of a regular pentagonal pyramid.

There are a few modifications to the existing functions as well.

* These are the same as the existing Math.volPyramid() and Math.areaPyramid() functions, respectively, but are included for completeness.

New Constants

  • Math.SQRT3 – Square root of 3.
  • Math.GOLDEN – Golden ratio.
  • Math.DELIAN – Delian constant.
  • Math.SIN45 – Sine of 45 degrees.
  • Math.COS45 – Cosine of 45 degrees.
  • Math.TAN45 – Tangent of 45 degrees.
  • Math.SIN30 – Sine of 30 degrees.
  • Math.COS30 – Cosine of 30 degrees.
  • Math.TAN30 – Tangent of 30 degrees.
  • Math.SIN60 – Sine of 60 degrees.
  • Math.COS60 – Cosine of 60 degrees.
  • Math.TAN60 – Tangent of 60 degrees.
  • Math.SIN90 – Sine of 90 degrees.
  • Math.COS90 – Cosine of 90 degrees.
  • Math.TAN90 – Tangent of 90 degrees.
  • Math.SIN180 – Sine of 180 degrees.
  • Math.COS180 – Cosine of 180 degrees.
  • Math.TAN180 – Tangent of 180 degrees.
  • Math.SIN270 – Sine of 270 degrees.
  • Math.COS270 – Sine of 270 degrees.
  • Math.TAN270 – Sine of 270 degrees.
  • Math.SIN360 – Sine of 360 degrees.
  • Math.COS360 – Cosine of 360 degrees.
  • Math.TAN360 – Tangent of 360 degrees.

webworker2: improved JavaScript Worker object

This is a simple library that improves the JavaScript Worker object, for creating web workers (basically allowing code to execute without blocking). It defines two new objects: Worker2 and WorkerFunction.

About

The first, Worker2, is a slight simplification of the built-in Worker object. The constructor takes three parameters: the name of the script to execute, an optional callback function for when the worker uses postMessage(), and an optional callback function for when an error occurs in the worker. The onmessage callback will be passed two parameters: the data sent and the event object. The onerror callback will be passed just the event object.

Example:

worker = new Worker2("myscript.js", function(data, e) { alert(data; });

Worker2 has four methods. The first two are postMessage() and the alias post(). These accept one parameter: the data to be sent. The other two methods are terminate() and stop(), both of which end the worker.

The other object, WorkerFunction, is more complex. It also takes three parameters, but the first is a function instead of a string. This function is used as the worker, so another file isn’t required. The two callbacks are used exactly the same way.

Example:

var myFunction = function(a, b, c) {
    return a + b + c;
};
var myCallback = function(data, e) {
    document.body.innerHTML = "<strong>" + data + "</strong>"
};
var worker = new WorkerFunction(myFunction, myCallback, function(e) { alert("Error: " + e.data); });
worker.post([1,2,3])

WorkerFunction has the same four methods as Worker2. postMessage() and post() work differently, however: they are used to pass parameters to the function if needed. They must only be passed one argument, an array of the parameters. Alternatively, they can be passed nothing if no parameters are needed.

Download

You can download webworker2 here.

extmath.js update 1

This is an update to extmath.js that adds a handful of new functions. The majority have to do with basic geometry, such as finding the area of shapes and surface area and volume of solids. (Although some are simply for completeness. Math.areaRect(), for example; who is actually going to forget how to calculate the area of a rectangle?)

New functions

  • Math.randInt(x, y) – Works the same as Math.random(x, y), with the exception that it only returns integers.
  • Math.pythagorean(a, b, c) – Uses the Pythagorean Theorem to solve for one of the variables. The value you want to find must be null, and the other two must be numbers. For example, Math.pythagorean(5, null, 13) will return 12.
  • Math.distance(x, y) – Finds the distance between two points. x and y are both arrays with two numbers, and are used as the points.
  • Math.midpoint(x, y) – Finds the midpoint of two points. x and y are both arrays with two numbers, and are used as the points. This will return an array with the x and y coordinates.
  • Math.slope(x, y) – Finds the slope of the line containing two points. x and y are both arrays with two numbers, and are used as the points.
  • Math.areaRect(x, y) – Returns the area of a rectangle with sides x and y.
  • Math.areaTri(b, h) – Returns the area of a triangle with base b and height h.
  • Math.areaCircle(r) – Returns the area of a circle with radius r.
  • Math.areaParallel(x, h) – Returns the area of a parallelogram with side x and height h.
  • Math.areaTrap(b1, b2, h) – Returns the area of a trapezoid with bases b1 and b2 and height h.
  • Math.areaRhom(d1, d2) – Returns the area of a rhombus with diagonals d1 and d2.
  • Math.areaEllipse(a, b) – Returns the area of an ellipse with radii a and b.
  • Math.areaSphere(r) – Returns the surface area of a sphere with radius r.
  • Math.areaRectPrism(x, y, z) – Returns the surface area of a rectangular prism with sides x, y, and z.
  • Math.areaCone(r, h) – Returns the surface area of a cone with base radius r and height h.
  • Math.areaPyramid(x, h) – Returns the surface area of a pyramid with base length x and height h. Note that this only works with 4-sided pyramids.
  • Math.areaCylinder(r, h) – Returns the surface area of a cylinder with radius r and height h.
  • Math.volRectPrism(x, y, z) – Returns the volume of a rectangular prism with sides x, y, and z.
  • Math.volSphere(r) – Returns the volume of a sphere with radius r.
  • Math.volCone(r, h) – Returns the volume of a cone with base radius r and height h.
  • Math.volPyramid(x, h) – Returns the volume of a pyramid with base length x and height h. Note that this only works with 4-sided pyramids.
  • Math.volCylinder(r, h) – Returns the volume of a cylinder with radius r and height h.

Download

You can download the updated file here, if you’re interested.

Miscellaneous JavaScript code

I’ve been going through a lot of my old(er) code recently, and I found these two files. They define functions for checking what type a variable is, and for determining various qualities of the variable. Not very exciting, I know, but they’re pretty useful.

/* typeOf(x) -- returns the type of the variable x. */
var typeOf = function(x) {
    if(x === null) {
        return "null";
    }
    if(x === undefined) {
        return "undefined";
    }
    if(x !== x) {
        return "NaN";
    }
    var type = typeof x;
    if(type != "object") {
        return type;
    }
    return Object.prototype.toString.call(x).slice(8, -1);
};
/* isDefined(x) -- returns true is x is defined, and false otherwise. */
var isDefined = function(x) {
    return x !== undefined;
};

/* isSomething(x) -- returns true if x is something (and false otherwise), based on the following qualities:

* it must be defined
* it must not be null
* if it's a number then it must not be zero
* if it's a string then it must not be the empty string
* if it's array-like then it must not have a length of zero
* if it's an object then it must have at least one enumerable non-inherited property
*/
var isSomething = function(x) {
    if(!isDefined(x) || x === null) {
        return false;
    }
    if(typeof x == "number" && x === 0) {
        return false;
    }
    if(typeof x == "string" && x === "") {
        return false;
    }
    if(isArrayLike(x) && x.length == 0) {
        return false;
    }
    if(typeof x == "object" && isEmptyObject(x)) {
        return false;
    }
    return true;
};

/* isNothing(x) -- returns the opposite of isSomething(x). */
var isNothing = function(x) {
    return !isSomething(x);
};

/* isEmptyObject(x) -- returns true if x is an object and has no enumerable non-inherited properties, and false otherwise. */
var isEmptyObject = function(x) {
    if(typeof x != "object") {
        return null;
    }
    for (var i in x) {
        if(x.hasOwnProperty(i)) {
            return false;
        }
    }
    return true;
};

/* isArrayLike(x) -- returns true if x is an array or is similar to an array, and false otherwise. */
var isArrayLike = function(x) {
    return x && typeof x == "object" && isDefined(x.length) && isFinite(x.length) && x.length >= 0 && x.length === Math.floor(x.length) && x.length < 4294967296;
};

/* isSameTypeAs(x, y) -- returns true if the type of x is the same as the type of y, and false otherwise. */
var isSameTypeAs = function(x, y) {
    return typeof x === typeof y;
};

extmath.js: JavaScript Math object extension

This is a fairly simple and small JavaScript library that extends the native JavaScript Math object. I created this really just because I was working on a lot of math-related projects with JavaScript so it made sense to collect everything I used into one file. I actually wrote most of this about a year ago, forgot about it, then found it again recently and updated it.

Here’s a list of all the new functions it defines:

  • Math.add(x) – Returns the sum of an array of numbers. This might seem kind of useless considering you can just use +, but when you have an array of numbers this is actually quite handy.
  • Math.subtract(x) – Returns the difference of an array of numbers.
  • Math.multiply(x) – Returns the product of an array of numbers.
  • Math.divide(x) – Returns the quotient of an array of numbers.
  • Math.modulus(x) – Returns the modulus of an array of numbers.
  • Math.factorial(x) – Returns the factorial of a number.
  • Math.range(x) – Returns the range of an array of numbers.
  • Math.mean(x) – Returns the mean (average) of an array of numbers.
  • Math.isInRange(x, y, z) – Returns true if x is between y and z, inclusive, and false otherwise.
  • Math.isInRange2(x, y, z) – Returns true if x is between y and z, exclusive, and false otherwise.
  • Math.acosec(x) – Returns the inverse cosecant of a number.
  • Math.acosech(x) – Returns the inverse hyperbolic cosecant of a number.
  • Math.acosh(x) – Returns the inverse hyperbolic cosine of a number.
  • Math.acot(x) – Returns the inverse cotangent of a number.
  • Math.acoth(x) – Returns the hyperbolic inverse cotangent of a number.
  • Math.asec(x) – Returns the inverse secant of a number.
  • Math.asech(x) – Returns the inverse hyperbolic secant of a number.
  • Math.asinh(x) – Returns the inverse hyperbolic sine of a number.
  • Math.atanh(x) – Returns the inverse hyperbolic tangent of a number.
  • Math.cosec(x) – Returns the cosecant of a number.
  • Math.cosech(x) – Returns the hyperbolic cosecant of a number.
  • Math.cosh(x) – Returns the hyperbolic cosine of a number.
  • Math.cot(x) – Returns the cotangent of a number.
  • Math.coth(x) – Returns the hyperbolic cotangent of a number.
  • Math.sec(x) – Returns the secant of a number.
  • Math.sech(x) – Returns the hyperbolic secant of a number.
  • Math.sign(x) – Returns 0 if the number is 0, -1 is the number is negative, and 1 if the number is positive.
  • Math.sinh(x) – Returns the hyperbolic sine of a number.
  • Math.tanh(x) – Returns the hyperbolic tangent of a number.
  • Math.crt(x) – Returns the cube root of a number.
  • Math.rt(x, y) – Returns the y root of x.
  • Math.isEven(x) – Returns true if a number is even, and false otherwise.
  • Math.isPrime(x) – Returns true if a number is prime, and false otherwise.
  • Math.mode(x) – Returns the most often occurring number in an array.
  • Math.median(x) – Returns the median of an array of numbers.
  • Math.random([x [, y]]) – If it is called without any arguments, this returns a pseudo-random number between 0 and 1. If it is called with one argument, this returns a pseudo-random number between 0 and x. If it is called with two arguments, this returns a pseudo-random number between x and y.
  • Math.isInteger(x) – Returns true if a number is an integer, and false otherwise.
  • Math.isNatural(x) – Returns true if a number is natural, and false otherwise.
  • Math.stdDev(x) – Returns the standard deviation of an array of numbers.
  • Math.quadEquation(a, b, c) – Returns the results of the quadratic equation using a, b, and c. If there are no real answers, it will return false.

It also defines a Math.Complex() class for complex numbers:

  • Math.Complex(real, imaginary)– This is the constructor.
  • complex.add(complex2) – Returns a new Math.Complex object that is the sum of complex and complex2.
  • complex.subtract(complex2) – Returns a new Math.Complex object that is the difference of complex and complex2.
  • complex.multiply(complex2) – Returns a new Math.Complex object that is the product of complex and complex2. Note that complex2 can be either a Math.Complexobject or a number.
  • complex.divide(complex2) – Returns a new Math.Complex object that is the quotient of complex and complex2. Note that complex2 can be either a Math.Complex object or a number.
  • complex.square() – Returns a new Math.Complex object that is complex squared.
  • complex.magnitude() – Returns the magnitude of complex.
  • complex.conjugate() – Returns a new Math.Complex object that is the conjugate of complex.
  • complex.negative() – Returns a new Math.Complex object that is the negative of complex.
  • complex.equals(complex2) – Returns true if complex and complex2 and equal, and false otherwise.
  • complex.valueOf() – This is the same as complex.magnitude(). It is called whenever complex needs to be automatically converted to a number.
  • complex.toString() – Returns complex in string form. It is called whenever complex needs to be automatically converted to a string.

If for some reason you’re interested in this, you can download it here.

JavaScript Timers object

These are just two short functions I wrote a while ago as improvements to the JavaScript setInterval() and setTimeout() timer functions.

Both functions take at minimum two arguments; the function to run and the interval/delay. They take additional optional arguments to specify an object to apply() the function to, and an array of arguments to pass to the function.

Timers.timeout() only runs once, but Timers.interval() will run forever unless you tell it not to. To do that, simply return false. It you return anything else, it will be passed as the first argument next time the function is run.

var Timers = {

interval: function(func, time, obj, args) {
    var r;
    var a = args ? args : [];
    var o = obj ? obj : null;
    var ifunc = function() {
        if(r === false) {
            return;
        }
        if(r !== undefined) {
            r = func.apply(o, [r].concat(a));
        } else {
            r = func.apply(o, a);
        }
        setTimeout(ifunc, time)
    ifunc();
},

timeout: function(func, time, obj, args) {
    var o = obj ? obj : null;
    if(args) {
        setTimeout(function() {
            func.apply(o, args);
        }, time);
    } else {
        setTimeout(function() {
            func.apply(o);
        }, time);
    }
}

};