def make_tags_for_employee(e_id): cnt_bigrams = Counter() employee_projects = GuideDataAccess( get_db()).get_projects_for_employee(e_id) project_access = ProjectDataAccess(get_db()) for project in employee_projects: tags = project_access.get_project_tags(project['project_id']) for tag in tags: cnt_bigrams[tag] += 1 return cnt_bigrams
def search(search_query): """ Handles the GET request to '/search/<search_query>'. :param search_query: search query :return: Json with results """ project_access = ProjectDataAccess(get_db()) active_only = not session.get("archive") results = project_access.search(search_query, active_only) return jsonify(results)
def active(receiver, is_student): if is_student: return '' projects = GuideDataAccess(get_db()).get_projects_for_employee( receiver.e_id) access = ProjectDataAccess(get_db()) projects = [access.get_project(x['project_id'], True) for x in projects] if not projects: return '' text = '\n\nACTIVE' for project in projects: text += project_link(project) return text
def archived_old(receiver, is_student): if is_student: return '' projects = GuideDataAccess(get_db()).get_projects_for_employee( receiver.e_id) access = ProjectDataAccess(get_db()) projects = [access.get_project(x['project_id'], False) for x in projects] projects = [project for project in projects if not project.is_active] if not projects: return '' text = '\n\nARCHIVED OLD:' for project in projects: text += project_link(project) return text
def get_all_project_data(p_id): """ Handles the GET request to '/get-all-project-data/<int:p_id>'. :param p_id: project id :return: Json with all project data, the research group and links. """ active_only = not session["archive"] project_access = ProjectDataAccess(get_db()) p_data = project_access.get_project(p_id, active_only) if current_user.is_authenticated and current_user.role == "student": p_data.liked = LikeDataAccess(get_db()).is_liked( p_data.project_id, current_user.user_id) # Add linked projects linked_projects = LinkDataAccess(get_db()).get_links_for_project(p_id) linked_projects_data = set() for link in linked_projects: linked_project = project_access.get_project(link.project_2, active_only) if len(linked_projects_data) >= 4: break if not linked_project.is_active: continue linked_projects_data.add(linked_project) # Fill linked projects list with most viewed projects if len(linked_projects_data) < 4: projects_most_views = project_access.get_most_viewed_projects( 8, active_only) i = 0 while len(linked_projects_data) < 4: if not projects_most_views[i].project_id == p_id: linked_projects_data.add(projects_most_views[i]) i += 1 try: research_group = ResearchGroupDataAccess(get_db()).get_research_group( p_data.research_group).to_dict() except: research_group = None return jsonify({ "project_data": p_data.to_dict(), "research_group": research_group, "links": [obj.to_dict() for obj in linked_projects_data] })
def add_type(project, p_type): """ Adds a type in the database. :param project: project id :param p_type: type name """ try: ProjectDataAccess(get_db()).add_type(project, p_type) except: pass
def archived_recent(receiver, is_student): if is_student: return '' projects = GuideDataAccess(get_db()).get_projects_for_employee( receiver.e_id) access = ProjectDataAccess(get_db()) projects = [access.get_project(x['project_id'], True) for x in projects] projects = [x for x in projects if x.is_active] if not projects: return '' text = '\n\nARCHIVED RECENT:' roll_over_performed = False for project in projects: if project_is_full(project): access.set_active(project.project_id, False) text += project_link(project) roll_over_performed = True if not roll_over_performed: return '' return text
def projects_pending(receiver, is_student): if is_student: return '' projects = GuideDataAccess(get_db()).get_projects_for_employee( receiver.e_id) proj_access = ProjectDataAccess(get_db()) projects = [ proj_access.get_project(x['project_id'], False) for x in projects ] projects = filter(lambda p: p.is_active, projects) reg_access = RegistrationDataAccess(get_db()) pending_projects = [ x for x in projects if reg_access.get_pending_registrations(x.project_id) ] if not pending_projects: return '' text = "\n\nPROJECTS WITH PENDING REGISTRATIONS:" for project in pending_projects: text += project_link(project) return text
def projects_assigned_new(receiver, is_student): access = ProjectDataAccess(get_db()) if is_student: reg_access = RegistrationDataAccess(get_db()) all_projects = access.get_project_ids(active_only=True) project_ids = [] for x in all_projects: registration = reg_access.get_registration(receiver.student_id, x) if registration: if registration.reg_date.year >= datetime.datetime.now( ).year - 1: project_ids.append(registration.project) newly_assigned_projects = [ access.get_project(x, False) for x in project_ids ] text = "\n\nREGISTERED PROJECTS FOR THIS YEAR AND LAST YEAR:" else: projects = GuideDataAccess(get_db()).get_projects_for_employee( receiver.e_id) projects = [ access.get_project(x['project_id'], False) for x in projects ] text = "\n\nNEWLY ASSIGNED PROJECTS:" projects = filter(lambda p: p.is_active, projects) newly_assigned_projects = [] for project in projects: newly_assigned_projects += [ project for x in project.registrations if x['status'] == "Accepted" and x['last_updated'].month >= datetime.datetime.now().month - 2 and x['last_updated'].year == datetime.datetime.now().year ] if not newly_assigned_projects: return '' newly_assigned_projects = list(dict.fromkeys(newly_assigned_projects)) for project in newly_assigned_projects: text += project_link(project) return text
def add_view(p_id): """ Handles the POST request to '/add-view/<int:p_id>'. :param p_id: project id :return: Json with success/failure status """ try: ProjectDataAccess(get_db()).add_view_count(p_id, 1) return jsonify({'success': True}), 200, { 'ContentType': 'application/json' } except: print("Failed to count a view for project " + str(p_id) + ".") return ""
def add_tag(project, tag): """ Adds a tag in the database. :param project: project id :param tag: tag name """ try: TagDataAccess(get_db()).add_tag(tag) except: pass try: ProjectDataAccess(get_db()).add_project_tag(project, tag) except: pass
def add_registration(): """ Handles the POST request to '/project-editor'. :return: Json with success/failure status. """ if current_user.is_authenticated and current_user.role == "student": try: project_id = request.form['data'] type = request.form['type'] registration = Registration(current_user.user_id, project_id, type, "Pending") RegistrationDataAccess(get_db()).add_registration(registration) project = ProjectDataAccess(get_db()).get_project( project_id, False) if not project.is_active: raise Exception() msg = f"You registered for project {project.title}!\n" \ f"You'll be notified when one of the supervisors changes your registration status.\n" \ f"Best of luck!" send_mail(current_user.user_id + "@ad.ua.ac.be", "ESP Registration", msg) msg_employees = f"Student {current_user.name} ({current_user.user_id}) has registered for your project {project.title}.\n" \ f"To change the registration status please visit the ESP site." \ guides = GuideDataAccess( get_db()).get_guides_for_project(project_id) employee_access = EmployeeDataAccess(get_db()) guides_with_info = [ employee_access.get_employee(x.employee) for x in guides ] for guide in guides_with_info: if guide.email: send_mail(guide.email, "ESP Registration", msg_employees) return jsonify({'success': True}), 200, { 'ContentType': 'application/json' } except Exception as e: return jsonify({ 'success': False, "message": "Failed to add a new registration!" }), 400, { 'ContentType': 'application/json' }
def employee_authorized_for_project(employee_name, project_id): """ Checks if an employee has authorisation over a certain project. :param employee_name: employee name :param project_id: project id :return: Boolean """ employee = EmployeeDataAccess(get_db()).get_employee_by_name(employee_name) guides = GuideDataAccess(get_db()).get_guides_for_project(project_id) for guide in guides: if guide.employee == employee.e_id: return True project = ProjectDataAccess(get_db()).get_project(project_id, False) return employee.research_group == project.research_group
def cancel_project_extension(p_id): """ Handles the POST request to '/extend_project/<int:p_id>'. Attempts to cancel project extension with sent project id. :param p_id: project id :return: Json with success/failure status. """ try: ProjectDataAccess(get_db()).delete_project_extension(p_id) return jsonify({'success': True}), 200, { 'ContentType': 'application/json' } except: return jsonify({'success': False, "message": "Failed to cancel project extension with id: " + str(p_id) + " !"}) \ , 400, {'ContentType': 'application/json'}
def construct_tag_database(): conn = DBConnection(dbname=config_data['dbname'], dbuser=config_data['dbuser'], dbpass=config_data['dbpass'], dbhost=config_data['dbhost']) tag_access = TagDataAccess(conn) project_access = ProjectDataAccess(conn) # Add most common tags common_tags = make_all_tags() common_tags_list = [] for tag, index in common_tags.most_common(200): if index > 2: try: tag_access.add_tag(tag) except: pass common_tags_list.append(tag) # Link tags with projects # Get all the project id's id_list = project_access.get_project_ids() for p_id in id_list: # Collect all the bigrams for the given project bigrams = make_project_tags(p_id) # Keep count of how many tags were added to the project tags_added = 0 reserve_tags = {} # First associate the tags that are already in the database for bigram in bigrams: if common_tags_list.count(bigram) >= 1 and tags_added < 5: try: project_access.add_project_tag(p_id, bigram) tags_added += 1 except Exception: pass else: reserve_tags[bigram] = p_id # Associate the rest of the tags (max 5 tags) while tags_added < 5 and reserve_tags: tag, p_id = reserve_tags.popitem() # Add try because the tag might already exist in the database try: tag_access.add_tag(tag) except Exception: pass try: project_access.add_project_tag(p_id, tag) except: pass tags_added += 1
def handle_registration(): """ Handles the POST request to '/handle-registration'. :return: Json with success/failure status. / redirects to login """ if current_user.is_authenticated and current_user.role != "student": try: data = request.json RegistrationDataAccess(get_db()).update_registration( student_id=data['student_id'], project_id=data['project_id'], new_status=data['status'], new_type=data['type']) project_title = ProjectDataAccess(get_db()).get_project( data['project_id'], False).title if data['status']: msg = f"Your registration for project {project_title} has changed to {data['status']}.\n" \ f"For questions or remarks please contact the supervisors of the project." send_mail(data['student_id'] + "@ad.ua.ac.be", "ESP Registration Update", msg) except: return jsonify({ 'success': False, "message": "Failed to update registration!" }), 400, { 'ContentType': 'application/json' } return jsonify({'success': True}), 200, { 'ContentType': 'application/json' } else: return jsonify({ 'success': False, "message": "Failed to update registration!" }), 400, { 'ContentType': 'application/json' }
def register_user_data(p_id): """ Handles the POST request to '/register-user-data/<int:p_id>'. :param p_id: project id :return: Json with success/failure status """ try: ProjectDataAccess(get_db()).add_view_count(p_id, 1) if session.get('session_id') is not None: ClickDataAccess(get_db()).add_project_click( p_id, session['session_id']) return jsonify({'success': True}), 200, { 'ContentType': 'application/json' } except: return jsonify({ 'success': True, 'message': "Failed to register user behaviour for project " + str(p_id) + "." }), 400, { 'ContentType': 'application/json' }
def construct_link_database(): all_projects = ProjectDataAccess(get_db()).get_projects(True, True) all_projects = [project.to_dict() for project in all_projects] link_access = LinkDataAccess(get_db()) dutch_projects = list() english_projects = list() # Devide projects on the language of their description for project in all_projects: if project['html_content_eng'] is not None: english_projects.append(project) if project['html_content_nl'] is not None: dutch_projects.append(project) # Calculate the match between english projects for project1 in english_projects: for project2 in english_projects: if not project1 == project2: match = calculate_match(project1, project2, 'html_content_eng') if match > 0.071: try: link_access.add_link( Link(project1['project_id'], project2['project_id'], match)) except: pass # Calculate the match between dutch projects for project1 in dutch_projects: for project2 in dutch_projects: if not project1 == project2: match = calculate_match(project1, project2, 'html_content_nl') if match > 1: try: link_access.add_link( Link(project1['project_id'], project2['project_id'], match)) except: pass
def get_projects_with_recommendations(): """ Fetches all projects, with their (updated) recommendation index. :return: Json of all projects """ if current_user.is_authenticated and current_user.role == "student": # Check if student in database try: student = StudentDataAccess(get_db()).get_student( current_user.user_id) student_found = student is not None likes = LikeDataAccess(get_db()).get_student_likes( student.student_id) project_clicks = SessionDataAccess(get_db()).get_student_clicks( student.student_id) # If there are clicks present if project_clicks: max_clicks = max(project_clicks, key=project_clicks.get) max_clicks = project_clicks[max_clicks] else: max_clicks = 0 recommendations = get_user_based_recommendations( get_favorite_projects(likes, project_clicks)) except: student_found = False else: student_found = False project_access = ProjectDataAccess(get_db()) active_only = not session.get("archive", False) all_projects = [ obj.to_dict() for obj in project_access.get_projects(active_only) ] max_views = project_access.get_most_viewed_projects( 1, active_only)[0].view_count oldest, newest = project_access.get_oldest_and_newest() oldest = oldest.timestamp() biggest_difference = newest.timestamp() - oldest for project in all_projects: project["recommendation"] = 0 if max_views != 0: project["recommendation"] += project["view_count"] / max_views if biggest_difference != 0: project["recommendation"] += (project["last_updated"] - oldest) / biggest_difference if not student_found: continue project["liked"] = project["project_id"] in likes if project["project_id"] in recommendations: project["recommendation"] += recommendations[project["project_id"]] if project["liked"]: project["recommendation"] += 0.5 elif project["project_id"] in project_clicks and max_clicks != 0: project["recommendation"] += project_clicks[ project["project_id"]] / max_clicks return all_projects
def project_editor(data): """ Modifies an existing project and makes sure that database content is added/removed/updated where necessary. :param data: data object containing all info for the altered project :return: Json with success/failure status and the project id. """ project_access = ProjectDataAccess(get_db()) guide_access = GuideDataAccess(get_db()) employee_access = EmployeeDataAccess(get_db()) document_access = DocumentDataAccess(get_db()) new_project = data.get('new', False) nl_data = data['html_content_nl'] en_data = data['html_content_eng'] if new_project: new_document = document_access.add_document( Document(None, en_data, nl_data)) document_id = new_document.document_id else: document_id = data['description_id'] document_access.update_document(Document(document_id, en_data, nl_data)) title = data['title'] group = data['research_group'] max_students = data['max_students'] is_active = data['is_active'] if new_project: project = Project(None, title, max_students, document_id, group, is_active, None, 0, False) project = project_access.add_project(project) p_id = project.project_id else: p_id = data['project_id'] project_access.update_project(p_id, title, max_students, group, is_active) guide_access.remove_project_guides(p_id) promotors = data['promotors'] for promotor in promotors: if promotor != "": employee_id = employee_access.get_employee_by_name(promotor).e_id guide = Guide(employee_id, p_id, "Promotor") guide_access.add_guide(guide) copromotorlist = data['co-promotors'] for copromotor in copromotorlist: if copromotor != "": employee_id = employee_access.get_employee_by_name(copromotor).e_id guide = Guide(employee_id, p_id, "Co-Promotor") guide_access.add_guide(guide) mentorlist = data['mentors'] for mentor in mentorlist: if mentor != "": employee_id = employee_access.get_employee_by_name(mentor).e_id guide = Guide(employee_id, p_id, "Mentor") guide_access.add_guide(guide) tags = data['tags'] if not new_project: project_access.remove_tags(p_id) tag_access = TagDataAccess(get_db()) for tag in tags: if tag != "": try: tag_access.add_tag(tag) except: pass project_access.add_project_tag(p_id, tag) types = data['types'] if not new_project: project_access.remove_types(p_id) type_access = TypeDataAccess(get_db()) for p_type in types: try: mytype = Type(p_type, True) type_access.add_type(mytype) except: pass project_access.add_type(p_id, p_type) attachment_access = AttachmentDataAccess(get_db()) if not new_project: attachment_access.remove_attachments(document_id) for json_attachment in data['attachments']: attachment = Attachment(name=json_attachment['name'], file_location=json_attachment['file_location'], document_id=document_id) attachment_access.add_attachment(attachment) project_access.update_search_index() return jsonify({ 'success': True, 'project_id': p_id }), 200, { 'ContentType': 'application/json' }
def manage(data): """ Modifies the database. :param data: object holding all data to be modified in the database. :return: Json with success/failure status. """ for entry in data['entries']: entry_type = entry['entry_type'] for project in data["projects"]: try: if "add-employee" == entry_type: guidance = entry['guidance'] name = entry['name'] add_employee(project, guidance, name) elif "remove-employee" == entry_type: name = entry['name'] employee = EmployeeDataAccess( get_db()).get_employee_by_name(name) GuideDataAccess(get_db()).remove_guide( employee.e_id, project) elif "add-tag" == entry_type: tag = entry['tag'] add_tag(project, tag) elif "remove-tag" == entry_type: tag = entry['tag'] ProjectDataAccess(get_db()).remove_tag(project, tag) elif "add-type" == entry_type: p_type = entry['type'] add_type(project, p_type) elif "remove-type" == entry_type: p_type = entry['type'] ProjectDataAccess(get_db()).remove_type(project, p_type) elif "replace-group" == entry_type: group = entry['group'] ProjectDataAccess(get_db()).set_research_group( project, group) elif "replace-active" == entry_type: active = entry['active'] ProjectDataAccess(get_db()).set_active(project, active) else: return jsonify({ 'success': False, "message": "Missing correct entry_type" }), 400, { 'ContentType': 'application/json' } except Exception as e: return jsonify({ 'success': False, "message": str(e) }), 400, { 'ContentType': 'application/json' } return jsonify({'success': True}), 200, {'ContentType': 'application/json'}
def make_all_tags(): all_projects = ProjectDataAccess(get_db()).get_projects(True) data_dct = [obj.to_dict() for obj in all_projects] return find_all_project_tags(data_dct)
def make_project_tags(p_id): project = ProjectDataAccess(get_db()).get_project(p_id, False) return find_tags_for_project(project.to_dict())