--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/export_kml.py Tue Sep 22 13:15:33 2009 +0200
@@ -0,0 +1,743 @@
+#!/usr/bin/python2.5
+#
+# Copyright 2009 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""The script which generates KML file for Google Summer of Code 2009 program.
+"""
+
+__authors__ = [
+ '"Daniel Hans" <daniel.m.hans@gmail.com>',
+]
+
+
+import sys
+import codecs
+import interactive
+
+
+from xml.dom.minidom import Document
+
+
+def _getMentoredProjects(mentor):
+ """Returns a list of projects which are mentored by a given mentor.
+ """
+
+ from soc.logic.models.student_project import logic as project_logic
+
+ filter = {
+ 'mentor': mentor
+ }
+
+ return project_logic.getForFields(filter=filter)
+
+
+def _getAcceptedOrgs():
+ """Returns a list of organizations which got accepted.
+ """
+
+ from soc.logic.models.organization import logic as org_logic
+
+ filter = {
+ 'status': 'active'
+ }
+
+ entities = org_logic.getForFields(filter=filter)
+
+ filter = {
+ 'status': 'new'
+ }
+
+ entities += org_logic.getForFields(filter=filter)
+
+ return entities
+
+
+def _getStudentProject(entity):
+ """Returns a project for a given student.
+ """
+
+ from soc.logic.models.student_project import logic as project_logic
+
+ filter = {
+ 'student': entity,
+ 'status': 'accepted',
+ }
+
+ return project_logic.getForFields(filter=filter, unique=True)
+
+
+def _getAllUsers():
+ """Returns a list of all valid users.
+ """
+
+ from soc.models.user import User
+
+ gen = lambda: User.all().filter('status =', 'valid')
+ return interactive.deepFetch(gen)
+
+
+def _getAllOrgAdmins():
+ """Returns a generator of all active mentors.
+ """
+
+ from soc.models.org_admin import OrgAdmin
+
+ gen = lambda: OrgAdmin.all().filter('status = ', 'active')
+ return interactive.deepFetch(gen)
+
+
+def _getAllMentors():
+ """Returns a generator of all active mentors.
+ """
+
+ from soc.models.mentor import Mentor
+
+ gen = lambda: Mentor.all().filter('status = ', 'active')
+ return interactive.deepFetch(gen)
+
+
+def _getAllStudents():
+ """Returns a generator of all active students.
+ """
+
+ from soc.models.student import Student
+
+ gen = lambda: Student.all().filter('status = ', 'active')
+ return interactive.deepFetch(gen)
+
+
+def _getPersonStyle(doc, type):
+ """Returns <Style> element for a particular person.
+ """
+
+ if type == 'org_admin':
+ x_text, y_text = '0', '0'
+ elif type == 'mentor':
+ x_text, y_text = '128', '96'
+ elif type == 'student':
+ x_text, y_text = '64', '160'
+
+ style = doc.createElement('Style')
+
+ icon_style = doc.createElement('IconStyle')
+ style.appendChild(icon_style)
+
+ icon = doc.createElement('Icon')
+ icon_style.appendChild(icon)
+
+ href = doc.createElement('href')
+ icon.appendChild(href)
+
+ text = doc.createTextNode('root://icons/palette-5.png')
+ href.appendChild(text)
+
+ x = doc.createElement('x')
+ icon.appendChild(x)
+
+ text = doc.createTextNode(x_text)
+ x.appendChild(text)
+
+ y = doc.createElement('y')
+ icon.appendChild(y)
+
+ text = doc.createTextNode(y_text)
+ y.appendChild(text)
+
+ w = doc.createElement('w')
+ icon.appendChild(w)
+
+ text = doc.createTextNode('32')
+ w.appendChild(text)
+
+ h = doc.createElement('h')
+ icon.appendChild(h)
+
+ text = doc.createTextNode('32')
+ h.appendChild(text)
+
+ return style
+
+
+def _getLineStringStyle(doc):
+ """Returns <Style> element for a line string placemark.
+ """
+
+ style = doc.createElement('Style')
+
+ line_style = doc.createElement('LineStyle')
+ style.appendChild(line_style)
+
+ color = doc.createElement('color')
+ line_style.appendChild(color)
+
+ text = doc.createTextNode('ff00ff00')
+ color.appendChild(text)
+
+ width = doc.createElement('width')
+ line_style.appendChild(width)
+
+ text = doc.createTextNode('1')
+ width.appendChild(text)
+
+ return style
+
+
+def _getDescriptionForStudent(doc, student, project):
+ """Returns <description> element for a given student.
+ """
+
+ description = doc.createElement('description')
+
+ text = doc.createTextNode('Working on...')
+ description.appendChild(text)
+
+ description.appendChild(doc.createElement('br'))
+
+ i = doc.createElement('i')
+ description.appendChild(i)
+
+ title = doc.createTextNode(project.title)
+ i.appendChild(title)
+ description.appendChild(doc.createElement('br'))
+
+ mentor = doc.createTextNode(
+ 'mentored by ' + _getName(project.mentor))
+ description.appendChild(mentor)
+ description.appendChild(doc.createElement('br'))
+
+ org = doc.createTextNode(project.scope.name)
+ description.appendChild(org)
+ description.appendChild(doc.createElement('br'))
+ description.appendChild(doc.createElement('br'))
+
+ description = _appendHomePageAndBlogContent(doc, description, student)
+
+ description = _appendStateAndCountryContnent(doc, description, student)
+
+ return description
+
+
+def _appendStateAndCountryContnent(doc, description, state, country):
+ """Appends state and country info to the description of a placemark.
+ """
+
+ if state:
+ description.appendChild(doc.createTextNode(state + ', '))
+
+ description.appendChild(doc.createTextNode(country))
+
+ return description
+
+
+def _appendHomePageAndBlogContent(doc, description, home_pages, blogs):
+ """Appends home page and blog info to the description of a placemark.
+ """
+
+ if home_pages:
+ text = doc.createTextNode('Home page:')
+ description.appendChild(text)
+ description.appendChild(doc.createElement('br'))
+
+ for home_page in home_pages:
+ description.appendChild(doc.createTextNode(home_page))
+ description.appendChild(doc.createElement('br'))
+
+ if home_pages:
+ description.appendChild(doc.createElement('br'))
+
+ if blogs:
+ text = doc.createTextNode('Blog:')
+ description.appendChild(text)
+ description.appendChild(doc.createElement('br'))
+
+ for blog in blogs:
+ description.appendChild(doc.createTextNode(blog))
+ description.appendChild(doc.createElement('br'))
+
+ if blogs:
+ description.appendChild(doc.createElement('br'))
+
+ return description
+
+
+def _getName(entity):
+ """For a given entity returns a name to be displayed.
+ """
+
+ return entity.name()
+
+
+def _getMentorDescription(doc, content):
+ """Returns <description> element for a mentor / org admin based on content.
+ """
+
+ description = doc.createElement('description')
+
+ admin = content['admin']
+ if admin:
+ text = doc.createTextNode('Organization admin for ' + admin)
+ description.appendChild(text)
+ description.appendChild(doc.createElement('br'))
+
+ projects = content['projects']
+ if projects:
+ text = doc.createTextNode('Mentoring...')
+ description.appendChild(text)
+ description.appendChild(doc.createElement('br'))
+
+ for project in projects:
+ i = doc.createElement('i')
+ description.appendChild(i)
+
+ title = doc.createTextNode(project['title'])
+ i.appendChild(title)
+ description.appendChild(doc.createElement('br'))
+
+ student = doc.createTextNode('by ' + project['student'])
+ description.appendChild(student)
+ description.appendChild(doc.createElement('br'))
+
+ organization = doc.createTextNode(project['org'])
+ description.appendChild(organization)
+ description.appendChild(doc.createElement('br'))
+
+ consults = content['consults']
+ for consult in consults:
+ text = doc.createTextNode(consult)
+ description.appendChild(text)
+ description.appendChild(doc.createElement('br'))
+
+ description.appendChild(doc.createElement('br'))
+
+ home_pages = content['home_pages']
+ blogs = content['blogs']
+ description = _appendHomePageAndBlogContent(doc, description,
+ home_pages, blogs)
+
+ state = content['state']
+ country = content['country']
+ description = _appendStateAndCountryContnent(doc, description, state,
+ country)
+
+ return description
+
+
+def _getStudentDescription(doc, content):
+ """Returns <description> element for a student based on content.
+ """
+
+ description = doc.createElement('description')
+
+ text = doc.createTextNode('Working on...')
+ description.appendChild(text)
+
+ description.appendChild(doc.createElement('br'))
+
+ project = content['project']
+ i = doc.createElement('i')
+ description.appendChild(i)
+
+ title = doc.createTextNode(project.title)
+ i.appendChild(title)
+ description.appendChild(doc.createElement('br'))
+
+ mentor = doc.createTextNode('mentored by ' + project.mentor.name())
+ description.appendChild(mentor)
+ description.appendChild(doc.createElement('br'))
+
+ org = doc.createTextNode(project.scope.name)
+ description.appendChild(org)
+ description.appendChild(doc.createElement('br'))
+ description.appendChild(doc.createElement('br'))
+
+ home_pages = content['home_pages']
+ blogs = content['blogs']
+ description = _appendHomePageAndBlogContent(doc, description,
+ home_pages, blogs)
+
+ state = content['state']
+ country = content['country']
+ description = _appendStateAndCountryContnent(doc, description, state,
+ country)
+
+ return description
+
+
+def _createFolderForMentorsAndOrgAdmins(doc):
+ """
+ """
+
+ folder = doc.createElement("Folder")
+
+ name = doc.createElement("name")
+ folder.appendChild(name)
+
+ nametext = doc.createTextNode("Mentors")
+ name.appendChild(nametext)
+
+ return folder
+
+
+def _createLineString(doc, student, mentor):
+ """Generates line string between a given student and mentor.
+ """
+
+ line_string = doc.createElement('LineString')
+
+ coordinates = doc.createElement('coordinates')
+ line_string.appendChild(coordinates)
+
+ text = doc.createTextNode(str(student[0]) + ',' + str(student[1]) + ' ' +
+ str(mentor[0]) + ',' + str(mentor[1]))
+ coordinates.appendChild(text)
+
+ altitude_mode = doc.createElement('altitudeMode')
+ line_string.appendChild(altitude_mode)
+
+ text = doc.createTextNode('clampToGround')
+ altitude_mode.appendChild(text)
+
+ extrude = doc.createElement('extrude')
+ line_string.appendChild(extrude)
+
+ text = doc.createTextNode('1')
+ extrude.appendChild(text)
+
+ tessellate = doc.createElement('tessellate')
+ line_string.appendChild(tessellate)
+
+ text = doc.createTextNode('1')
+ tessellate.appendChild(text)
+
+ return line_string
+
+
+def _createPoint(doc, longitude, latitude):
+ """Generates <Point> subtree with coordinates for a given entity.
+ """
+
+ point = doc.createElement('Point')
+
+ coordinates = doc.createElement('coordinates')
+ point.appendChild(coordinates)
+
+ text = doc.createTextNode(str(longitude) + ',' + str(latitude))
+ coordinates.appendChild(text)
+
+ return point
+
+
+def _createStudentPlacemark(doc, coordinates, content):
+ """Creates <Placemark> element for a student based on a given content.
+ """
+
+ placemark = doc.createElement('Placemark')
+
+ style = _getPersonStyle(doc, 'student')
+ placemark.appendChild(style)
+
+ name = doc.createElement('name')
+ placemark.appendChild(name)
+
+ text = doc.createTextNode(content['name'])
+ name.appendChild(text)
+
+ description = _getStudentDescription(doc, content)
+ placemark.appendChild(description)
+
+ point = _createPoint(doc, coordinates[0], coordinates[1])
+ placemark.appendChild(point)
+
+ return placemark
+
+
+def _createMentorPlacemark(doc, coordinates, content):
+ """Creates <Placemark> element for a mentor based on a given content.
+ """
+
+ placemark = doc.createElement('Placemark')
+
+ type = 'org_admin' if content['admin'] is not None else 'mentor'
+ style = _getPersonStyle(doc, type)
+ placemark.appendChild(style)
+
+ name = doc.createElement('name')
+ placemark.appendChild(name)
+
+ text = doc.createTextNode(content['name'])
+ name.appendChild(text)
+
+ description = _getMentorDescription(doc, content)
+ placemark.appendChild(description)
+
+ point = _createPoint(doc, coordinates[0], coordinates[1])
+ placemark.appendChild(point)
+
+ return placemark
+
+
+def _createLineStringPlacemark(doc, student_coordinates, mentor_coordinates):
+ """Creates <Placemark> element for a line string between given student
+ coordinates and mentor coordinates.
+ """
+
+ placemark = doc.createElement('Placemark')
+
+ line_string = _createLineString(doc, student_coordinates, mentor_coordinates)
+ placemark.appendChild(line_string)
+
+ style = _getLineStringStyle(doc)
+ placemark.appendChild(style)
+
+ return placemark
+
+
+def _processMentor(doc, org_admin, mentors, folder):
+ """Processes a student and adds information to a folder.
+ """
+
+ projects = []
+ placemarks = {}
+ longitude = None
+ latitude = None
+
+ for entity in mentors:
+ if not entity.publish_location:
+ continue
+
+ longitude, latitude = (entity.longitude, entity.latitude)
+
+ if not placemarks.get((longitude, latitude)):
+ placemarks[(longitude, latitude)] = {
+ 'admin': None,
+ 'projects': [],
+ 'consults': [],
+ 'name': entity.name(),
+ 'country': entity.res_country,
+ 'state': entity.res_state,
+ 'home_pages': set(),
+ 'blogs': set()
+ }
+
+ projects = _getMentoredProjects(entity)
+ if not projects:
+ placemarks[(longitude, latitude)]['consults'].append(
+ 'Mentor for ' + entity.scope.name)
+ else:
+ for project in projects:
+ placemarks[(longitude, latitude)]['projects'].append({
+ 'title': project.title,
+ 'org': project.scope.name,
+ 'student': project.student.name()
+ })
+
+ if entity.home_page:
+ placemarks[(longitude, latitude)]['home_pages'].add(entity.home_page)
+ if entity.blog:
+ placemarks[(longitude, latitude)]['blogs'].add(entity.blog)
+
+ if org_admin and org_admin.publish_location:
+
+ if not (longitude, latitude):
+ longitude, latitude = (org_admin.longitude, org_admin.latitude)
+
+ if not placemarks.get((longitude, latitude)):
+ placemarks[(longitude, latitude)] = {
+ 'admin': None,
+ 'projects': [],
+ 'consults': [],
+ 'name': org_admin.name(),
+ 'country': org_admin.res_country,
+ 'state': org_admin.res_state,
+ 'home_pages': set(),
+ 'blogs': set()
+ }
+
+ placemarks[(longitude, latitude)]['admin'] = org_admin.scope.name
+
+ if org_admin.home_page:
+ placemarks[(longitude, latitude)]['home_pages'].add(org_admin.home_page)
+ if org_admin.blog:
+ placemarks[(longitude, latitude)]['blogs'].add(org_admin.blog)
+
+ for coordinates, content in placemarks.iteritems():
+ placemark = _createMentorPlacemark(doc, coordinates, content)
+ folder.appendChild(placemark)
+
+
+def _processStudent(doc, student, orgs_folder):
+ """Processes a student and adds information to a folder.
+ """
+
+ if not student.publish_location:
+ return
+
+ project = _getStudentProject(student)
+
+ if not project:
+ return
+
+ folder = doc.createElement('Folder')
+
+ name = doc.createElement('name')
+ folder.appendChild(name)
+
+ name.appendChild(doc.createTextNode(student.name()))
+
+ content = {
+ 'name': student.name(),
+ 'project': project,
+ 'country': student.res_country,
+ 'state': student.res_state,
+ 'home_pages': [student.home_page] if student.home_page else [],
+ 'blogs': [student.blog] if student.blog else []
+ }
+
+ coordinates = student.longitude, student.latitude
+
+ placemark = _createStudentPlacemark(doc, coordinates, content)
+ folder.appendChild(placemark)
+
+ mentor = project.mentor
+
+ if mentor.publish_location:
+ mentor_coordinates = mentor.longitude, mentor.latitude
+ line_string = _createLineStringPlacemark(doc, coordinates,
+ mentor_coordinates)
+ folder.appendChild(line_string)
+
+ org = project.scope
+ org_folder = orgs_folder[org.name]
+ org_folder.appendChild(folder)
+
+
+def _processAllUsers(doc, mentors_folder, orgs_folder):
+ """Processes all users and fills folders with information based on roles.
+ """
+
+ from soc.logic.models.mentor import logic as mentor_logic
+ from soc.logic.models.org_admin import logic as org_admin_logic
+ from soc.logic.models.student import logic as student_logic
+
+ it = _getAllOrgAdmins()
+ org_admins = dict()
+ for org_admin in it:
+ org_admins[org_admin.link_id] = org_admin
+
+ it = _getAllMentors()
+ mentors = dict()
+ for mentor in it:
+ link_id = mentor.link_id
+ if link_id not in mentors:
+ mentors[link_id] = []
+ mentors[link_id].append(mentor)
+
+ it = _getAllStudents()
+ students = dict()
+ for student in it:
+ students[student.link_id] = student
+
+ link_ids = set(mentors.keys() + org_admins.keys())
+
+ for link_id in link_ids:
+ entity = org_admins.get(link_id)
+ entities = mentors.get(link_id, [])
+
+ if entity or entities:
+ _processMentor(doc, entity, entities, mentors_folder)
+ continue
+
+ link_ids = students.keys()
+ for link_id in link_ids:
+ entity = students.get(link_id)
+ if entity:
+ _processStudent(doc, entity, orgs_folder)
+
+
+def _createFolderForStudentsAndOrgs(doc):
+ """Creates <Folder> elements for all students and for all accepted
+ organizations.
+
+ Returns:
+ A tuple whose first element is a folder for students and the second
+ one is a dictionary mapping organization names with their folders.
+ """
+
+ folder = doc.createElement('Folder')
+
+ name = doc.createElement('name')
+ folder.appendChild(name)
+
+ text = doc.createTextNode('Students')
+ name.appendChild(text)
+
+ orgs = _getAcceptedOrgs()
+ org_folders = {}
+
+ for org in orgs:
+ org_folder = doc.createElement('Folder')
+ folder.appendChild(org_folder)
+
+ name = doc.createElement('name')
+ org_folder.appendChild(name)
+
+ text = doc.createTextNode(org.name)
+ name.appendChild(text)
+
+ org_folders[org.name] = org_folder
+
+ return folder, org_folders
+
+
+def generateCompleteKML():
+ """Generates complete KML file for Google Summer of Code 2009.
+ """
+
+ doc = Document()
+
+ kml = doc.createElement('kml')
+ doc.appendChild(kml)
+
+ document = doc.createElement('Document')
+ kml.appendChild(document)
+
+ mentor_folder = _createFolderForMentorsAndOrgAdmins(doc)
+ document.appendChild(mentor_folder)
+
+ student_folder, org_folders = _createFolderForStudentsAndOrgs(doc)
+ document.appendChild(student_folder)
+
+ _processAllUsers(doc, mentor_folder, org_folders)
+
+ out = codecs.open('soc_map2009.kml', 'w', 'utf-8')
+ out.write(doc.toprettyxml(indent=' '))
+ out.close()
+
+
+def main(args):
+
+ context = {
+ 'export': generateCompleteKML,
+ }
+ interactive.setup()
+ interactive.remote(args, context)
+
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print "Usage: %s app_id [host]" % (sys.argv[0],)
+ sys.exit(1)
+
+ main(sys.argv[1:])