Archive for the ‘Programming’ Category

Calculate Stamp Duty with Excel

Thursday, December 22nd, 2011

A quick post of how to calculate the Stamp Duty of a property with Excel, in my example I am using the Western Australia Residential Rate Dutiable value.

Stamp Duty
Cutoff [$]  Rate [%]  Duty [$]  Formula
0           1.9       0    0
120000      2.85      2280      =C3+(A4-A3)*B3/100
150000      3.8       3135      =C4+(A5-A4)*B4/100
360000      4.75      11115     =C5+(A6-A5)*B5/100
725000      5.15      28452.5   =C6+(A7-A6)*B6/100

Property Value        500000    
Duty                  17765     =VLOOKUP(C9,A:C,3,TRUE) + (C9-VLOOKUP(C9,A:C,1,TRUE))*VLOOKUP(C9,A:C,2,TRUE)/100

Download the Excel WorkBook.

Update, next day
This also works for Individual income tax rates;

Tax Rates
Cutoff [$]  Rate [%] Tax [$]  Formula
0           0        0        0
6000        15       0        =C3+(A4-A3)*B3/100
37000       30       4650     =C4+(A5-A4)*B4/100
80000       37       17550    =C5+(A6-A5)*B5/100
180000      45       54550    =C6+(A7-A6)*B6/100

Income               100000
Tax                  24950    =VLOOKUP(C9,A:C,3,TRUE) + (C9-VLOOKUP(C9,A:C,1,TRUE))*VLOOKUP(C9,A:C,2,TRUE)/100

Related posts:

  1. VBA automatically saves Excel 2003 Workbook in compatibility mode as Excel 2007 Workbook
  2. Bad review – Budget Car Rentals (Doha)

SyntaxHighlighter problems with jQuery 1.7.1

Friday, December 16th, 2011

Recently I upgraded my WordPress plugins to jQuery version 1.7.1 and noticed that Internet Explorer 8 was causing errors “‘null’ is null or not an object”. I isolated this to the SyntaxHighlighter Evolved WordPress plugin I was also uses.

On further Googling it seemed that there were issues with the XRegExp library and jQuery 1.7.1, reported by other uses on IE 6 to 9. Schabse Laks posted a fix to the problem on his blog, though this gave me a new error, so I have modified it slightly, modification on line 271;

