CSC/ECE 517 Spring 2015/oss S1504 AAC
About Sahana
Sahana Eden is an Open Source Humanitarian Platform which can be used to provide solutions for Disaster Management, Development, and Environmental Management sectors. Being open source, it is easily customisable, extensible and free. It is supported by the Sahana Software Foundation. Sahana Eden was first developed in Sri Lanka as a response to the Indian Ocean Tsunami in 2005. The code for the Sahana Eden project is hosted at Github and it is published under the MIT License. The demo version of Sahana Eden can be found here.
Eden is a flexible humanitarian platform with a rich feature set which can be rapidly customized to adapt to existing processes and integrate with existing systems to provide effective solutions for critical humanitarian needs management either prior to or during a crisis. Sahana Eden contains a number of different modules like 'Organization Registry', 'Project Tracking', 'Human Resources', 'Inventory', 'Assets', 'Assessments', 'Scenarios & Events', 'Mapping', 'Messaging' which can be configured to provide a wide range of functionality. We are contributing to Sahana Eden as a part of our Object-Oriented Design and Development's Open-Source Software (OSS) Project. In this Wiki Page, we would be explaining the goals of our project and how we implemented them.
Goals of the project
Implementation
Searching Internal database
#Get vars from url user_str = get_vars["name_startsWith"] callback_func = request.vars["callback"] atable = db.gis_location query = atable.name.lower().like(user_str + '%') rows = db(query).select(atable.id, atable.level, atable.name, atable.lat, atable.lon ) results = [] count = 0 for row in rows: count += 1 result = {} #Convert the level colum into the ADM codes geonames returns #fcode = row["gis_location.level"] level = row["gis_location.level"] if level=="L0": #Country fcode = "PCL" #Zoom 5 elif level=="L1": #State/Province fcode = "ADM1" elif level=="L2": #County/District fcode = "ADM2" elif level=="L3": #Village/Suburb fcode = "ADM3" else: #City/Town/Village fcode = "ADM4" result = {"id" : row["gis_location.id"], "fcode" : fcode, "name" : row["gis_location.name"], "lat" : row["gis_location.lat"], "lng" : row["gis_location.lon"]} results.append(result)
Searching geonames
If the initial search for the user query on the internal 'Locations' table, then a search is done on Geonames as a fallback. This fallback search is implemented within the 'gis' controller using 'urllib2' an extensible Python module for opening URLs. The base URL for the Geonames search is http://ws.geonames.org/searchJSON?. The searchJSON action expects the Geonames username, the prefix of the location names to be searched, number of rows in the JSON result, etc. as parameters. The following code performs the HTTP GET request and loads the JSON response in a dictionary.
username = settings.get_gis_geonames_username() maxrows = "20" lang = "en" charset = "UTF8" nameStartsWith = user_str geonames_base_url = "http://ws.geonames.org/searchJSON?" url = "%susername=%s&maxRows=%s&lang=%s&charset=%s&name_startsWith=%s" % (geonames_base_url,username,maxrows,lang,charset,nameStartsWith) response = urllib2.urlopen(url) dictResponse = json.loads(response.read().decode(response.info().getparam('charset') or 'utf-8')) response.close()
The JSON object in the response has two keys 'totalResultsCount' and 'geonames'. The object corresponding to the 'geonames' key is an array of the Geonames search results, each of which is a dictionary in itself. Of all the Keys present in a single result dictionary, the relevant ones are 'id', 'fcode', 'name', 'lat' and 'lng'. The relevant keys are extracted and a new dictionary is created for each search result. The array of new dictionaries is then returned as a response. The following code performs the decoding of the JSON object, creating new dictionary objects with the relevant keys and then collecting them as a single array.
results = [] if dictResponse["totalResultsCount"] != 0: geonamesResults = dictResponse["geonames"] for geonamesResult in geonamesResults: result = {} result = {"id" : int(geonamesResult["geonameId"]), "fcode" : str(geonamesResult["fcode"]), "name" : str(geonamesResult["name"]),"lat" : float(geonamesResult["lat"]), "lng" : float(geonamesResult["lng"])} results.append(result)