<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NelsonWells.net</title>
	<atom:link href="http://nelsonwells.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://nelsonwells.net</link>
	<description>Programming and other distractions</description>
	<lastBuildDate>Wed, 08 Feb 2012 04:47:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>JSON.stringify with mapped variables</title>
		<link>http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=json-stringify-with-mapped-variables</link>
		<comments>http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 05:08:08 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Mirth]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=153</guid>
		<description><![CDATA[There are times when I want to create a data structure in Mirth, and output the contents of that data structure while debugging the code.  Luckily, JSON.stringify() is available not only in modern browsers but also in Mirth. var o &#8230;<p class="read-more"><a href="http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>There are times when I want to create a data structure in Mirth, and output the contents of that data structure while debugging the code.  Luckily, JSON.stringify() is available not only in modern browsers but also in Mirth.</p>
<pre>var o = {
  mrn: '8675309',
  labs: [
    'blood bank',
    'microbiology',
    'toxicology'
  ]
};

console.log(JSON.stringify(o, null, '\t'));</pre>
<p>However, there are any types of Mirth mapped variables, the JSON.stringify() method blows up on itself with a message similar to</p>
<pre>DETAILS:    Java class "[B" has no public instance field or method named "toJSON".</pre>
<p>This is how we fix it.</p>
<p><span id="more-153"></span></p>
<p>Consider the following code.  Assume that a variable has been mapped to mrn using Mirth's mapper transformer or a call to channelMap.put().  This code explodes with the aforementioned error.</p>
<pre>var o = {
  mrn: $('mrn'),
  labs: [
    'blood bank',
    'microbiology',
    'toxicology'
  ]
};</pre>
<p>Oddly, if we call logger.error($(&#8216;mrn&#8217;)), the mapped variable shows up correctly.  Our assumption is that $(&#8216;mrn&#8217;) would return a string if the mapped variable was in fact a string (as opposed to a javascript object, for example).  However, if we then call logger.error(typeof $(&#8216;mrn&#8217;)), we get &#8220;object.&#8221;  This should be our first clue that not all is what it seems.</p>
<p>Since I am not a Java programmer, I searched the internet trying to find what &#8220;[B" represents.  I've found that [B is some kind of a byte array in Java, and thus Mirth or maybe even Rhino implements a mapped variable as a byte array.  When JSON.stringify() is called on our data structure, toJSON() is called on each individual element in the structure... since the java byte array [B does not implement toJSON(), an exception is thrown.</p>
<p>So, our goal is to convert the [B object into a javascript string since a javascript string does implement the toJSON() method.  My original instinct was to simply called toString() on the mapped variable, but that failed similarly.</p>
<p>I eventually found that explicitly constructing a javascript string with the new keyword would get the job done.  This is the working code for printing a data structure with a mapped variable.</p>
<pre>var o = {
  mrn: new String($('mrn')),
  labs: [
    'blood bank',
    'microbiology',
    'toxicology'
  ]
};

logger.error(JSON.stringify(o, null, &#8216;\t&#8217;));</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2012/02/json-stringify-with-mapped-variables/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introduction to web scraping with Node.js</title>
		<link>http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introduction-to-web-scraping-with-node-js</link>
		<comments>http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 04:23:02 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=129</guid>
		<description><![CDATA[The internet has a wealth of freely available information in difficult to consume formats.  For example, ClicheSite has lists of cliches, euphemisms, and other phrases that are just perfect for a hangman or Wheel of Fortune game.  Coincidentally, I wanted &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>The internet has a wealth of freely available information in difficult to consume formats.  For example, <a href="http://www.clichesite.com">ClicheSite</a> has lists of cliches, euphemisms, and other phrases that are just <em>perfect</em> for a hangman or Wheel of Fortune game.  Coincidentally, I wanted to write such a game to learn some new technologies, so I wrote a short, simple Node.js script to scrape some pages for those phrases.  In this tutorial, I&#8217;ll discuss how to make an HTTP request and get a page&#8217;s HTML, how to parse the HTML for specific information, and why you would and would not want to do this in the first place.<br />
<span id="more-129"></span></p>
<h3>Identifying Necessary Information</h3>
<p>ClicheSite obviously does not have all of it&#8217;s cliches listed on the home page.  It is technically feasible to begin at the homepage and follow links until we find something useful, but sometimes it makes more sense to take a manual step or two.  In this case, I identified alphabetic listings of phrases; each letter in the alphabet has its own page.  For example, http://clichesite.com/alpha_list.asp?which=lett+1 is a list of all phrases beginning with the letter A and http://clichesite.com/alpha_list.asp?which=lett+26 is a list of all phrases beginning with the letter Z.  So, it is clear that we can open and parse 26 pages to grab our phrases.</p>
<p>Next, we need to look at the pages&#8217; HTML source and identify a way to grab the data we want.  I used Firebug to look at the HTML, but you can also just look at the source directly with your favorite browser.  In Firefox, for example, you can right click anywhere on the page and hit &#8220;View page source.&#8221;  In any case, here is a portion of the HTML we&#8217;re concerned with.</p>
<pre> &lt;tr&gt;
   &lt;td valign="top" bgcolor="#FFFFCC"&gt;&amp;nbsp;&lt;/td&gt;
   &lt;td valign="top" bgcolor="#FFFFCC"&gt;
     &lt;span&gt; &lt;a href="content.asp?which=tip+1332"&gt;Acorn doesn't fall far from the tree, The&lt;/a&gt;&lt;/span&gt;
   &lt;/td&gt;
   &lt;td valign="top" bgcolor="#FFFFCC"&gt;                      
     &lt;span&gt; United States&lt;/span&gt;&lt;/td&gt;
 &lt;/tr&gt;

&lt;tr&gt;
  &lt;td valign="top" bgcolor="#FFFFCC"&gt;&amp;nbsp;&lt;/td&gt;
  &lt;td valign="top" bgcolor="#FFFFEE"&gt;  
    &lt;span&gt; &lt;a href="content.asp?which=tip+65"&gt;Actions speak louder than words&lt;/a&gt;&lt;/span&gt;
  &lt;/td&gt;                         
  &lt;td valign="top" bgcolor="#FFFFEE"&gt;         
  &lt;span&gt; United States&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;</pre>
<p>Let&#8217;s examine what we have here.  The HTML shows us that we have two rows with 3 columns.  We see that the two phrases are in the second column wrapped in a span and anchored (linked).  One possible action we could take is to write an HTML parser or use a 3rd party library to parse the HTML and then drill down to that HTML node.  However, for this particular case, that solution is a shovel when all you really need is a spoon.  Instead, we&#8217;ll use a regular expression to grab the phrases&#8230; but how?</p>
<p>Notice that each phrase is surrounded by an anchor tag, and inside that anchor tag is the word &#8220;tip&#8221;.  That will be the basis for our regular expression.  The content between the anchor tag with &#8220;tip&#8221; in the href attribute will be our phrase.  We&#8217;ll see that regular expression in the next section.</p>
<h3>The Code</h3>
<p>Since the code is so short, I&#8217;ll let you look over it and familiarize yourself with it before I explain it.</p>
<pre>var http = require('http');

var options;
var regex = /&lt;a.*tip.*&gt;(.*)&lt;\/a&gt;/g;

for(var i = 1; i &lt;= 26; i++) {

  options = {
    host: 'clichesite.com',
    path: '/alpha_list.asp?which=lett+' + i
  };

  http.get(options, function(res) {

    // accessible to 'data' and 'end' events
    var data = '';

    res.on('data', function(chunk) {
      data += chunk.toString();
    })
    .on('end', function() {
      while((match = regex.exec(data))) {
        console.log(match[1]);
      }
    });
  });

}</pre>
<p>First, we load the HTTP module.  We&#8217;ll use this to make HTTP requests to ClicheSite.  Then, we&#8217;ll define an options variable.  This is used as a parameter in the HTTP request and identifies the host and path (effectively, the URL) to hit.  Finally, we define a regex literal to identify the phrases.  Let&#8217;s break it apart piecewise.</p>
<pre>&lt;a   - <em>less than followed by the letter a</em>
.*   - <em>followed by any character any number of times</em>
tip  - <em>followed by the letters t, i, p</em>
.*   - <em>followed by any character any number of times</em>
&gt;    - <em>followed by a greater than</em>
(.*) - <em>followed by any character any number of times, and capture it</em>
&lt;    - <em>followed by a less than</em>
\/a  - <em>followed by a forward slash and the letter a</em>
&gt;    - <em>followed, finally, by greater than</em></pre>
<p>We&#8217;ll match it globally.  Later, we&#8217;ll loop through the result of the regular expression and grab the captured phrase.</p>
<p>Now, since we&#8217;ve previously identified that we need to scrape pages where lett+ a number 1 through 26 appears in the URL, we&#8217;ll loop through that range.  We&#8217;ll populate that options variable we created earlier with an object with two properties, host and path.  The host is the domain we wish to hit with our HTTP request, and the path is basically everything past that point in the URL.  Notice that we&#8217;re appending our loop index to the end of the path.  That is how we&#8217;ll hit pages A through Z.</p>
<p>Now, we&#8217;ll make an HTTP request.  All we have to do is call the get method of the HTTP object. We&#8217;ll define a callback function with an HTTP result object as a parameter&#8230; we&#8217;ll register events on this res object to do the actual scraping.  In the .get callback, we define an empty string called data.  This will eventually hold the full HTML content of the page.</p>
<p>Next, we register two events on the res object.  The first event, &#8220;data&#8221;, is fired when data is received.  When that happens, we&#8217;ll just append that data to the data string we defined.  The next event, &#8220;end&#8221; is fired when the HTTP request has finished.  When that happens, we will have the full HTML document.  This is where we do the work.</p>
<p>In the callback to this event, we loop through the results of our regular expression with the following construct:</p>
<pre>while((match = regex.exec(data))) {</pre>
<p>The regular expression exec will eventually evaluate to null, a falsey value, and the loop will end.  In the body of the loop, we can access the phrase with match[1].  Match[0], of course, contains the whole matched expression; we just want the capturing group.  In this example, I simply print the phrase to the screen&#8230; you&#8217;ll likely want to do more to the data than that, though.</p>
<h3>Pitfalls</h3>
<p>One thing you&#8217;ll notice about this solution is that the results are not in alphabetical order even though we iterate alphabetically from A to Z.  This is because of Node.js&#8217; event-driven, asynchronous nature.  In the body of the most broad loop, we make an HTTP request.  However, that request will most likely not finish before the we hit the next iteration of the loop.  Processing seed is much faster than network latency, after all.  In fact, when I was testing the script, I was often making 5-10 HTTP requests before the first one returned!  For this simple example, if you wanted a sorted list you could run the script and pipe to sort</p>
<pre>node index.js | sort</pre>
<p>More likely, you&#8217;ll want to store the results in a data structure and sort it or in a database so it can be sorted later.  This depends on context, of course.</p>
<p>Ironically, you also need to be wary of scraping pages heavy with Javascript.  If the contents of the page are dynamic, you may not have access to the data you actually want to get!</p>
<h3>Final Thoughts</h3>
<p>Why scrape web pages?  If you are feeling black hat, it is relatively simple to scrape for email addresses, phone numbers, and addresses.  In the real world, you may want to scrape your own web applications to ensure data validity and correct formatting of data.</p>
<p>In any case, please be nice!  Don&#8217;t break a website&#8217;s terms of use, and most certainly do not blame it on me! <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Happy coding</p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/11/introduction-to-web-scraping-with-node-js/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Swap object keys and values in Javascript</title>
		<link>http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=swap-object-key-and-values-in-javascript</link>
		<comments>http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 01:53:11 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=125</guid>
		<description><![CDATA[There are times when I would like to do work with the values in a Javascript object used as a hash map.  For example, sometimes I&#8217;d like to iterate over the values and perform an action on them, or perhaps &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>There are times when I would like to do work with the values in a Javascript object used as a hash map.  For example, sometimes I&#8217;d like to iterate over the values and perform an action on them, or perhaps check that a value exists in the hash map.  In this post, I&#8217;ll write a function that inverts the keys and values in a hash map, give a couple of examples in regards to how and why you&#8217;d want to do that, and explain the short-comings of the approach.</p>
<p><span id="more-125"></span></p>
<h3>The Invert Function</h3>
<pre>var invert = function (obj) {

  var new_obj = {};

  for (var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      new_obj[obj[prop]] = prop;
    }
  }

  return new_obj;
};</pre>
<p>The function itself is fairly simple.  We&#8217;ll pass an object as a parameter; this is the object whose keys and values we&#8217;ll invert.  We then create a new empty object; this is the object that we will return with the inverted keys and values.  We do not operate on the object that we pass as a parameter because we do not want to change the original object.</p>
<p>First, we&#8217;ll loop through the properties of obj.  We&#8217;ll use hasOwnProperty to verify that the keys we invert were defined on the object itself and not up the prototype chain.  In the loop, we&#8217;ll create a new key from the value of the key in the original object.  We&#8217;ll assign the value of that key the property we&#8217;re currently looking at in our iteration.  That&#8217;s all there is to inverting the keys and values!</p>
<p>Of course, we&#8217;ll return the newly generated object.</p>
<h3>Use Cases</h3>
<p>Okay, so we can invert k, v pairs.  What can we do with that, though?  How about iterating over them and performing some kind of action on it?</p>
<pre>var obj = {
  firstname : "nelson",
  middlename : "dane",
  lastname: "wells",
};

var name = '';

for(var value in invert(obj)) {
  name += value + ' ';
}

console.log(name.trim());</pre>
<p>Maybe we want to know if a value exists in the hash map?</p>
<pre>var obj = {
  firstname : "nelson",
  middlename : "dane",
  lastname: "wells",
};

if(invert(obj)['dane']) {
  //value exists in the hash
  console.log("Value exists");
} else {
  console.log("Value does not exist");
}

if(invert(obj)['terry']) {
  console.log("Value exists");
} else {
  console.log("Value does not exist");
};</pre>
<p>Of course, there&#8217;s nothing preventing you from inverting the keys, saving the inversion in a var, and doing something with it later.  In fact, you may want to do that&#8230;</p>
<h3>Shortcomings</h3>
<p>There are some obvious shortcomings with this function.  First, every time we call it, we&#8217;re iterating over the object&#8217;s properties.  Of course, we&#8217;re not going to want to do this in a loop because of performance implications.  Instead, we would want to call the function once and assign the result to a variable, and operate on <em>that</em> object.</p>
<p>Another shortcoming is the hash map must have only one to one relationships.  If a value exists for two keys, when the object is inverted, we&#8217;ll lose a key in the process.  It should be trivial to add exception handling to the function or some other mechanism to handle this deficiency gracefully, so if anyone is interested in that and can&#8217;t do it themselves, I&#8217;d be happy to help.</p>
<p>We&#8217;ll also prefer non-nested objects.  An array, another object, or a function may not make a great key <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introduction to memoization with Javascript</title>
		<link>http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=introduction-to-memoization-with-javascript</link>
		<comments>http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/#comments</comments>
		<pubDate>Sun, 25 Sep 2011 21:03:45 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Observation]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[recursion]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=112</guid>
		<description><![CDATA[Memoization is a function optimization technique used to avoid remaking calculations in subsequent function calls.  The classic example, which we&#8217;ll demonstrate here, is the factorial function.  5! = 5 * 4 * 3 * 2 * 1&#8230; factorials are recursive &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Memoization is a function optimization technique used to avoid remaking calculations in subsequent function calls.  The classic example, which we&#8217;ll demonstrate here, is the factorial function.  5! = 5 * 4 * 3 * 2 * 1&#8230; factorials are recursive in nature if we give it some thought.  5! = 5 * 4! and 4! = 4 * 3! and so on.  By recognizing this pattern, we can also recognize that if we calculate 5! and save the results, then we should not have to recalculate it when we do 7!.  Instead of calculating 7! by 7 * 6 * 5 * 4 * 3 * 2 * 1, we&#8217;ll calculate it by 7 * 6 * 5!.</p>
<p>We&#8217;ll first examine the naive approach and then the memoization method.  All in Javascript, and all with code samples&#8230;<br />
<span id="more-112"></span></p>
<h3>The Naive Approach</h3>
<p>The naive approach is very simple.  This is a snip / modification of the larger script, which you can see at the bottom of this post, but you will get the point.</p>
<pre>function naive(n) {
  if(n &lt;= 1) { return 1; }
    return n * naive(n - 1);
  }
}</pre>
<p>In this function, the parameter n is the value of the factorial we wish to calculate.  In this recursive function call, our base case will be when the parameter is 1.  1! = 1, of course, so instead of recursing we&#8217;ll simple return the value.  If n is greater than 1, we&#8217;ll recursively call the function, returning the current value we wish to calculate multiplied by n &#8211; 1.</p>
<p>While this approach works, it is wasteful.  By calling naive(5), we calculate 5 * 4 * 3 * 2 * 1.  Instead of saving the value of naive(5) to be used the next time we call the function, we effectively discard it.  When we call, naive(7), we cannot reuse the value we found for naive(5).</p>
<h3>The Memoization Approach</h3>
<p>The memoization approach is only slightly more complicated.  Again, this code is a section of a larger script, so bear with me.</p>
<pre>var lookup = {};

function memoized(n) {
  if(n &lt;= 1) { return 1; }

  if(lookup[n]) {
    return lookup[n];
  }

  lookup[n] = n * memoized(n - 1);
  return lookup[n];
}</pre>
<p>First, we create an empty object to serve as a lookup table for our factorial function.  This is where we&#8217;ll save the factorials that we&#8217;ve already calculated.  Our function has the same parameter and base case as our naive example.  The difference in the function is the lookup.  If the value of n is a key in our lookup table, then we simply return that value.  If the value isn&#8217;t in the lookup table, we&#8217;ll save it in the lookup table for later.  Now that we&#8217;ve found and saved the value of factorial n, we&#8217;ll return it to the caller.</p>
<p>If we first call memoized(5), we&#8217;ll calculate 5 * 4 * 3 * 2 * 1.  If we then call memoized(7), we&#8217;ll calculate 7 * 6 * 5!, the 5! being saved in the lookup table.  Much faster!</p>
<h3>The Full Script and Observations</h3>
<p>I said previously that the snippets above were part of a larger script.  In the process of writing this post, I wrote the functions as part of a Javascript object I also wrote a function to test the speed increase.  While not absolutely scientific, it should help you grasp the kind of increase you can expect over the succession of function calls.  The script was written and executed in node.js, but should work just as well in Firebug or even Rhino if you remove the #! script declaration.</p>
<p>For what it&#8217;s worth, on my machine node.js executed the test set for the naive method in ~5ms and the memoization method in ~1ms.  Firebug / Firefox 6.0 executed the test set for the naive method in ~14ms and the memoization method in ~1ms.  I think that says something about the speed of the V8 Javascript engine.</p>
<p>Feel free to use / modify this script for your own tests.  I hope that this example helps you speed up your code in the future.</p>
<pre>#!/usr/local/bin/node

var factorial = (function() {
  var lookup = {};

  return {
    //show_lookup is mainly for debugging purposes
    show_lookup : function() { return lookup; },

    run : {

      naive : function(n) {
        if(n &lt;= 1) { return 1; }
        return n * this.naive(n - 1);
      },

      memoized : function(n) {
        if(n &lt;= 1) { return 1; }

        if(lookup[n]) {
          return lookup[n];
        }

        lookup[n] = n * this.memoized(n - 1);
        return lookup[n];
      }

    }
  };
})();

var caller = function(method) {
  var start = (new Date()).getTime();

  for(var i = 0; i &lt;= 150; i++) {
    factorial.run[method](i);
  }

  for(var j = 150; j &gt; 1; j--) {
    factorial.run[method](j);
  }

  return (new Date()).getTime() - start;
};

console.log(caller("naive"));
console.log(caller("memoized"));</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/09/introduction-to-memoization-with-javascript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Maintain a running list of your external IP address</title>
		<link>http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=maintain-a-running-list-of-your-external-ip-address</link>
		<comments>http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/#comments</comments>
		<pubDate>Mon, 08 Aug 2011 03:46:57 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=105</guid>
		<description><![CDATA[At home, I have a consumer level cable internet service.  I actually do not know if I have a dynamic IP address or a static IP address because I haven&#8217;t really cared enough to ask my ISP.  I would assume &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>At home, I have a consumer level cable internet service.  I actually do not know if I have a dynamic IP address or a static IP address because I haven&#8217;t really cared enough to ask my ISP.  I would assume that I have a dynamic IP address since most ISPs charge a premium for a static IP address, but since I don&#8217;t know for sure I thought I would find out for myself.</p>
<p>Using http://whatismyip.com &#8216;s &#8220;automation&#8221; page, Perl, and cron, I am going to maintain a list of my external IP addresses.  Not only will this answer the original question, but I can also gather some additional information, such as how often my IP address changes and whether or not I can force my IP address to change by disconnecting my modem <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p><span id="more-105"></span></p>
<h3>The logical steps</h3>
<p>The method I am going to use is relatively simple.  First, I need a script that will fetch a page with my current external IP address.  I&#8217;m going to use Perl, but any scripting language will do.  Once the script has fetched my current IP address, I will append the IP address and the current date, separated by a comma, to a log file.  I want the two fields to be comma separated in case I ever want to run a script over the log it will be easy to grab the information I want.</p>
<p>Once the script is finished, I need a way to automate it.  I would like to do this once a day&#8230; you may want to do this less often or more often depending on your goal.  Luckily, this is simple to do with cron, the Linux utility to run scheduled tasks.</p>
<h3>The code</h3>
<p>First, we need to create the script.  I am going to call my script ip_logger.pl.  We need to declare that the file is a Perl script, give the usual safety directives, and load relevant libraries.</p>
<pre>#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
use LWP::Simple;
use Time::localtime;</pre>
<p>I&#8217;ve loaded File::Slurp to ease reading and writing the the log file.  I&#8217;ve loaded LWP::Simple (libwww-perl) to fetch the page with our external IP.  I use Simple since we just need to make a GET request, we don&#8217;t need any additional features.  I&#8217;ve loaded Time::localtime to make generating a current date string simple and easy to read.</p>
<p>Next, we need to decide where we&#8217;re going to put our log file, and then actually make the request to the website to retrieve our external IP address.</p>
<pre># cron runs the script from your home directory,
# so give an absolute path
my $ip_addresses_filename = '/home/nelson/projects/perl/ip_logger/ip_addresses.txt';

# get current external ip address
my $content = get('http://automation.whatismyip.com/n09230945.asp');
$content = 'Could not pull ip address!' if !$content;</pre>
<p>Let&#8217;s notice that we create a scalar called $content and populate it with the contents at the whatismyip.com &#8216;s automation page.  The page has no HTML, it only contains the IP address, so we don&#8217;t have to parse the IP address or do anything else.  We&#8217;ll just assign the returned string to the scalar.  Also notice that if the page fetch fails, we&#8217;ll put a string indicative of such in the $content scalar.</p>
<p>Next, we need to capture the current date.  I&#8217;m going for the month-day-year format.</p>
<pre># get the current date to also write to our file
my $month = localtime-&gt;mon + 1;
my $day = localtime-&gt;mday;
my $year = localtime-&gt;year + 1900;
my $current_date = "$month-$day-$year";</pre>
<p>The last thing the script needs to do is actually write to the log file.  File::Slurp&#8217;s write_file function is smart enough to create the file if it doesn&#8217;t exist so we don&#8217;t need to guard against that.</p>
<pre># write / append it to the file
write_file($ip_addresses_filename, {append =&gt; 1}, $content . ',' . $current_date . "\n");</pre>
<h3>The cron</h3>
<p>The script by itself will not do a whole lot of good.  Unless you want to manually run the script once a day, we need to schedule it to run automatically.  In shell, we will do crontab -e to open our crontab for editing.  Then, we&#8217;ll insert this line.</p>
<pre>30 6 * * * /home/nelson/projects/perl/ip_logger/ip_logger.pl</pre>
<p>I want to run the script at 6:30 AM every day.  As I said earlier, you may want to adjust the interval to something more appropriate for your situation.</p>
<h3>The result</h3>
<p>After a few days, I&#8217;ll have a log file that looks similar to this.</p>
<pre>104.94.155.241,8-8-2011
104.94.155.241,8-9-2011
104.94.155.241,8-10-2011
104.94.155.241,8-11-2011
104.94.155.241,8-12-2011
104.94.155.241,8-13-2011</pre>
<p>Happy automating!</p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/08/maintain-a-running-list-of-your-external-ip-address/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fixing line breaks in HL7 messages in Mirth Connect</title>
		<link>http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fixing-line-breaks-in-hl7-messages-in-mirth-connect</link>
		<comments>http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 04:07:28 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Mirth]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[e4x]]></category>
		<category><![CDATA[hl7]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=95</guid>
		<description><![CDATA[Anyone who has worked in the world of healthcare integration or with HL7 knows that if you have seen one HL7 message, you&#8217;ve seen one HL7 message.  Now, a common problem with some source systems is that a line break &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Anyone who has worked in the world of healthcare integration or with HL7 knows that if you have seen one HL7 message, you&#8217;ve seen <em>one</em> HL7 message.  Now, a common problem with some source systems is that a line break will sneak in the middle of a segment, rendering the whole message invalid.  How many times have you seen this message?</p>
<pre>MSH|^~\&amp;|DDTEK LAB|ELAB-1|DDTEK OE|BLDG14|200502150930||ORU^R01^ORU_R01|CTRL-9876|P|2.4
PID|||010-11-1111||Estherhaus^Eva^E^^^^L|Smith|19720520|F|||256 Sherwood Forest Dr.^^Baton Rouge^LA^70809||(225)334-5232|(225)752-1213||||AC010111111||76-B4335^LA^20070520
OBR|1|948642^DDTEK OE|917363^DDTEK LAB|1554-5^GLUCOSE|||200502150730|||||||||020-22-2222^Levin-Epstein^Anna^^^^MD^^Micro-Managed
Health Associates|||||||||F|||||||030-33-3333&amp;Honeywell&amp;Carson&amp;&amp;&amp;&amp;MD
OBX|1|SN|1554-5^GLUCOSE^^^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^175|mg/dl|70_105|H|||F</pre>
<p>Notice the &#8220;Health Associates&#8221; segment? Obviously, this segment invalidates the message.  When this message is sent through a Mirth channel that expects incoming HL7, the message will error out when Mirth tries to parse it.  Here is how we can fix that.</p>
<p><span id="more-95"></span></p>
<h3>The Solution</h3>
<p>To fix this, we&#8217;re going to use a channel&#8217;s preprocessor script to append seemingly broken segments to the previous segment.  Since the preprocessor script is invoked <em>before</em> Mirth&#8217;s HL7 parser, we don&#8217;t have to worry about Mirth&#8217;s HL7 parser choking on it.</p>
<p>Instead of explaining the logic in a separate paragraph, I have left inline comments to explain what is happening.  I think, though, that it is fairly easy to follow.</p>
<p>Paste the following code into your channel&#8217;s preprocessor script.</p>
<h3>The Code</h3>
<pre>// initialize a first_iteration flag.
// we don't want to add a carriage return
// before the MSH segment
var first_iteration = true;

// initialize the new message as an empty string
var new_message = '';

// loop over each line in the message
// by splitting on the hl7 standard carriage return
for each (var line in message.split(/\r/)) {

  // if it is a valid hl7 segment, we'll
  // append the new line to the new message
  if(line.match(/^[a-zA-Z0-9]{3}\|/)) {
    // see the first comment
    if( ! first_iteration){
      new_message += '\r';
    }
    new_message += line;
  } else {
    // if it isn't a valid hl7 segment,
    // we'll append it to the end of the
    // previous segment instead
    new_message += ' ' + line;
  }

  // it will never be the first_iteration again
  first_iteration = false;
}

//send the fixed message to the channel
message = new_message;

return message;</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/07/fixing-line-breaks-in-hl7-messages-in-mirth-connect/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A visual comparison of the good and bad parts of Javascript</title>
		<link>http://nelsonwells.net/2011/02/a-visual-comparison-of-the-good-and-bad-parts-of-javascript-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-visual-comparison-of-the-good-and-bad-parts-of-javascript-2</link>
		<comments>http://nelsonwells.net/2011/02/a-visual-comparison-of-the-good-and-bad-parts-of-javascript-2/#comments</comments>
		<pubDate>Sat, 12 Feb 2011 06:58:27 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Observation]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=55</guid>
		<description><![CDATA[Javascript can be very expressive and powerful in the right hands.  It isn&#8217;t without it&#8217;s faults, though.  For an actual dissection of both the good parts and the bad parts of the language, I recommend Douglas Crockford&#8217;s book, Javascript: The &#8230;<p class="read-more"><a href="http://nelsonwells.net/2011/02/a-visual-comparison-of-the-good-and-bad-parts-of-javascript-2/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Javascript can be very expressive and powerful in the right hands.  It isn&#8217;t without it&#8217;s faults, though.  For an actual dissection of both the good parts and the bad parts of the language, I recommend Douglas Crockford&#8217;s book, <a href="http://www.amazon.com/exec/obidos/ASIN/0596517742/wrrrldwideweb">Javascript: The Good Parts</a>.  In the mean time, take a look at this picture.  The difference in page count between the Javascript reference and The Good Parts is pretty accurate <img src='http://nelsonwells.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://nelsonwells.net/wp-content/uploads/2011/06/javascript_good_and_bad_parts.jpg"><img class="alignnone size-full wp-image-61" title="javascript_good_and_bad_parts" src="http://nelsonwells.net/wp-content/uploads/2011/06/javascript_good_and_bad_parts.jpg" alt="" width="600" height="210" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2011/02/a-visual-comparison-of-the-good-and-bad-parts-of-javascript-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zip code library in CodeIgniter</title>
		<link>http://nelsonwells.net/2010/07/zip-code-library-in-codeigniter/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zip-code-library-in-codeigniter</link>
		<comments>http://nelsonwells.net/2010/07/zip-code-library-in-codeigniter/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 00:31:34 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=47</guid>
		<description><![CDATA[Recently, a client wanted a member search for his website that included a search by zip code. The &#8216;easy&#8217; solution would be to implement the search as a LIKE statement in SQL, but the solution is inaccurate, and I like &#8230;<p class="read-more"><a href="http://nelsonwells.net/2010/07/zip-code-library-in-codeigniter/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Recently, a client wanted a member search for his website that included a search by zip code.  The &#8216;easy&#8217; solution would be to implement the search as a LIKE statement in SQL, but the solution is inaccurate, and I like the &#8216;good&#8217; solutions over the &#8216;easy&#8217; ones.  I looked for a CodeIgniter library that would give me the functionality for which I wanted to implement, but no such thing existed.  Then, I came across Micah Carrick&#8217;s native PHP library which gave the exact functionality I was looking for.  I did end up using his library, but not without modification: I&#8217;ve ported the native library to a CodeIgniter library.  This is where you can get it.</p>
<p><span id="more-47"></span></p>
<h3>The Code</h3>
<p>First, you&#8217;ll need to create your database.  You can use this MySQL script to create the table.</p>
<pre>CREATE TABLE `zip_code` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `zip_code` varchar(5) collate utf8_bin NOT NULL,
  `city` varchar(50) collate utf8_bin default NULL,
  `county` varchar(50) collate utf8_bin default NULL,
  `state_name` varchar(50) collate utf8_bin default NULL,
  `state_prefix` varchar(2) collate utf8_bin default NULL,
  `area_code` varchar(3) collate utf8_bin default NULL,
  `time_zone` varchar(50) collate utf8_bin default NULL,
  `lat` float NOT NULL,
  `lon` float NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `zip_code` (`zip_code`)</pre>
<p>You will need to populate the table, of course, and you will do so with the MySQL scripts included in the project.</p>
<p><a href="http://www.nelsonwells.net/assets/downloads/geozip_example.zip">Download the project.</a></p>
<p>Now, for the meat and potatoes.  Here is the library itself.  It is GPL Version 3 licensed so keep that in mind if you decide to use it.</p>
<pre><!--?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); //constant for convering to kilometers from miles define('M2KM_FACTOR', 1.609344); // constants for passing $sort to get_zips_in_range() define('SORT_BY_DISTANCE_ASC', 1); define('SORT_BY_DISTANCE_DESC', 2); define('SORT_BY_ZIP_ASC', 3); define('SORT_BY_ZIP_DESC', 4); class Geozip  {     var $units;     var $decimals;     var $last_error;     var $CI;          function __construct()     {         $this--->&lt;?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

//constant for convering to kilometers from miles
define('M2KM_FACTOR', 1.609344);

// constants for passing $sort to get_zips_in_range()
define('SORT_BY_DISTANCE_ASC', 1);
define('SORT_BY_DISTANCE_DESC', 2);
define('SORT_BY_ZIP_ASC', 3);
define('SORT_BY_ZIP_DESC', 4);

class Geozip
{
  var $units;
  var $decimals;
  var $last_error;
  var $CI;

  function __construct()
  {
    $this-&gt;CI = get_instance();

    $this-&gt;units = "miles";
    $this-&gt;decimals = 2;
  }

  function get_zip_details($zip)
  {
    $this-&gt;CI-&gt;db-&gt;select("lat AS lattitude, lon AS longitude, city, county, state_prefix");
    $this-&gt;CI-&gt;db-&gt;select("state_name, area_code, time_zone");
    $this-&gt;CI-&gt;db-&gt;where("zip_code", $zip);
    $results = $this-&gt;CI-&gt;db-&gt;get("zip_code");

    if($results-&gt;num_rows() &lt; 1)
    {
      $this-&gt;set_last_error("Zip not found in database");
      return false;
    }
    else
    {
      return $results-&gt;row();
    }
  }

  function get_zips_in_range($zip, $range, $sort=1, $include_base=true)
  {
    //get base zip details
    $details = $this-&gt;get_zip_point($zip);

    if( ! $details)
    {
      return false;
    }

    //find max - min lat / long for radius and zero point and query
    //only zips in that range.
    $lat_range = $range/69.172;
    $lon_range = abs($range/(cos($details-&gt;lat) * 69.172));
    $min_lat = number_format($details-&gt;lat - $lat_range, "4", ".", "");
    $max_lat = number_format($details-&gt;lat + $lat_range, "4", ".", "");
    $min_lon = number_format($details-&gt;lon - $lon_range, "4", ".", "");
    $max_lon = number_format($details-&gt;lon + $lon_range, "4", ".", "");

    //build the sql query
    $this-&gt;CI-&gt;db-&gt;select("zip_code, lat, lon");

    if( ! $include_base)
    {
      $this-&gt;CI-&gt;db-&gt;where("zip_code &lt;&gt;", $zip);
    }

    $this-&gt;CI-&gt;db-&gt;where("lat BETWEEN '$min_lat' AND '$max_lat'");
    $this-&gt;CI-&gt;db-&gt;where("lon BETWEEN '$min_lon' AND '$max_lon'");

    $result = $this-&gt;CI-&gt;db-&gt;get("zip_code");

    if($result-&gt;num_rows() &lt; 1)
    {
      $this-&gt;set_last_error("SQL error in get_zips_in_range");
      return false;
    }
    else
    {
      //loop through all 40 some thousand zip codes and determine whether
      //or not it's within the specified range.

      foreach($result-&gt;result() as $row)
      {
        $distance = $this-&gt;calculate_mileage($details-&gt;lat,$row-&gt;lat,$details-&gt;lon,$row-&gt;lon);

        if($this-&gt;units == "kilos")
        {
          $distance *= M2KM_FACTOR;
        }

        if($distance &lt;= $range)
        {
          $zips[$row-&gt;zip_code] = $distance;
        }
      }
    }

    //sort the zips as selected
    switch($sort)
    {
      case SORT_BY_DISTANCE_ASC:
        asort($zips);
        break;

      case SORT_BY_DISTANCE_DESC:
        arsort($zips);
        break;

      case SORT_BY_ZIP_ASC:
        ksort($zips);
        break;

      case SORT_BY_ZIP_DESC:
        krsort($zips);
        break;
    }

    return $zips;

  }

  /*
  * Get the distance between 2 zip codes.
  */
  function get_distance($zip1, $zip2)
  {
    //return 0 miles / kilos if its the same zip
    if($zip1 == $zip2)
    {
      return 0;
    }

    //get the details from the database and exit if there is an error
    $details1 = $this-&gt;get_zip_point($zip1);
    $details2 = $this-&gt;get_zip_point($zip2);

    if($details1 === false || $details2 === false)
    {
      return false;
    }

    //calculate the distance between the 2 zip codes based on
    //the latitude and longitude pulled from the database
    $miles = $this-&gt;calculate_mileage($details1-&gt;lat,
    $details2-&gt;lat,
    $details1-&gt;lon,
    $details2-&gt;lon);

    if($this-&gt;units == "kilos")
    {
      return round($miles * M2KM_FACTOR, $this-&gt;decimals);
    }
    else
    {
      return round($miles, $this-&gt;decimals);
    }   
  }

  /*
  * Set the units to describe distance
  * Accepts "miles" or "kilos"
  */
  function set_units($units = "miles")
  {
    if($units != "kilos" || $units != "miles")
    {
      $this-&gt;units = "miles";
    }
    else
    {
      $this-&gt;units = $units;
    }
  }

  function get_last_error()
  {
    return $this-&gt;last_error();
  }

  /*
  * Pull latitude and longitude from the database
  */
  private function get_zip_point($zip)
  {
    $this-&gt;CI-&gt;db-&gt;select("lat, lon")-&gt;where("zip_code", $zip);
    $result = $this-&gt;CI-&gt;db-&gt;get("zip_code");

    if($result-&gt;num_rows() &lt; 1)
    {
      $this-&gt;set_last_error("Zip code not found in db: $zip");
      return false;
    }
    else
    {
      return $result-&gt;row();
    }
  }

  private function calculate_mileage($lat1, $lat2, $lon1, $lon2)
  {
    //convert lattitude/longitude (degrees) to radians for calculations
    $lat1 = deg2rad($lat1);
    $lon1 = deg2rad($lon1);
    $lat2 = deg2rad($lat2);
    $lon2 = deg2rad($lon2);

    //find the deltas
    $delta_lat = $lat2 - $lat1;
    $delta_lon = $lon2 - $lon1;

    //find the Great Circle distance
    $temp = pow(sin($delta_lat/2.0),2) + cos($lat1) * cos($lat2) * pow(sin($delta_lon/2.0),2);
    $distance = 3956 * 2 * atan2(sqrt($temp),sqrt(1-$temp));

    return $distance;
  }

  private function set_last_error($error)
  {
    $this-&gt;last_error = $error;
  }
}</pre>
<h3>How to use</h3>
<p>The library supports 3 main features right now: get zip details, get distance between 2 zip codes, and get a list of zip codes in a given radius of another zip code.  The library supports miles and kilometers as distance units.  I&#8217;ll demonstrate how to use each of these functions, and how to change the units.</p>
<p>Copy the code above into a file named geozip.php and place it in the application/libraries folder in your CodeIgniter installation.  Then, in whatever controller you want to use it in, load it like you would any other library.</p>
<pre>$this-&gt;load-&gt;library("geozip");</pre>
<p>Getting and displaying the zip&#8217;s details are simple.  In the controller, you would do</p>
<pre>$zip_details = $this-&gt;geozip-&gt;get_zip_details($this-&gt;input-&gt;post("zip"));
$data['zip_details'] = $zip_details;</pre>
<p>and then in the view, you could access the following variables:</p>
<pre>echo $zip_details-&gt;lattitude;
echo $zip_details-&gt;longitude;
echo $zip_details-&gt;city;
echo $zip_details-&gt;county;
echo $zip_details-&gt;state_prefix;
echo $zip_details-&gt;state_name;
echo $zip_details-&gt;area_code;
echo $zip_details-&gt;time_zone;</pre>
<p>Getting the distance between 2 zips is equally as easy.</p>
<pre>$distance = $this-&gt;geozip-&gt;get_distance("90210", "60601");</pre>
<p>Doing a radial search is only slightly more complicated, but only because you have some options when you call the function.  The function accepts 4 parameters: the zip code, the range to cover, sort order, and whether or not to include the original zip in the result set.  The default sort order is sorted by distance ascending, and the default &#8216;include base&#8217; is true.  You can change the default sort order using the following defines, and you can change the &#8216;include base&#8217; by setting it to boolean false.</p>
<pre>// constants for passing $sort to get_zips_in_range()
define('SORT_BY_DISTANCE_ASC', 1);
define('SORT_BY_DISTANCE_DESC', 2);
define('SORT_BY_ZIP_ASC', 3);
define('SORT_BY_ZIP_DESC', 4);</pre>
<p>Here is how you could find all the zips in a 20 mile radius of Beverly Hills sorted by zip ascending, but not including Beverly Hills.</p>
<pre>$zips = $this-&gt;geozip-&gt;get_zips_in_range("90210", 20, SORT_BY_ZIP_ASC, false);
$data['zips'] = $zips;</pre>
<p>$zips will be an associative array with the zip code as the key and the distance from the origin zip as the value.  You can process this in your controller or view as you see fit.</p>
<pre>foreach($zips as $zip =&gt; $distance)
{
  echo "$zip is $distance miles away from the origin.";
  //or other processing you wish to do with these zips.
}</pre>
<p>I did say that the library supports miles and kilometers.  To change between them, simply do</p>
<pre>$this-&gt;geozip-&gt;set_units("kilos"); //only accepts "miles" or "kilos"</pre>
<p>And any function that returns a distance will return whichever unit you&#8217;ve specified.</p>
<h3>Things to remember</h3>
<p>The biggest problem with this approach is the database.  As stated in the original blog by Micah, the database was derived from a variety of sources and may be out of date.  Depending on how critical this feature is to your application, the current database may or may not work.  If you want an up to date database, you&#8217;ll probably have to purchase and import it yourself.</p>
<p>You can <a href="http://www.nelsonwells.net/assets/downloads/geozip_example.zip">download an example application</a> that is ready to deploy, but it is likely to become outdated as time passes and I make feature and bug changes.  You can always get the latest version in the <a href="http://bitbucket.org/nelson.wells/geozip">BitBucket repo</a>.</p>
<p>If you have any questions or comments, post them here and I&#8217;ll be sure to answer them!  You can also <a href="http://www.nelsonwells.net/contact">contact me</a> if your issues should remain private.  Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2010/07/zip-code-library-in-codeigniter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>&#8220;Presto&#8221; math trick in Java</title>
		<link>http://nelsonwells.net/2010/06/presto-math-trick-in-java/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=presto-math-trick-in-java</link>
		<comments>http://nelsonwells.net/2010/06/presto-math-trick-in-java/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 23:33:59 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[math]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=35</guid>
		<description><![CDATA[According to Futility Closet, if you start with a 3 digit and place it next to the same number to form a 6 digit number, you can divide the 6 digit number by 7, 11, and then 13 and you &#8230;<p class="read-more"><a href="http://nelsonwells.net/2010/06/presto-math-trick-in-java/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>According to <a href="http://www.futilitycloset.com/2007/11/14/presto/">Futility Closet</a>, if you start with a 3 digit and place it next to the same number to form a 6 digit number, you can divide the 6 digit number by 7, 11, and then 13 and you will end up with the original 3 digit number and no remainders.  For example, by taking the number 412 and making it 412412 and then doing the divisions, you will end up with 412.  I wrote a small program in Java to test it.</p>
<p><span id="more-35"></span></p>
<h3>The Code</h3>
<pre>public class Main
{
  public static void main(String[] args)
  {
    for(int i = 100; i &lt;= 999; i++)
    {
      //get the number, and "double" it
      int number = Integer.parseInt(Integer.toString(i) + Integer.toString(i));

      //successively divided by 7, 11, then 13
      System.out.print((i) + "\t");
      System.out.print((number) + "\t");
      System.out.print((number /= 7) + "\t");
      System.out.print((number /= 11) + "\t");
      System.out.print(number /= 13);

      //is the result what we expect? (input == output)
      if(i == number)
      {
        System.out.print("\tCorrect\n");
      }
      else
      {
        System.out.print("\tIncorrect");
        break;
      }
    }
  }
}</pre>
<p>In this snippet, we loop through all 3 digit numbers (100 to 999) and output the results of each operation in a tab separated column.  If the result (output) is the same as the input, we print correct and continue with the loop.  Otherwise, we print incorrect and break.  Give it a try!</p>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2010/06/presto-math-trick-in-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>jQuery change event on checkbox</title>
		<link>http://nelsonwells.net/2010/06/jquery-change-event-on-checkbox/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jquery-change-event-on-checkbox</link>
		<comments>http://nelsonwells.net/2010/06/jquery-change-event-on-checkbox/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 04:54:04 +0000</pubDate>
		<dc:creator>Nelson</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nelsonwells.net/?p=39</guid>
		<description><![CDATA[A lot of times, you&#8217;ll want to call a javascript function when a checkbox is changed from unchecked to check and vice versa. Up until the release of jQuery 1.4, the obvious way to do it (the jQuery .change() event) &#8230;<p class="read-more"><a href="http://nelsonwells.net/2010/06/jquery-change-event-on-checkbox/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>A lot of times, you&#8217;ll want to call a javascript function when a checkbox is changed from unchecked to check and vice versa.  Up until the release of jQuery 1.4, the obvious way to do it (the jQuery .change() event) did not work properly across all versions of Internet Explorer.  Instead, you had to check for the .click() event.  This was an accessibility problem because it did not fire when a user changed a checkbox with the space bar instead of by clicking.  Well, now we can rejoice.  The following code snippet works exactly how you think it would across browsers, including IE.</p>
<p><span id="more-39"></span></p>
<pre>&lt;!-- Load jQuery, and the necessary html --&gt;
&lt;script type='text/javascript src='<a class="linkification-ext" title="Linkification: http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" href="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js">http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js</a>'&gt;&lt;/script&gt;
&lt;input type='checkbox' name='my_checkbox' value='true' checked='checked'&gt;</pre>
<pre>$(document).ready(function(){
    $(":checkbox").change(function(){
        if($(this).attr("checked"))
        {
            //call the function to be fired
            //when your box changes from
            //unchecked to checked
        }
        else
        {
            //call the function to be fired
            //when your box changes from
            //checked to unchecked
        }
    });
});</pre>
]]></content:encoded>
			<wfw:commentRss>http://nelsonwells.net/2010/06/jquery-change-event-on-checkbox/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

