Handling school closure RSS feeds

Some background information

Some councils (currently 4 in the UK) manage a school closure RSS feed. This RSS feed is updated when a school is closed, this is great news for sites like my school closures as it enables them to dynamically update parents based on verified information supplied by the council. I have been in contact with a lot of schools state side who also want to begin providing closure information via RSS to third parties.  If you don’t know what an RSS feed is then this article probably isn’t for you.

Why is this important?

Globally recording school closures isn’t everyone’s cup of tea.  But if you think about how powerful it would be to compare school closures against weather/disasters etc. and the ability to then predict closures and other local closures based upon a school closure you begin to have a much bigger understanding of the economic and social impact such a system/standard can have.

The problem at the moment is that there is no framework for this information so working with it is a bit of a nightmare.  Therefore the target audience for this article is whoever is making the feeds for the council.

Remember: Computers are only as accurate as the information that goes into them.  RSS school closures feeds from councils may be a new area to explore but it is an area that will inevitably expand so we should get it right early on.

My work in this area

I write the mechanics for my school closures, providing school closure feeds and notifications for well over 5000 schools worldwide. I also work on the Ushahidi project, working on the social aggregation object which is in place to take information from social networks and assign them to schools based on locations. I am also working on a method of predicting school closures based on weather/notifications and/or and global disasters inc. fire, floods etc.

Suggested framework

I think it’s great councils are providing closure information but we need to address a few things.

1.) Provide documentation – We need either a standard for council closure RSS feeds OR councils needs to provide documentation along side their RSS feed.
2.) Do not create ghost items – Councils that create an RSS feed where the item is “No new items exist” is not cool. If your feed has no items then simply keep your feed empty.
3.) Don’t be vague – Councils need to fill their feed with as much information possible, I don’t expect lat/long but at least the street name.  Just putting the school name in the feed is not enough information, there is often two “St Matthews(replace Matthews with whatever you want) primary school’s” in the same district/council area.  Include in the feed if the school is open or closed and the reason for the closure (if this is the case).
4.) Don’t break your feed – Councils have to keep their RSS feeds working and up to date, this is a no brainer but is ignored on the previously mentioned closure feeds.
5.) Understand copyright law – Don’t put a copyright on public information RSS feeds (sighs).
6.) Use Geo tags on your feed – Consider putting some geo tags into your actual feed header, there are quite a few councils with the same name so a feed named “York Council RSS feed (new)” would get confused with New York, if you include a location tag such as “York, UK” then it will be a lot easier to aggregate this information.
7.) Use Geo tags on your items – Consider putting some geo tags into your items. I appreciate this is a bit of a pain to do but it will help us avoid matching the wrong notification to the wrong school.
8). Use the appropriate ttl on your feed.  Is 5 minutes really how frequently readers need to update this information?
9.) Create unique guids for each information update. Obvious really yet this is being ignored.
10.) Use open/closed in the title. If you use the word open or closed in the title it will save us creating a tag, however we should do that anyway.

An example of a bad feed

<rss version="2.0" xmlns:schools="http://purl.org/dc/elements/1.1/">
<channel>
<title>Barmon Schools - School Closures</title>
<link>https://rss.Barmon.com</link>
<description>This feed provides a list of schools that are closed in the Barmon District https://rss.Barmon.com</description>
<copyright>(c) Barmon Schools</copyright>
<pubDate>Thu, 08 Jul 2010 09:56:11 GMT</pubDate>
<ttl>5</ttl>
<item>
<title>- No Schools Closed Today -</title>
<description>- No Schools Closed Today -</description>
<link>https://rss.Barmon.com/Schools/SchoolClosure_Index.aspx</link>
<pubDate>Thu, 15 Jul 2010 17:20:16 GMT</pubDate>
<guid>https://rss.Barmon.com/Schools/SchoolClosure_Index.aspx</guid>
</item>
</channel>
</rss>

An example of a good feed

