| #!/usr/bin/env python |
| # |
| # 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. |
| """ |
| |
| |
| 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:]) |