I realized I didn’t actually include any implementation details when writing my sleepy post about stable locations and temperature the other night. I figured I’d elaborate on that now.

Having never used HTML5 geolocation features before, I kind of winged it and hacked together something that works for now. Currently I get the user’s location in two cases - on registration, and when searching for wild snails.

Here is how it happens on the registration page:


    <script>
        getLocation();
        function getLocation() {
            console.log('getLocation here');
            if (Modernizr.geolocation) {
                console.log('geolocation in');
                navigator.geolocation.getCurrentPosition(createHiddenInput, geolocationError);
            } else {
                console.log('no native support');
            }
        }

        function createHiddenInput(position) {
            var latitude = position.coords.latitude;
            var longitude = position.coords.longitude;
            console.log('latitude: ' + latitude);
            console.log('longitude: ' + longitude);

            jQuery(document).ready(function() {
                $('#registrationForm').append('<input type="hidden" name="stableLatitude" value=' + latitude + '/>');
                $('#registrationForm').append('<input type="hidden" name="stableLongitude" value=' + longitude +'/>');
                $('#registrationForm').append('Stable Location: ' + getCityName(latitude, longitude) + ',' + getCountryName(latitude, longitude));

            });
        }
    </script>

{:lang=“javascript”}

Problem - retrieving the location takes a few seconds. If the user happens to register too quickly their location will not be retrieved. As a potential solution I am considering disabling the Submit button until the location is ready…however, what if they don’t want to allow me to retrieve their location at all?

If the user does not let me retrieve their location, it will be set by default to some place in Louisiana. Maybe then I can just display a “Don’t want to be in Louisiana? Wait while we get your location!” message…

So the latitude and longitude is stored for the user’s new account. Then to get the country and city name when displaying where the user is we use the Geonames API. Example:

public static function GetCityName($latitude, $longitude) {
    $cityName = null;
    if (Utility::InternetOn()) {
        $url = "http://api.geonames.org/findNearbyPlaceName?lat=" . $latitude . "&lng=" . $longitude . "&username=myusername";
        Log::info ('connection');
        $xmlDoc = new \DOMDocument();
        $xmlDoc->load($url);
        $cityNameNode = $xmlDoc->getElementsByTagName("name");
        $cityName = null;
        if ($cityNameNode->length > 0) {
            $cityName = $cityNameNode->item(0)->nodeValue;
        }
    }

    return $cityName;
}

{:lang=“php”}

To get temperature I originally tried OpenWeatherMap but that seems very slow and unreliable. So I am trying out The Dark Sky:

public static function GetCurrentTemperature($latitude, $longitude) {
    $url = "https://api.forecast.io/forecast/MYAPIKEY/" . $latitude . "," . $longitude;

    $JSON = file_get_contents($url);
    $data = json_decode($JSON);

    $f = $data->currently->temperature;
    $c = Utility::FahrenheitToCelsius($f);

    return $c;
}

{:lang=“php”}

The Dark Sky gives me 1000 free API calls per day. I blew through that in under an hour because I was stupid and calling the API each time I needed to get the temperature. Which is a lot…passive events alone blow through about 200 calls in 5 minutes.

So I added a currentTemp field in the User table and a temp_updated_at field. I added a recurring event to update the temperature once per hour.

Now it is time to start varying wild snail traits based on location you are looking in. I might even embed a Google Map on the wild-snail-collection page so that instead of just clicking “Look under a rock” or whatever you can click on a spot in your general vicinity on a map and see what snail pops up there!