<rss version="2.0">
<channel>
<title>Barmon Schools - School Closures</title>
<link>https://rss.Barmon.com</link>
<description>This feed provides a list of schools that are closed in the Barmon District https://rss.Barmon.com</description>
<pubDate>Thu, 08 Jul 2010 09:56:11 GMT</pubDate>
<ttl>600</ttl>
<item>
<title>Moleswood Primary School is closed due to a fire</title>
<description>A fire swept through Moleswood Primary School, BA1 2AM.  The school is closed for an unspecified period</description>
<link>https://rss.Barmon.com/Schools/SchoolClosure_Index.aspx?school=1&view=rss</link>
<pubDate>Thu, 15 Jul 2010 17:20:16 GMT</pubDate>
<guid>82291559asdh22184</guid>
<geo:lat>53.795740</geo:lat>
<geo:lon>-1.758306</geo:lon>
<schoolinfo:name>Moleswood Primary School</schoolinfo:name>
<schoolinfo:type>closed</schoolinfo:type>
<schoolinfo:reason>Fire</schoolinfo:reason>
</item>
</channel>
</rss>

Why this standard is better than the current mechanism

We basically chose to extend the RSS schema to include some school specific info. Surprisingly to some people is why we didn’t include something such as the UPN or “code” of the school. This is because the scope of this standard is global and most countries have their own coding structure.

We chose name for obvious reasons.  The schoolinfo:type allows different values such as closed, open, halfday, holiday etc. so can be extended reasonably well and the reason is simply complimentary for these values.

Why is Latitude and Longitude SO important?  Quite a few reasons, firstly is mapping, it is much easier to map based on lat and lon.  Second is conflicting school names and thirdly is very close by schools.  Lat and Lon of a location allows accurate location based results and also allows us to update records in case a school moves.

I can guarantee that councils will eventually adopt either this standard or a standard similar to this, be it through a smart management decision or through consumer demands.  A standard like this allows for much smarter closure announcements and future proofing of the quality of service delivered by educational institutions.

Ushahidi post tweets to API php example

The below code takes an rss search result from twitter, detects the authors location then posts the information to Ushahidi via the API.

Application I used it inMy School Closures for detecting people who tweet about school closures.  Unfortunately I have to use pipes for the location builder which isn’t elegant as Yahoo Pipes sucks and I wish I never started playing with it.  Feel free to play with the pipe I created to get geo location information from a location name, it is the pipe that has the json_decode.

You will need mysql and a table for the guids (this stops us from spamming twitter for authors we have already located). Make sure you change the configuration settings and create a table in mysql.

The method is simple, the code isn’t pretty and will require polishing but here it is:

<pre>
<?php
//CONFIGURE THE SETTINGS BELOW
//twitter settings
$twitterusername = "mytwitteraccount";
$twitterpassword = "apasswordgoeshere";

//database settings
$host = "databasehostname";
$user = "databaseusername";
$pass = "databasepassword";
$dbname = 'databasename';

// You should create a table called tweetguids in your database
$tablename = "tweetguids";

// Change the below feed to a rss feed similar to below
$rssurl = "http://pipes.yahoo.com/pipes/pipe.run?_id=a9663ebc09e69b9195fb2407fba9f2bc&_render=rss";

// END OF CONFIG

$conn = mysql_connect($host, $user, $pass) or die                      ('Error connecting to mysql');
mysql_select_db($dbname);

ini_set('display_errors', 1);
ini_set('log_errors', 1);
ini_set('error_log', dirname(__FILE__) . '/error_log.txt');
error_reporting(E_ALL);

