def competition_leaderboard(event_name): """Landing page for the competition leaderboard for all users. Parameters ---------- event_name : str The event name. """ event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user(u'{}: no event named "{}"'.format( flask_login.current_user.firstname, event_name)) add_user_interaction(db.session, interaction='looking at leaderboard', user=flask_login.current_user, event=event) admin = is_admin(db.session, event_name, flask_login.current_user.name) leaderboard_html = event.public_competition_leaderboard_html leaderboard_kwargs = dict(leaderboard=leaderboard_html, leaderboard_title='Leaderboard', sorting_column_index=0, sorting_direction='asc', event=event, admin=admin) return render_template('leaderboard.html', **leaderboard_kwargs)
def event_plots(event_name): """Landing page of the plot illustrating the score evolution over time for a specific RAMP event. Parameters ---------- event_name : str The name of the event. """ event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user('{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name)) if event: p = score_plot(db.session, event) script, div = components(p) return render_template('event_plots.html', script=script, div=div, event=event) return redirect_to_user('Event {} does not exist.' .format(event_name), is_error=True)
def user_event(event_name): """Landing page for a given event. Parameters ---------- event_name : str The event name. """ if flask_login.current_user.access_level == 'asked': msg = 'Your account has not been approved yet by the administrator' logger.error(msg) return redirect_to_user(msg) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user('{}: no event named "{}"'.format( flask_login.current_user.firstname, event_name)) event = get_event(db.session, event_name) if event: if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='looking at event', event=event, user=flask_login.current_user) admin = is_admin(db.session, event_name, flask_login.current_user.name) approved = is_user_signed_up(db.session, event_name, flask_login.current_user.name) asked = is_user_sign_up_requested(db.session, event_name, flask_login.current_user.name) return render_template('event.html', event=event, admin=admin, approved=approved, asked=asked) return redirect_to_user('Event {} does not exist.'.format(event_name), is_error=True)
def leaderboard(event_name): """Landing page showing all user's submissions information. Parameters ---------- event_name : str The name of the event. """ event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user( '{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name)) if app.config['TRACK_USER_INTERACTION']: add_user_interaction( db.session, interaction='looking at leaderboard', user=flask_login.current_user, event=event ) if is_accessible_leaderboard(db.session, event_name, flask_login.current_user.name): leaderboard_html = event.public_leaderboard_html_with_links else: leaderboard_html = event.public_leaderboard_html_no_links if event.official_score_type.is_lower_the_better: sorting_direction = 'asc' else: sorting_direction = 'desc' leaderboard_kwargs = dict( leaderboard=leaderboard_html, leaderboard_title='Leaderboard', sorting_column_index=4, sorting_direction=sorting_direction, event=event ) if is_admin(db.session, event_name, flask_login.current_user.name): failed_leaderboard_html = event.failed_leaderboard_html new_leaderboard_html = event.new_leaderboard_html template = render_template( 'leaderboard.html', failed_leaderboard=failed_leaderboard_html, new_leaderboard=new_leaderboard_html, admin=True, **leaderboard_kwargs ) else: template = render_template( 'leaderboard.html', **leaderboard_kwargs ) return template
def private_leaderboard(event_name): """Landing page for the private leaderboard. Parameters ---------- event_name : str The event name. """ if not flask_login.current_user.is_authenticated: return redirect(url_for('auth.login')) event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user( '{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name) ) if (not is_admin(db.session, event_name, flask_login.current_user.name) and (event.closing_timestamp is None or event.closing_timestamp > datetime.datetime.utcnow())): return redirect(url_for('ramp.problems')) if app.config['TRACK_USER_INTERACTION']: add_user_interaction( db.session, interaction='looking at private leaderboard', user=flask_login.current_user, event=event ) leaderboard_html = event.private_leaderboard_html admin = is_admin(db.session, event_name, flask_login.current_user.name) if event.official_score_type.is_lower_the_better: sorting_direction = 'asc' else: sorting_direction = 'desc' approved = is_user_signed_up( db.session, event_name, flask_login.current_user.name ) asked = approved template = render_template( 'leaderboard.html', leaderboard_title='Leaderboard', leaderboard=leaderboard_html, sorting_column_index=5, sorting_direction=sorting_direction, event=event, private=True, admin=admin, asked=asked, approved=approved ) return template
def test_is_accessible_event(session_toy_db, event_name, user_name, is_accessible): # force one of the user to not be approved if user_name == 'test_user': user = get_user_by_name(session_toy_db, user_name) user.access_level = 'asked' session_toy_db.commit() # force an event to be private if event_name == 'boston_housing_test': event = get_event(session_toy_db, event_name) event.is_public = False session_toy_db.commit() assert is_accessible_event(session_toy_db, event_name, user_name) is is_accessible
def my_submissions(event_name): """Landing page of all user's submission information. Parameters ---------- event_name : str The name of the event. """ event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user( '{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name) ) if app.config['TRACK_USER_INTERACTION']: add_user_interaction( db.session, interaction='looking at my_submissions', user=flask_login.current_user, event=event ) if not is_accessible_code(db.session, event_name, flask_login.current_user.name): error_str = ('No access to my submissions for event {}. If you have ' 'already signed up, please wait for approval.' .format(event.name)) return redirect_to_user(error_str) # Doesn't work if team mergers are allowed event_team = get_event_team_by_name(db.session, event_name, flask_login.current_user.name) leaderboard_html = event_team.leaderboard_html failed_leaderboard_html = event_team.failed_leaderboard_html new_leaderboard_html = event_team.new_leaderboard_html admin = is_admin(db.session, event_name, flask_login.current_user.name) if event.official_score_type.is_lower_the_better: sorting_direction = 'asc' else: sorting_direction = 'desc' return render_template('leaderboard.html', leaderboard_title='Trained submissions', leaderboard=leaderboard_html, failed_leaderboard=failed_leaderboard_html, new_leaderboard=new_leaderboard_html, sorting_column_index=4, sorting_direction=sorting_direction, event=event, admin=admin)
def sign_up_for_event(event_name): """Landing page to sign-up to a specific RAMP event. Parameters ---------- event_name : str The name of the event. """ event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user('{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name)) if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='signing up at event', user=flask_login.current_user, event=event) ask_sign_up_team(db.session, event.name, flask_login.current_user.name) if event.is_controled_signup: admin_users = User.query.filter_by(access_level='admin') for admin in admin_users: subject = ('Request to sign-up {} to RAMP event {}' .format(event.name, flask_login.current_user.name)) body = body_formatter_user(flask_login.current_user) url_approve = ('http://{}/events/{}/sign_up/{}' .format( app.config['DOMAIN_NAME'], event.name, flask_login.current_user.name )) body += ('Click on this link to approve the sign-up request: {}' .format(url_approve)) send_mail(admin, subject, body) return redirect_to_user("Sign-up request is sent to event admins.", is_error=False, category='Request sent') sign_up_team(db.session, event.name, flask_login.current_user.name) return redirect_to_sandbox( event, '{} is signed up for {}.' .format(flask_login.current_user.firstname, event), is_error=False, category='Successful sign-up' )
def private_competition_leaderboard(event_name): """Landing page for the private competition leaderboard. Parameters ---------- event_name : str The event name. """ if not flask_login.current_user.is_authenticated: return redirect(url_for('auth.login')) event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user(u'{}: no event named "{}"'.format( flask_login.current_user.firstname, event_name)) if (not is_admin(db.session, event_name, flask_login.current_user.name) and (event.closing_timestamp is None or event.closing_timestamp > datetime.datetime.utcnow())): return redirect(url_for('ramp.problems')) if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='looking at private leaderboard', user=flask_login.current_user, event=event) admin = is_admin(db.session, event_name, flask_login.current_user.name) approved = is_user_signed_up(db.session, event_name, flask_login.current_user.name) asked = approved leaderboard_html = event.private_competition_leaderboard_html leaderboard_kwargs = dict(leaderboard=leaderboard_html, leaderboard_title='Leaderboard', sorting_column_index=0, sorting_direction='asc', event=event, admin=admin, asked=asked, approved=approved) return render_template('leaderboard.html', **leaderboard_kwargs)
def user_event(event_name): """Landing page for a given event. Parameters ---------- event_name : str The event name. """ if flask_login.current_user.access_level == 'asked': msg = 'Your account has not been approved yet by the administrator' logger.error(msg) return redirect_to_user(msg) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user('{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name)) event = get_event(db.session, event_name) if event: if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='looking at event', event=event, user=flask_login.current_user) description_f_name = os.path.join( event.problem.path_ramp_kit, '{}_starting_kit.html'.format(event.problem.name) ) with codecs.open(description_f_name, 'r', 'utf-8') as description_file: description = description_file.read() admin = is_admin(db.session, event_name, flask_login.current_user.name) approved = is_user_signed_up( db.session, event_name, flask_login.current_user.name ) asked = approved return render_template('event.html', description=description, event=event, admin=admin, approved=approved, asked=asked) return redirect_to_user('Event {} does not exist.' .format(event_name), is_error=True)
def update_event(event_name): """Update the parameters of an event. Parameters ---------- event_name : str The name of the event. """ if not is_admin(db.session, event_name, flask_login.current_user.name): return redirect_to_user( 'Sorry {}, you do not have admin rights' .format(flask_login.current_user.firstname), is_error=True ) event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user( '{}: no event named "{}"' .format(flask_login.current_user.firstname, event_name) ) logger.info('{} is updating event {}' .format(flask_login.current_user.name, event.name)) admin = is_admin(db.session, event_name, flask_login.current_user.name) # We assume here that event name has the syntax <problem_name>_<suffix> suffix = event.name[len(event.problem.name) + 1:] h = event.min_duration_between_submissions // 3600 m = event.min_duration_between_submissions // 60 % 60 s = event.min_duration_between_submissions % 60 form = EventUpdateProfileForm( suffix=suffix, title=event.title, is_send_trained_mails=event.is_send_trained_mails, is_send_submitted_mails=event.is_send_submitted_mails, is_public=event.is_public, is_controled_signup=event.is_controled_signup, is_competitive=event.is_competitive, min_duration_between_submissions_hour=h, min_duration_between_submissions_minute=m, min_duration_between_submissions_second=s, opening_timestamp=event.opening_timestamp, closing_timestamp=event.closing_timestamp, public_opening_timestamp=event.public_opening_timestamp, ) if form.validate_on_submit(): try: if form.suffix.data == '': event.name = event.problem.name else: event.name = event.problem.name + '_' + form.suffix.data event.title = form.title.data event.is_send_trained_mails = form.is_send_trained_mails.data event.is_send_submitted_mails = form.is_send_submitted_mails.data event.is_public = form.is_public.data event.is_controled_signup = form.is_controled_signup.data event.is_competitive = form.is_competitive.data event.min_duration_between_submissions = ( form.min_duration_between_submissions_hour.data * 3600 + form.min_duration_between_submissions_minute.data * 60 + form.min_duration_between_submissions_second.data) event.opening_timestamp = form.opening_timestamp.data event.closing_timestamp = form.closing_timestamp.data event.public_opening_timestamp = form.public_opening_timestamp.data db.session.commit() except IntegrityError as e: db.session.rollback() message = '' existing_event = get_event(db.session, event.name) if existing_event is not None: message += 'event name is already in use' # # try: # # User.query.filter_by(email=email).one() # # if len(message) > 0: # # message += ' and ' # # message += 'email is already in use' # except NoResultFound: # pass if message: e = NameClashError(message) flash('{}'.format(e), category='Update event error') return redirect(url_for('update_event', event_name=event.name)) return redirect(url_for('ramp.problems')) approved = is_user_signed_up( db.session, event_name, flask_login.current_user.name ) asked = approved return render_template( 'update_event.html', form=form, event=event, admin=admin, asked=asked, approved=approved )
def sandbox(event_name): """Landing page for the user's sandbox. Parameters ---------- event_name : str The event name. """ event = get_event(db.session, event_name) if not is_accessible_event(db.session, event_name, flask_login.current_user.name): return redirect_to_user(u'{}: no event named "{}"'.format( flask_login.current_user.firstname, event_name)) if not is_accessible_code(db.session, event_name, flask_login.current_user.name): error_str = ('No access to sandbox for event {}. If you have ' 'already signed up, please wait for approval.'.format( event.name)) return redirect_to_user(error_str) # setup the webpage when loading # we use the code store in the sandbox to show to the user sandbox_submission = get_submission_by_name(db.session, event_name, flask_login.current_user.name, event.ramp_sandbox_name) event_team = get_event_team_by_name(db.session, event_name, flask_login.current_user.name) # initialize the form for the code # The amount of python magic we have to do for rendering a variable # number of textareas, named and populated at run time, is mind # boggling. # First we need to make sure CodeForm is empty # for name_code in CodeForm.names_codes: # name, _ = name_code # delattr(CodeForm, name) CodeForm.names_codes = [] # Then we create named fields in the CodeForm class for each editable # submission file. They have to be populated when the code_form object # is created, so we also create a code_form_kwargs dictionary and # populate it with the codes. code_form_kwargs = {} for submission_file in sandbox_submission.files: if submission_file.is_editable: f_field = submission_file.name setattr(CodeForm, f_field, StringField(u'Text', widget=TextArea())) code_form_kwargs[f_field] = submission_file.get_code() code_form_kwargs['prefix'] = 'code' code_form = CodeForm(**code_form_kwargs) # Then, to be able to iterate over the files in the sandbox.html # template, we also fill a separate table of pairs (file name, code). # The text areas in the template will then have to be created manually. for submission_file in sandbox_submission.files: if submission_file.is_editable: code_form.names_codes.append( (submission_file.name, submission_file.get_code())) # initialize the submission field and the the uploading form submit_form = SubmitForm(submission_name=event_team.last_submission_name, prefix='submit') upload_form = UploadForm(prefix='upload') admin = is_admin(db.session, event_name, flask_login.current_user.name) if request.method == 'GET': return render_template('sandbox.html', submission_names=sandbox_submission.f_names, code_form=code_form, submit_form=submit_form, upload_form=upload_form, event=event, admin=admin) if request.method == 'POST': if ('code-csrf_token' in request.form and code_form.validate_on_submit()): try: for submission_file in sandbox_submission.files: if submission_file.is_editable: old_code = submission_file.get_code() submission_file.set_code( request.form[submission_file.name]) new_code = submission_file.get_code() diff = '\n'.join( difflib.unified_diff(old_code.splitlines(), new_code.splitlines())) similarity = difflib.SequenceMatcher( a=old_code, b=new_code).ratio() if app.config['TRACK_USER_INTERACTION']: add_user_interaction( db.session, interaction='save', user=flask_login.current_user, event=event, submission_file=submission_file, diff=diff, similarity=similarity) except Exception as e: return redirect_to_sandbox(event, u'Error: {}'.format(e)) return redirect_to_sandbox( event, 'You submission has been saved. You can safely comeback to ' 'your sandbox later.', is_error=False, category='File saved') elif request.files: upload_f_name = secure_filename(request.files['file'].filename) upload_name = upload_f_name.split('.')[0] # TODO: create a get_function upload_workflow_element = WorkflowElement.query.filter_by( name=upload_name, workflow=event.workflow).one_or_none() if upload_workflow_element is None: return redirect_to_sandbox( event, u'{} is not in the file list.'.format(upload_f_name)) # TODO: create a get_function submission_file = SubmissionFile.query.filter_by( submission=sandbox_submission, workflow_element=upload_workflow_element).one() if submission_file.is_editable: old_code = submission_file.get_code() tmp_f_name = os.path.join(tempfile.gettempdir(), upload_f_name) request.files['file'].save(tmp_f_name) file_length = os.stat(tmp_f_name).st_size if (upload_workflow_element.max_size is not None and file_length > upload_workflow_element.max_size): return redirect_to_sandbox( event, u'File is too big: {} exceeds max size {}'.format( file_length, upload_workflow_element.max_size)) if submission_file.is_editable: try: with open(tmp_f_name) as f: code = f.read() submission_file.set_code(code) except Exception as e: return redirect_to_sandbox(event, u'Error: {}'.format(e)) else: # non-editable files are not verified for now dst = os.path.join(sandbox_submission.path, upload_f_name) shutil.copy2(tmp_f_name, dst) logger.info(u'{} uploaded {} in {}'.format( flask_login.current_user.name, upload_f_name, event)) if submission_file.is_editable: new_code = submission_file.get_code() diff = '\n'.join( difflib.unified_diff(old_code.splitlines(), new_code.splitlines())) similarity = difflib.SequenceMatcher(a=old_code, b=new_code).ratio() if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='upload', user=flask_login.current_user, event=event, submission_file=submission_file, diff=diff, similarity=similarity) else: if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='upload', user=flask_login.current_user, event=event, submission_file=submission_file) return redirect(request.referrer) # TODO: handle different extensions for the same workflow element # ie: now we let upload eg external_data.bla, and only fail at # submission, without giving a message elif ('submit-csrf_token' in request.form and submit_form.validate_on_submit()): new_submission_name = request.form['submit-submission_name'] if not 4 < len(new_submission_name) < 20: return redirect_to_sandbox( event, 'Submission name should have length between 4 and ' '20 characters.') try: new_submission_name.encode('ascii') except Exception as e: return redirect_to_sandbox(event, u'Error: {}'.format(e)) try: new_submission = add_submission(db.session, event_name, event_team.team.name, new_submission_name, sandbox_submission.path) except DuplicateSubmissionError: return redirect_to_sandbox( event, u'Submission {} already exists. Please change the name.'. format(new_submission_name)) except MissingExtensionError as e: return redirect_to_sandbox(event, 'Missing extension') except TooEarlySubmissionError as e: return redirect_to_sandbox(event, str(e)) logger.info(u'{} submitted {} for {}.'.format( flask_login.current_user.name, new_submission.name, event_team)) if event.is_send_submitted_mails: admin_users = User.query.filter_by(access_level='admin') for admin in admin_users: subject = 'Submission {} sent for training'.format( new_submission.name) body = """A new submission have been submitted: event: {} user: {} submission: {} submission path: {} """.format(event_team.event.name, flask_login.current_user.name, new_submission.name, new_submission.path) send_mail(admin, subject, body) if app.config['TRACK_USER_INTERACTION']: add_user_interaction(db.session, interaction='submit', user=flask_login.current_user, event=event, submission=new_submission) return redirect_to_sandbox(event, u'{} submitted {} for {}'.format( flask_login.current_user.firstname, new_submission.name, event_team), is_error=False, category='Submission') admin = is_admin(db.session, event_name, flask_login.current_user.name) return render_template('sandbox.html', submission_names=sandbox_submission.f_names, code_form=code_form, submit_form=submit_form, upload_form=upload_form, event=event, admin=admin)