Kyle Boddy Entrepreneur, Hacker, Biomechanics Researcher, Baseball Lover.

26Apr/112

Mass Geolocation Script (PHP)

I recently wrote a mass geolocation script in PHP since Google seems to be taking down all the websites that offer this vital service. Right now it:

  • Checks a table for records without lat/long coordinates
  • Sends those records' addresses to Google's geolocation API
  • Updates your records with the lat/long coordinates

It checks for the "#" sign and handles it since Google has problems with translating "2020 Anywhere Place #200" as a real address, but there are probably other errors I haven't adequately checked for.

At the moment it updates records that are missing lat/long coordinates and writes zeroes into those fields if it can't geolocate the address correctly. As a result, if you run the script again, it will assume those records were updated correctly and will pass over them, since they are not null. This is a known issue and is one (of many) areas of improvement for the script.

I didn't want to spend a ton of hours on the script to make it a full-fledged awesome service, since Google doesn't seem to like that. It's just a basic script that handles common problems and works well enough.

You can get it over at my GitHub repo page for GeoCode. Enjoy.

1Apr/118

Minor League Splits Redux Launched

I've launched yet another half-complete web application relating to baseball sabermetrics! ML Splits is a database of minor league baseball players (batters only for now) that shows their "splits" (performance against LHP and RHP) as well as park effects and major league equivalencies. The data is taken from Jeff Sackmann's old minorleaguesplits.com site where he made the CSVs available for import as open source.

ML Splits

ML Splits

I leaned on jQuery for front-end display purposes, as I'm getting more and more comfortable with using it for front-facing web applications. Mostly just dynamic div tagging and toggle() to keep the screen clear of distractions and make it easy to see what stats are really important. Wrote the entire thing in PHP 5.3.x, MySQL 5, CodeIgniter 2.0, and jQuery.

Enjoy!

EDIT: Pitchers are up as of April 4th.

15Feb/110

Creating Batch Users in TankAuth (CodeIgniter)

As detailed in this Stack Overflow request, I had the need to convert an existing database of users/passwords (stored in plaintext) to our new authentication library driven by CI and TankAuth. User jondavidjohn got me on the right track, and here's the code I ended up writing to submit to Stack Overflow for sample use:

function batchReg()
	{
		$this->load->model('mymodel');

		// connect to the database
		$this->mymodel->dbconnect();

		// build it
		$query = "SELECT user, email, pass from newusers ORDER BY user ASC";

		// ship it
		$result = mysql_query($query);

		// loop it
		while ($row = mysql_fetch_array($result))
		{
			$data = $this->tank_auth->create_user($row['user'], $row['email'], $row['pass'], FALSE);
			print_r($data);
			echo "<p>";
		}

	}

Enjoy!

17Jan/110

array_walk() in CodeIgniter

Recently I needed to call trim() for multiple variables in an array in my CodeIgniter application, but had issues with calling the custom function using array_walk() to do so. A bit of Googling and experimentation led me to this answer:

function stuff()
    {
	    // trim array data
	    array_walk($data, array($this, 'trim_value'));

	    $this->load->view('preview_view', $data);
	}

	function trim_value(&$value)
	{
	    $value = trim($value);
	}

You have to pass array_walk() or array_walk_recursive() an array with $this as a defined variable/pointer.

Try that piece of code if you're having an issue!

7Nov/100

Merging Two Arrays of Different Size (PHP)

This isn't pretty, but I needed to write code that would merge two arrays of differing sizes. One contained injury information for 1400 players with an overlapping field of elias_id with an array of 900 players of PITCHf/x data. Simply put, I needed to insert two values from the injury array to matching players in the PITCHf/x array.

Here's how I did it with array_search() and preg_replace() - the arrays were in the format of $pitcher['elias_idxxx'] where xxx was the numeric point at which the value was in (so elias_id0 through elias_id899 for the PITCHf/x array and elias_id0 through elias_id1399 for the injury array).

Whether or not the arrays are properly formatted and constructed is not the point of this blog post. (Though it is likely that it is better done through a second recursive array, we're not selling code here. We're selling functionality.)

$x = 0;
$y = 0;
$pattern = '/[^0-9]/';

if (!@$pitcher){
	// do nothing
}
else // parse the array
{
	foreach($pitcher as $blank)
	{
		$key = array_search($pitcher['elias_id' . $x], $injuries);
		if ($key)
			{
				$y = preg_replace($pattern, '', $key);
				$pitcher['timesinjured' . $x] = $injuries['timesinjured' . $y];
				$pitcher['daysmissed' . $x] = $injuries['daysmissed' . $y];
			}
		$x++;
		if (!@$pitcher['elias_id' . $x])
			break;
	}
}
14Oct/100