$rss = simplexml_load_file($rssurl) or die("failure");
$count = 0;
foreach ($rss->channel as $chan)
{
$time = $chan->pubDate;
}
foreach ($rss->channel as $chan){$time = $chan->pubDate;}
foreach ($rss->channel->item as $item)
        {
        // only do first 10 records
        if ($count < 10)
                {
                $foundguid=0;
                $guidnew=$item->guid;
                // Check to see if guid exists in db already
                $sql="SELECT * FROM $tablename where guid = \"$guidnew\"";
                $result=mysql_query($sql, $conn);
                while ($row=mysql_fetch_array($result))
                        {
                        $foundguid=1;
                        echo "Foundguid: $foundguid";
                        }
                if($foundguid==1)
                        {
                        echo "We found an alredy existing guid...";
                        }
else
                        {
                        $count = $count + 1;
                        $task="report";
                        $incident_title=$item->title;
                        $guidnew=$item->guid;
                        $incident_title=str_replace(" ","+",$incident_title);
                        $incident_description=$item->description;
                        $incident_description=str_replace(" ","+",$incident_description);
                        $incident_date=date("m/d/Y",$time);
                        $incident_hour=date("H",$time);
                        $incident_minute=date("i",$time);
                        $incident_ampm=date("a",$time);
                        $incident_category="Possible Closure";
                        $location_name="Unknown";
                        $author = $item->author;
                        $author = str_replace(" ","+",$author);
                        $pos = strpos($author,"+");
                        //$author = substr($author,0,$pos);
                        $author = str_ireplace("http://twitter.com/","",$author);
                        $url = "http://$twitterusername:$twitterpassword@api.twitter.com/1/users/lookup.xml?screen_name=$author";
                        //echo $url;
                        $output = simplexml_load_file($url) or die("badauth");
                        foreach ($output->user as $item)
                                {
                                // Get the values out of the XML
                                $location=$item->location;
                                // Clean up the location
                                $location=str_ireplace("-",",",$location);
                                $location=str_ireplace(" ",",",$location);
//                              $location=preg_replace("/[^a-zA-Z0-9\s]/", "", $location);
                                echo "<br/><b>Location content: $location<br/>";
                                // Pass the location to yahoo pipe
                                $location = str_ireplace(" ","",$location);
                                //echo "<br/>Loc: $location";
                                $locationurl = "http://pipes.yahoo.com/pipes/pipe.run?_id=03539616e4cdd62eb15ed26b81e3041e&_render=json&q=$location";

                                 $ch = curl_init();
                                curl_setopt($ch, CURLOPT_URL, $locationurl);
                                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

                                //make the request
                                $json = curl_exec($ch);
                                $arr = (json_decode($json,true));
                                $blah = $arr['value']['items'][0]['name']['loc'];
                                //print_r($blah);
                                $latitude = $blah['lat'];
                                $longitude = $blah['lon'];
                                $location_name = $blah['city'];
                        }

                        $incident_description="Closure reported from twitter";
                        $url = "task=report&incident_title=$incident_title&incident_description=$incident_description&incident_date=$incident_date&incident_hour=$incident_hour&incident_minute=$incident_minu$
                        $posturl = "http://myschoolclosures.com/ushahidi/api";
                        $Curl_Session = curl_init($posturl);
                         curl_setopt ($Curl_Session, CURLOPT_POST, 1);
                         curl_setopt ($Curl_Session, CURLOPT_POSTFIELDS,
                        $url);
                        curl_setopt ($Curl_Session, CURLOPT_FOLLOWLOCATION, 1);
                        curl_exec ($Curl_Session);
                        curl_close ($Curl_Session);
                        //Write to the database
                        $sqlgo="INSERT INTO $tablename VALUES (\"$guidnew\")";
                        $result=mysql_query($sqlgo, $conn);
                }
        }
        //Write anything else to DB just in case anything trails behind
        $sql="INSERT INTO $tablename VALUES (\"$guidnew\")";
        $result=mysql_query($sql, $conn);
        $row=mysql_fetch_array($result);
        //echo "<br/>$sql<br/>";
}
?>

My school closures needs you!

Since the WHO announced that school closures may stop the spread of swine flu a lot of parents, teachers and schools have been registering on My School Closures.

As My school closures is a completely free service we need volunteers to help us monitor all the school closure requests and also help spread the word so no school misses out!
For those who aren’t aware what my school closures is then basically it is a website where schools, parents and teachers can register their email address and mobile(sms) number and recieve free emails and sms notifications if their school is closed.
Learning authorities and district’s worldwide have adopted this open source method to this problem as it is easily embedded into a website or learning platform meaning that parents do not need to visit the my school closures website to recieve the information they need or to subscribe to the service.
Please get in touch if you think you can bring something to our team!