Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
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)
Beispiel #8
0
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'
    )
Beispiel #9
0
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)
Beispiel #10
0
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)
Beispiel #11
0
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
    )
Beispiel #12
0
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)