RegExp.prototype.exec = function (str) {
	if (typeof(str) !== "string")
		str = String(str);
	var match = real.exec.apply(this, arguments),
		name, r2;

Download the resolved SyntaxHighlighter files here
shCore.max.js
shCore.js

RegexBuddy – a solution to the Regular Expressions (Regex) nightmare

Thursday, December 15th, 2011

For the last few months I have been using RegexBuddy, software designed to help with Regular Expressions.

After using it to create and test more than one extremely complex regular expression, I thought it was time I gave RegexBuddy some ‘big ups’.

So what is so good about RegexBuddy,

Firstly, it allows you to create regular expressions using layman’s terms, “Non printable character”, “Match between zero and unlimited times”, “Create back-reference”, etc, no longer is there a need to remember the regular expression syntax.

Secondly, I can test my regular expression with extreme ease, I can show the full matched text and any matched groupings.

Thirdly, I can directly translate the regular expression to the programming language of choice, VB, PHP, JavaScript, etc, and not have to worry about the specifics of how to form a regular expression for that specific language.

I use RegexBuddy for PHP and JavaScript, I no longer need to ‘guess’ what the regular expression will be and constantly have to upload my code to the server to try it out.

Here’s an example expression I recently used in my WordPress plugin Slimbox2 Slideshow;

Related posts:

  1. Convert Relative Links to Absolute Links with PHP Regex
  2. Online RSVP form and database with PHP, JavaScript and MySQL

MATLAB Scaled Image Normalized Cross-Correlation

Friday, November 11th, 2011

A few week’s ago I got reacquainted with an old friend MATLAB, to solve a computer image manipulation problem.

When I blog about my travels I liked to Geocode my photos and reference them on a Google Map with a marker (see here), on the photo thumbnail I had previously stamped a circle marker on the lower right corner referencing the Google Map marker (the examples below will explain it better). I decided to move away from this approach and dynamically add these circle markers with a CSS and JavaScript solution, as this was a lot cleaner.

The problem, how do I remove the circle markers from my thumbnails, without having to re-crop every single one of my photos. It is fine for landscape photos, all image programs could batch resize the thumbnail from the full size photo, but what about portrait photos, each thumbnail was a cropping of the full size photo. I could assume either the top, vertical centre or bottom of the photo, but that would most likely be different to the original thumbnail and may miss the detail of the full size photo.

The solution was Normalized Cross Correlation, MATLAB already had an example that worked well if the cropped image had not been resized, but I needed something that would allow for resized thumbnails.

My crude solution, loops from smallest to largest sized cropped thumbnails and records the maximum peak of the normalized cross correlation, the maximum would then correspond to the correct scaled image size. This worked well, though the only issue was speed, I managed to optimise the speed by stepping the size in 6 pixel intervals, I also decrease the size of the full sized photo to shorten the number of iterations.

I have called the function cropxcorr, input Template takes in the thumbnail image, input A takes in the full size image, returns C a cropped image mirroring the thumbnail image.

There is also a MATLAB script I ran to loop through the files, portrait images will be passed with cropxcorr, landscape images simply resized.

You can download the MATLAB code and see the examples below.

cropxcorr.m

image-loop.m

Example 1
Thumbnail with marker
Example 1 thumbnail with marker
Original full sized image
Example 1 original full sized image
Generated thumbnail with no marker
Example 1 thumbnail with no marker
Example 2
Thumbnail with marker
Example 2 thumbnail with marker
Original full sized image
Example 2 original full sized image
Generated thumbnail with no marker
Example 2 thumbnail with no marker
Example 3
Thumbnail with marker
Example 3 thumbnail with marker
Original full sized image
Example 3 original full sized image
Generated thumbnail with no marker
Example 3 thumbnail with no marker

Related posts:

  1. Slimbox2 Lightbox clone with automatic image resizing
  2. Slimbox2 Slideshow – WordPress plugin to add image lightbox and slideshow

Convert from Google KML to GPS Exchange Format GPX with PHP

Thursday, October 27th, 2011

Here is a quick post on converting from KML files used in Google Earth/Maps to GPX Exchange Format (GPX) with PHP.

Code is quite explanatory, change $u with the location of the KML file, code will output GPX XML.

Alternatively, download the code here.

<?php
	//enter location of KML file here
	$u = "http://code.google.com/apis/kml/documentation/KML_Samples.kml";

	function utcdate() {
		return gmdate("Y-m-d\Th:i:s\Z");
	}

	$u_parts = pathinfo($u); //array of url parts
	$u_ext = strtoupper($u_parts['extension']);
	if ($u_ext== "KML") {

		$dom_kml = new DOMDocument();
		$dom_kml->load($u);

		$dom_gpx = new DOMDocument('1.0', 'UTF-8');
		$dom_gpx->formatOutput = true;

		//root node
		$gpx = $dom_gpx->createElement('gpx');
		$gpx = $dom_gpx->appendChild($gpx);

		$gpx_version = $dom_gpx->createAttribute('version');
		$gpx->appendChild($gpx_version);
		$gpx_version_text = $dom_gpx->createTextNode('1.0');
		$gpx_version->appendChild($gpx_version_text);

		$gpx_creator = $dom_gpx->createAttribute('creator');
		$gpx->appendChild($gpx_creator);
		$gpx_creator_text = $dom_gpx->createTextNode('http://thydzik.com');
		$gpx_creator->appendChild($gpx_creator_text);

		$gpx_xmlns_xsi = $dom_gpx->createAttribute('xmlns:xsi');
		$gpx->appendChild($gpx_xmlns_xsi);
		$gpx_xmlns_xsi_text = $dom_gpx->createTextNode('http://www.w3.org/2001/XMLSchema-instance');
		$gpx_xmlns_xsi->appendChild($gpx_xmlns_xsi_text);

		$gpx_xmlns = $dom_gpx->createAttribute('xmlns');
		$gpx->appendChild($gpx_xmlns);
		$gpx_xmlns_text = $dom_gpx->createTextNode('http://www.topografix.com/GPX/1/0');
		$gpx_xmlns->appendChild($gpx_xmlns_text);

		$gpx_xsi_schemaLocation = $dom_gpx->createAttribute('xsi:schemaLocation');
		$gpx->appendChild($gpx_xsi_schemaLocation);
		$gpx_xsi_schemaLocation_text = $dom_gpx->createTextNode('http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd');
		$gpx_xsi_schemaLocation->appendChild($gpx_xsi_schemaLocation_text);

		$gpx_url = $dom_gpx->createElement('url');
		$gpx_url = $gpx->appendChild($gpx_url);
		$gpx_url_text = $dom_gpx->createTextNode($u_parts['dirname']);
		$gpx_url->appendChild($gpx_url_text);

		$gpx_time = $dom_gpx->createElement('time');
		$gpx_time = $gpx->appendChild($gpx_time);
		$gpx_time_text = $dom_gpx->createTextNode(utcdate());
		$gpx_time->appendChild($gpx_time_text);

		// placemarks
		$names = array();
		foreach ($dom_kml->getElementsByTagName('Placemark') as $placemark) {
			//name
			foreach ($placemark->getElementsByTagName('name') as $name) {
				$name  = $name->nodeValue;
				//check if the key exists
				if (array_key_exists($name, $names)) {
					//increment the value
					++$names[$name];
					$name = $name." ({$names[$name]})";
				} else {
					$names[$name] = 0;
				}
			}
			//description
			foreach ($placemark->getElementsByTagName('description') as $description) {
				$description  = $description->nodeValue;
			}
			foreach ($placemark->getElementsByTagName('Point') as $point) {
				foreach ($point->getElementsByTagName('coordinates') as $coordinates) {
					//add the marker
					$coordinate = $coordinates->nodeValue;
					$coordinate = str_replace(" ", "", $coordinate);//trim white space
					$latlng = explode(",", $coordinate);

					if (($lat = $latlng[1]) && ($lng = $latlng[0])) {
						$gpx_wpt = $dom_gpx->createElement('wpt');
						$gpx_wpt = $gpx->appendChild($gpx_wpt);

						$gpx_wpt_lat = $dom_gpx->createAttribute('lat');
						$gpx_wpt->appendChild($gpx_wpt_lat);
						$gpx_wpt_lat_text = $dom_gpx->createTextNode($lat);
						$gpx_wpt_lat->appendChild($gpx_wpt_lat_text);

						$gpx_wpt_lon = $dom_gpx->createAttribute('lon');
						$gpx_wpt->appendChild($gpx_wpt_lon);
						$gpx_wpt_lon_text = $dom_gpx->createTextNode($lng);
						$gpx_wpt_lon->appendChild($gpx_wpt_lon_text);

						$gpx_time = $dom_gpx->createElement('time');
						$gpx_time = $gpx_wpt->appendChild($gpx_time);
						$gpx_time_text = $dom_gpx->createTextNode(utcdate());
						$gpx_time->appendChild($gpx_time_text);

						$gpx_name = $dom_gpx->createElement('name');
						$gpx_name = $gpx_wpt->appendChild($gpx_name);
						$gpx_name_text = $dom_gpx->createTextNode($name);
						$gpx_name->appendChild($gpx_name_text);

						$gpx_desc = $dom_gpx->createElement('desc');
						$gpx_desc = $gpx_wpt->appendChild($gpx_desc);
						$gpx_desc_text = $dom_gpx->createTextNode($description);
						$gpx_desc->appendChild($gpx_desc_text);

						//$gpx_url = $dom_gpx->createElement('url');
						//$gpx_url = $gpx_wpt->appendChild($gpx_url);
						//$gpx_url_text = $dom_gpx->createTextNode($ref);
						//$gpx_url->appendChild($gpx_url_text);

						$gpx_sym = $dom_gpx->createElement('sym');
						$gpx_sym = $gpx_wpt->appendChild($gpx_sym);
						$gpx_sym_text = $dom_gpx->createTextNode('Waypoint');
						$gpx_sym->appendChild($gpx_sym_text);
					}
				}
			}
			foreach ($placemark->getElementsByTagName('LineString') as $lineString) {
				foreach ($lineString->getElementsByTagName('coordinates') as $coordinates) {
					//add the new track
					$gpx_trk = $dom_gpx->createElement('trk');
					$gpx_trk = $gpx->appendChild($gpx_trk);

					$gpx_name = $dom_gpx->createElement('name');
					$gpx_name = $gpx_trk->appendChild($gpx_name);
					$gpx_name_text = $dom_gpx->createTextNode($name);
					$gpx_name->appendChild($gpx_name_text);

					$gpx_trkseg = $dom_gpx->createElement('trkseg');
					$gpx_trkseg = $gpx_trk->appendChild($gpx_trkseg);

					$coordinates = $coordinates->nodeValue;
					$coordinates = preg_split("/[\s\r\n]+/", $coordinates); //split the coords by new line
					foreach ($coordinates as $coordinate) {
						$latlng = explode(",", $coordinate);

						if (($lat = $latlng[1]) && ($lng = $latlng[0])) {
							$gpx_trkpt = $dom_gpx->createElement('trkpt');
							$gpx_trkpt = $gpx_trkseg->appendChild($gpx_trkpt);

							$gpx_trkpt_lat = $dom_gpx->createAttribute('lat');
							$gpx_trkpt->appendChild($gpx_trkpt_lat);
							$gpx_trkpt_lat_text = $dom_gpx->createTextNode($lat);
							$gpx_trkpt_lat->appendChild($gpx_trkpt_lat_text);

							$gpx_trkpt_lon = $dom_gpx->createAttribute('lon');
							$gpx_trkpt->appendChild($gpx_trkpt_lon);
							$gpx_trkpt_lon_text = $dom_gpx->createTextNode($lng);
							$gpx_trkpt_lon->appendChild($gpx_trkpt_lon_text);

							$gpx_time = $dom_gpx->createElement('time');
							$gpx_time = $gpx_trkpt->appendChild($gpx_time);
							$gpx_time_text = $dom_gpx->createTextNode(utcdate());
							$gpx_time->appendChild($gpx_time_text);
						}
					}
				}
			}
		}
		header("Content-Type: text/xml");
		echo $dom_gpx->saveXML();
	}
?>

Let me know if you find any issues.

Related posts:

  1. thydzik Google Map v2.0 released – rewritten code supporting API v3 and gpx downloads!
  2. Convert Relative Links to Absolute Links with PHP Regex
  3. VB6/VBA functions to convert binary string to Base64 string

Convert Relative Links to Absolute Links with PHP Regex

Sunday, October 23rd, 2011

Here is a quick post on how to find and replace relative links with absolute links using PHP Regular Expressions (regex).

$url = "http://myabsoluteurl.com/";
$ret = preg_replace('/((?:href|src) *= *[\'"](?!(http|ftp)))/i', "$1$url", $ret);

Related posts:

  1. PHP Factorial and Combination functions
  2. RSS feed aggregator/combiner in PHP with Magpie RSS (v2)
  3. Dynamic Google Maps circle markers/icons with PHP

Slimbox2 Lightbox clone with automatic image resizing

Saturday, October 15th, 2011

I recently moved from Lightbox 2 to Slimbox2, whilst it is a little outdated, Slimbox2 offers many advantages;

  • jQuery language – no need for Prototype/Scriptaculous
  • page doesn’t need to be loaded completely before being run
  • has its own API

Unfortunately, it is missing automatic image resizing, which I love.

With the help of Example 9 on Neil’s Slimbox Examples, I have managed to hack together this feature which I am happy about.

Modified Slimbox2 with auto resize JavaScript
Modified Slimbox2 with auto resize CSS

Example in the below Image Map;

Test Images

1024x768 768x1024 800x600 600x800 640x480 480x640 320x240 240x320

Related posts:

  1. Photoshop VBScript to automatically resize images

Online RSVP form and database with PHP, JavaScript and MySQL

Friday, September 30th, 2011

Requirements

Recently, I needed an online RSVP system for a reception I was hosting, all the options out there didn’t meet my requirements;

  • Customisable and able to self-host
  • No need for tracking codes/numbers to be sent with invitation
  • Able to RSVP additional guests
  • Able to modify an existing RSVP

Implementation

As usual, I decided to implement my own online RSVP solution, which has the following functionality;
  • PHP/JavaScript front-end
  • MySQL back-end
  • Sleek CSS (borrowed from WordPress)
  • Client-side checking with JavaScript
  • Server-side checking with PHP
  • Very basic submission viewing in HTML, wasn’t a real requirement as I could browse the database with phpMyAdmin, but it was good to have some visibility without the need of logging in

Installation

  • You will need PHP installed and a MySQL database.
  • Import the following SQL query to create a RSVP table with required fields.
  • Create a folder on your web hosting.
  • Extract the following zip file contents to this newly created folder.
  • Edit rsvp.php and configure your database settings, including database name, user name, password and host.
  • If using the optional email confirmation, configure the email from address and email body contents.
  • On your website, create an iframe to show the RSVP form.
Testing
  • Navigate to rsvp.php and submit a test response.
  • Navigate to res.php and confirm you can see your test response.
  • Alternatively, view the MySQL table directly (with phpMyAdmin)
Downloads

Improvements

Two small things I would have added, known after it’s use;

  • Client-side checking for ‘and’ in the full name field, few guests still tried to add themselves and their partner in that field.
  • Improved response email that would be addressed to all guests not just the first name.

Related posts:

  1. Dynamic Google Maps circle markers/icons with PHP
  2. RSS feed aggregator/combiner in PHP
  3. Dynamic Google Maps markers/icons with PHP