WordPress Code: Attachment / Category Loop

Wordpress Logo

Wordpress!

Recently while writing some PHP/WordPress code for a client of mine, I ran into an interesting situation. The previous developer had some godawful code that I won't get into right now, but the client wanted to be able to display the following on a static page:

  • Groups of areas where his business did work
  • Blog posts in those groups (testimonials / examples of previous jobs)
  • The first image attached to each blog post as a thumbnail, linking back to the original blog post

I had never done something like this before with WordPress, but it's actually fairly simple, as WP is quite powerful. After finding out that all the images were the same aspect ratio (phew!), I decided on writing a loop that would have only two arrays of hard-coded data. These arrays would: 1) Define the areas that his business did work, and 2) Match the category slugs that WP uses.

My client agreed to post his work to categories that were matched to the groups of areas where his business did work. As such, I defined two arrays with the same number of items in the same order that matched the description and the category slug for each group. This might be better off in a single nested array with multiple key-value pairs, but I think this is a simple solution that scales well and can be modified easily at any time.

Here's the code:

 <?php
 $areas = array(1 => 'Seattle','East Side & Mercer Island','North Side','South Side');
 $slugs = array(1 => 'seattle-jobs','east-side-and-mercer-island-jobs','north-end-jobs','south-end-and-west-seattle-jobs');
 $i = count($areas);
 $n = 1;

 while ($n <= $i)
 {
     global $post;
     $myposts = get_posts('numberposts=-1&offset=0&category_name=' . $slugs[$n]);
     echo '<div id="imageList">';
     echo '<a name="' . $areas[$n] . '"></a><h2>' . $areas[$n] . '</h2>';
     echo '<table id="ourwork"><tr>';
     $x = 1;

     foreach($myposts as $post)
     {
       setup_postdata($post);

        echo '<td>';
        $args = array(
                'post_type' => 'attachment',
                'numberposts' => '-1',
                'post_status' => null,
                'post_parent' => $post->ID
        );
        $attachments = get_posts($args);

        if ($attachments) {
                    $y = count($attachments);
                    $y--;
                    echo '<a href="' . $post->guid . '">';
                    echo wp_get_attachment_image($id = $attachments[$y]->ID, $size=array(200,133), $icon = false);
                    echo '<strong><br><br>';
                    echo apply_filters('the_title', $attachments[$y]->post_title);
                    echo '</strong></a>';
                    echo '</td>';
                    if ($x == 4)
                    {
                        echo '</tr><tr>';
                        $x = 0;
                    }
                    $x++;
                }
     }
    echo '</tr></table>';
    echo '</div><div class="blog"></div>';
    $n++;
  }
?>

As you can see, I defined the arrays to start at 1 for simpler counting.  After that, it prints out the category's name in a header tag, defines a table and anchor (this was tied into another imagemap project), and runs a foreach to get all the posts under the first slug in the $slugs array. In the foreach loop, it finds all posts with at least one attachment to it, counts the number of attachments, and uses the first attachment in the post to print out as an image with the title of it right below it - both linked to the original blog post.

It then increments up to four times per line for formatting purposes, then kicks out and starts a new table row.

For future expansion, all that needs to be done is adding, removing, or changing the paired $areas and $slugs to run together.

Right now the client only has 50-80 entries, so it all fits fine with minor scrolling (plus the aforementioned imagemap from the home page shortcuts you to the correct anchor). However, in the future, it may get unwieldy. Using a Javascript show/hide function will probably be my next project and is simple to implement. It can even be tied in with the anchors from the imagemap by using the $_GET function in PHP to pass that variable along, ensuring that only that category opens up while the rest stay hidden (at no penalty to SEO, I might add).

Pretty fun piece of code. It took me about 5-6 hours to research and put together. Hope it helps you!

Tagged as: , No Comments
27Apr/100

Programming Pride, Volume 1

I wrote a script in PHP/CI that serves a page to show a basic view of company listings derived from another PHP script I wrote that performs ETL logic. Then I scheduled a cron job to ping the initial PHP/CI script using wget. When the initial script's unique controller function is hit by wget, it iterates over the basic list to perform a giant serialized array compilation using many SQL queries to look up revenue information. After that, it fires PHP's mail() command, routing an email through MercuryE's relay logic through a secure smtp gmail connection to the business team that needs this information.

Prior to my awesome scripting, database, and systems analysis skills, the report in question took 90 minutes to manually compile using a SQL interface and Microsoft Excel. I just gave the business analyst back 7.5 hours per week - nearly a full workday - by automating some tasks and understanding the underlying model. It took me about 20 hours to write the scripts and do the research.