コード例 #1
0
    def post(self):
        contest_dict = contest.get_contest_dict_from_request(self.request)
        parsed_time = time.strptime(contest_dict['time'], "%H:%M")
        date_and_time = datetime.datetime(
            year=int(contest_dict["year"]),
            month=list(calendar.month_name).index(contest_dict["month"]),
            day=int(contest_dict["day"]),
            hour=parsed_time.tm_hour,
            minute=parsed_time.tm_min)
        timezone = pytz.timezone(contest_dict["time_zone"])
        date_and_time = timezone.localize(date_and_time)
        contest_dict["date_and_time"] = date_and_time

        contest_dict["full_name"] = contest_dict["full_name"].replace(
            '\n', ' ')

        cont = None
        contest_id = self.request.get("id")
        if contest_id:

            cont = contest.get_contest_by_id(contest_id)
            for prop in cont.properties():
                setattr(cont, prop, contest_dict[prop])
            if not cont:
                self.redirect('\error?message=No contest with given id')
                return
        else:
            contest_dict["full_name"] = cgi.escape(contest_dict["full_name"])
            contest_dict["short_name"] = cgi.escape(contest_dict["short_name"])
            contest_dict["info"] = cgi.escape(contest_dict["info"])
            cont = Contest(parent=contest.PARENT_KEY, **contest_dict)

        cont.put()

        self.redirect('/')
コード例 #2
0
ファイル: edit_contest.py プロジェクト: rizar/win-them-all
    def post(self):
        contest_dict = contest.get_contest_dict_from_request(self.request)
        parsed_time = time.strptime(contest_dict['time'], "%H:%M")
        date_and_time = datetime.datetime(year = int(contest_dict["year"]),
                                          month = list(calendar.month_name).index(contest_dict["month"]),
                                          day = int(contest_dict["day"]),
                                          hour = parsed_time.tm_hour,
                                          minute = parsed_time.tm_min)
        timezone = pytz.timezone(contest_dict["time_zone"])
        date_and_time = timezone.localize(date_and_time)
        contest_dict["date_and_time"] = date_and_time

        contest_dict["full_name"] = contest_dict["full_name"].replace('\n', ' ')

        cont = None
        contest_id = self.request.get("id")
        if contest_id:

            cont = contest.get_contest_by_id(contest_id)
            for prop in cont.properties():
                setattr(cont, prop, contest_dict[prop])
            if not cont:
                self.redirect('\error?message=No contest with given id')
                return
        else:
            contest_dict["full_name"] = cgi.escape(contest_dict["full_name"])
            contest_dict["short_name"] = cgi.escape(contest_dict["short_name"])
            contest_dict["info"] = cgi.escape(contest_dict["info"])
            cont = Contest(parent = contest.PARENT_KEY, **contest_dict)

        cont.put()

        self.redirect('/')
コード例 #3
0
 def check(self):
   contest = Contest(self.contestId)
   if contest.systemTest():
     users = contest.participants()
     channels = []
     for user in users:
       if self.toFilter.count(user) > 0:
         print "Will send to ... " + user 
         channels.append(fix(user) + 'SystemTest')
     print "System Test is Final"
     sender = NotificationSender('CF Contest %d, system test is over' % self.contestId, channels)
     print sender.send()
     return True
   return False
コード例 #4
0
 def check(self):
   contest = Contest(self.contestId)
   if contest.ratingChanges():
     users = contest.participants()
     channels = []
     for user in users:
       if self.toFilter.count(user) > 0:
         print "Will send to ... " + user
         channels.append(fix(user) + 'Rating')
     print "Ratings are out!"
     sender = NotificationSender('CF Contest %d, Ratings are updated!' % self.contestId, channels)
     print sender.send()
     return True
   return False
コード例 #5
0
 def check(self):
     contest = Contest(self.contestId)
     if contest.ratingChanges():
         users = contest.participants()
         channels = []
         for user in users:
             if self.toFilter.count(user) > 0:
                 print "Will send to ... " + user
                 channels.append(fix(user) + 'Rating')
         print "Ratings are out!"
         sender = NotificationSender(
             'CF Contest %d, Ratings are updated!' % self.contestId,
             channels)
         print sender.send()
         return True
     return False
コード例 #6
0
 def check(self):
     contest = Contest(self.contestId)
     if contest.systemTest():
         users = contest.participants()
         channels = []
         for user in users:
             if self.toFilter.count(user) > 0:
                 print "Will send to ... " + user
                 channels.append(fix(user) + 'SystemTest')
         print "System Test is Final"
         sender = NotificationSender(
             'CF Contest %d, system test is over' % self.contestId,
             channels)
         print sender.send()
         return True
     return False
コード例 #7
0
ファイル: atcoder.py プロジェクト: todokku/AtCoderChokuZen
def _get_upcoming_contest_info(upcoming_contests):
    ''' HACK: The codes depend on AtCoder Home page.
        contest_info contains below information:

        ignore       : http://www.timeanddate.com/worldclock/fixedtime.html?
                       iso=202xxxxxTxxxx&px=xxx
        contest date : 202x-xx-xx xx:xx:xx+0900
        contest url  : /contests/abbreviated_contest_name
        contest name : hogehoge
    '''
    from contest import Contest

    contest_info = upcoming_contests.find_all('a', limit=2)
    name, start_date, url = '', '', ''

    for index, link in enumerate(contest_info):
        if index == 0:
            start_date = _fix_contest_date_format(link.text)
        elif index == 1:
            name = link.text
            url = ATCODER_BASE_URL + link['href']

    contest = Contest(name=name, start_date=start_date, url=url)

    return contest
コード例 #8
0
ファイル: main.py プロジェクト: dmachb/eurovision-dataset
def get_contest(y, rounds):
    contest = Contest(y)
    for r in rounds:
        print('Scraping: Eurovision Song Contest {} {}'.format(y, r))
        contest = scraper.scrape_year(contest, r)

    contest = scraper.scrape_misc(contest)
    return contest
コード例 #9
0
ファイル: log2csv.py プロジェクト: kcs/SOTAnaplo
    def __init__(self, string, prev=None):
        """Initialize the activation from the string
        At least callsign, date, and sota reference are needed, other
        information is optional.
        If a previous activation is given then the callsign and date
        can be preserved from it, but new sota reference is mandatory.
        An asterisk instead of sota reference means a chase
        """
        self.previous = prev

        # start splitting the string into words
        w, pos, end = find_word(string)
        # callsign
        m = call.fullmatch(w)
        if m:
            self.callsign = w.upper()
            w, pos, end = find_word(string, end)
        elif prev:
            self.callsign = prev.callsign
        else:
            raise LogException("Error in activation definition, missing callsign", pos)
        # date
        m = date_reg.fullmatch(w)
        if m:
            try:
                self.date = date(int(m.group(1)), int(m.group(3)), int(m.group(4)))
            except ValueError:
                raise LogException("Error in activation definition, invalid date format", pos)
            w, pos, end = find_word(string, end)
        elif prev:
            self.date = prev.date
        else:
            raise LogException("Error in activation definition, missing date", pos)
        # sota reference is mandatory
        m = sota_ref.fullmatch(w)
        if m:
            self.ref = w.upper()
        elif w == '*':
            self.ref = ''
        else:
            raise LogException("Error in activation definition, invalid SOTA reference detected", pos)

        notes = string[end:].strip()

        m = contest.search(notes)
        if m:
            self.contest = Contest(m.group(1))
            notes = notes[:m.start()] + notes[m.end():]
        else:
            self.contest = None

        self.notes = notes
        self.qsos = []

        # TODO: other information
        self.wwff = None
        self.locator = None
コード例 #10
0
def add_contest(update, context):
    if update.message.from_user.username != 'maksim1744':
        update.message.reply_text('This option is not available for you')
        return

    context.bot_data.setdefault('contest', dict())

    for contest in context.args:
        if not re.fullmatch(r'[0-9]+', contest):
            update.message.reply_text('Contest must be an integer')
            break
        if contest in context.bot_data['contest']:
            continue
        context.bot_data['contest'][contest] = Contest(contest)
    ask_contest(update, context)
コード例 #11
0
def main():
    input_file_name = input(
        "Enter the path to the voting data spreadsheet (made by create_voter_spreadsheet.py): "
    )
    contest = Contest()
    contest.populate_from_spreadsheet(input_file_name)
    output_file_name_prefix = input(
        "Enter the prefix that the output spreadsheets will start with: ")
    num_winners = int(
        input("Enter the desired number of winners for the contest: "))
    contest.get_winners(num_winners, output_file_name_prefix)
コード例 #12
0
ファイル: show_contests.py プロジェクト: rizar/win-them-all
    def get(self):
        # initialize request time boundaries
        after_utc = self.request.get("after_utc")
        before_utc = self.request.get("before_utc")

        after_time = None
        if after_utc:
            after_time = int(after_utc) // 1000
        else:
            after_time = time.time()
            after_utc = int(after_time * 1000)

        before_time = None
        if before_utc:
            before_time = int(before_utc) // 1000
        else:
            before_time = time.time() + 86400 * 28
            before_utc = int(before_time * 1000)

        # make the database query
        query = Contest.all().ancestor(contest.PARENT_KEY)
        contests = list(
            query.filter("date_and_time >= ", datetime.datetime.fromtimestamp(after_time))
            .filter("date_and_time <= ", datetime.datetime.fromtimestamp(before_time))
            .order("date_and_time")
        )

        # make list of boxes containing contest and it's UTC timestamp
        boxes = [contest.Box(cont) for cont in contests]
        self.response.out.write(
            template.render(
                os.path.join("templates", "show_contests.html"),
                {"boxes": boxes, "after_utc": after_utc, "before_utc": before_utc},
                common.DEBUG,
            )
        )

        """unix_times = list()
コード例 #13
0
    def get(self):
        # initialize request time boundaries
        after_utc = self.request.get("after_utc")
        before_utc = self.request.get("before_utc")
        
        after_time = None
        if after_utc:
            after_time = int(after_utc) // 1000
        else:
            after_time = time.time()
            after_utc = int(after_time * 1000)

        before_time = None
        if before_utc:
            before_time = int(before_utc) // 1000
        else:
            before_time = time.time() + 86400 * 28
            before_utc = int(before_time * 1000)

        # make the database query
        query = Contest.all().ancestor(contest.PARENT_KEY)
        contests = list(query.filter("date_and_time >= ", 
                                     datetime.datetime.fromtimestamp(after_time))
                             .filter("date_and_time <= ", 
                                     datetime.datetime.fromtimestamp(before_time))
                             .order("date_and_time"))

        #make list of boxes containing contest and it's UTC timestamp
        boxes = [contest.Box(cont) for cont in contests]
        self.response.out.write(template.render(os.path.join("templates", "show_contests.html"), 
                                                {"boxes" : boxes,
                                                "after_utc" : after_utc,
                                                "before_utc" : before_utc},
                                                common.DEBUG))

        """unix_times = list()
コード例 #14
0
def minerva_pvalue(sample, popsize, alpha, Vw, Vl, null_margin):
    """Computes the pvalue for a one-round minerva audit with the passed values.
    Uses an adapted version of Grant's Minerva code in r2b2 (adapted for null margins).

    Parameters:
        sample : list of 1's (vote for winner) and 0's (vote for loser)
        popsize : total ballots in stratum
        alpha : risk limit
        Vw : reported votes for winner in stratum
        Vl : reported votes for loser in stratum
        null_margin : the margin in votes assumed under the null

    Returns:
        float : the minerva pvalue
    """
    contest = Contest(popsize, {
        'A': Vw,
        'B': Vl
    }, 1, ['A'], ContestType.PLURALITY)
    audit = Minerva_S(alpha, 1.0, contest, null_margin)

    n = len(sample)

    audit.rounds.append(n)
    audit.current_dist_reported()
    audit.current_dist_null()

    k = np.sum(sample == 1)
    x = (popsize + null_margin) / 2

    if x < k or popsize - x < np.sum(sample == 0):
        return 0

    pvalue = audit.stopping_condition(k)['pvalue']

    return min(pvalue)
コード例 #15
0
from contest import Contest

contest = Contest(675)

print contest.systemTest()
print contest.ratingChanges()

res = contest.participants()

for x in res:
  print x
コード例 #16
0
ファイル: main.py プロジェクト: ishayrabi/multi-contests-game
                    new_arrangement[contest].append({"type": player_tuple["type"], "amount": perm[contest]})
                new_arrangements.append(new_arrangement)
        arrangements = new_arrangements

games = list()

for i in range(len(arrangements)):
    arrangement = arrangements[i]
    # We now needs to create contests.
    # Each arrangement is a game

    game = dict()
    for contest_id in arrangement:

        players = arrangement[contest_id]
        game[contest_id] = Contest(prizes[contest_id])
        game[contest_id].add_players(players)
        game[contest_id].calculate_inner_equilibrium()
    games.append(game)

for game_id in range(len(games)):
    print game_id
    for contest_id in games[game_id]:
        print games[game_id][contest_id]
        print games[game_id][contest_id]._contest_result

print "\n"
neighbors_matrix = []

for game_id in range(len(games)):
    neighbors_matrix.append([])
コード例 #17
0
    def __init__(self, string, prev=None):
        """Initialize the activation from the string
        At least callsign, date, and sota reference are needed, other
        information is optional.
        If a previous activation is given then the callsign and date
        can be preserved from it, but new sota reference is mandatory.
        An asterisk instead of sota reference means a chase
        """
        self.previous = prev

        # start splitting the string into words
        w, pos, end = find_word(string)
        # callsign
        m = call.fullmatch(w)
        if m:
            self.callsign = w.upper()
            w, pos, end = find_word(string, end)
        elif prev:
            self.callsign = prev.callsign
        else:
            raise LogException(
                "Error in activation definition, missing callsign", pos)
        # date
        m = date_reg.fullmatch(w)
        if m:
            try:
                self.date = date(int(m.group(1)), int(m.group(3)),
                                 int(m.group(4)))
            except ValueError:
                raise LogException(
                    "Error in activation definition, invalid date format", pos)
            w, pos, end = find_word(string, end)
        elif prev:
            self.date = prev.date
        else:
            raise LogException("Error in activation definition, missing date",
                               pos)
        # sota reference is mandatory
        m = sota_ref.fullmatch(w)
        if m:
            self.ref = w.upper()
        elif w == '*':
            self.ref = ''
        else:
            raise LogException(
                "Error in activation definition, invalid SOTA reference detected",
                pos)

        notes = string[end:].strip()

        m = contest.search(notes)
        if m:
            self.contest = Contest(m.group(1))
            notes = notes[:m.start()] + notes[m.end():]
        else:
            self.contest = None

        self.notes = notes
        self.qsos = []

        # TODO: other information
        self.wwff = None
        self.locator = None
コード例 #18
0
class Activation:
    """Class holding information about an activation or a chase
    Activations contain information about the date and place of activation,
    callsign used and all qsos.
    Also a link to the previous activation is stored
    In a chase multiple qsos can be merged from a single day.
    """
    def __init__(self, string, prev=None):
        """Initialize the activation from the string
        At least callsign, date, and sota reference are needed, other
        information is optional.
        If a previous activation is given then the callsign and date
        can be preserved from it, but new sota reference is mandatory.
        An asterisk instead of sota reference means a chase
        """
        self.previous = prev

        # start splitting the string into words
        w, pos, end = find_word(string)
        # callsign
        m = call.fullmatch(w)
        if m:
            self.callsign = w.upper()
            w, pos, end = find_word(string, end)
        elif prev:
            self.callsign = prev.callsign
        else:
            raise LogException(
                "Error in activation definition, missing callsign", pos)
        # date
        m = date_reg.fullmatch(w)
        if m:
            try:
                self.date = date(int(m.group(1)), int(m.group(3)),
                                 int(m.group(4)))
            except ValueError:
                raise LogException(
                    "Error in activation definition, invalid date format", pos)
            w, pos, end = find_word(string, end)
        elif prev:
            self.date = prev.date
        else:
            raise LogException("Error in activation definition, missing date",
                               pos)
        # sota reference is mandatory
        m = sota_ref.fullmatch(w)
        if m:
            self.ref = w.upper()
        elif w == '*':
            self.ref = ''
        else:
            raise LogException(
                "Error in activation definition, invalid SOTA reference detected",
                pos)

        notes = string[end:].strip()

        m = contest.search(notes)
        if m:
            self.contest = Contest(m.group(1))
            notes = notes[:m.start()] + notes[m.end():]
        else:
            self.contest = None

        self.notes = notes
        self.qsos = []

        # TODO: other information
        self.wwff = None
        self.locator = None

    def add_qso(self, string):
        """Add a QSO to list of qsos
        Consider the last qso as the previous one for the new qso
        """
        prev_qso = self.qsos[-1] if self.qsos else None
        if self.contest:
            self.qsos.append(QSO(string, prev_qso, self.contest.exchange))
        else:
            self.qsos.append(QSO(string, prev_qso))

    def print_qsos(self,
                   format='SOTA_v2',
                   config=None,
                   handle=None,
                   qsl_info=None):
        if self.previous:
            self.previous.print_qsos(format, config, handle, qsl_info)

        # TODO: trace, remove it from final code
        #print("Processing {} from {} with callsign {}".format(
        #    "chase" if not self.ref else "activation of {}".format(self.ref),
        #   self.date.strftime("%Y-%m-%d"), self.callsign))

        # TODO: only SOTA_v2 is understood as of now
        if format == 'SOTA_v2':
            sota_line = [
                'v2', self.callsign, self.ref,
                self.date.strftime("%d/%m/%Y")
            ] + [''] * 6
            for qso in self.qsos:
                sota_line[4] = '{:02}{:02}'.format(qso.time[0], qso.time[1])
                sota_line[5] = qso.freq
                sota_line[6] = qso.mode
                sota_line[7] = qso.callsign
                sota_line[8] = getattr(qso, 'ref', '')
                sota_line[9] = quote_text(qso.notes)
                #sota_line[9] = quote_text(' '.join((qso.sent, qso.rcvd, qso.notes)))
                print(','.join(sota_line), file=handle)
        # contest format: if a contest was specified for an activation
        # use the contest rules to determine the output format
        elif format == 'contest' and self.contest:
            self.contest.configure(self, config)
            for qso in self.qsos:
                self.contest.add_qso(self.callsign, self.date, qso)
            print(self.contest, file=handle)
        # qsl status format:
        # group callsigns by country and add qsl marker:
        #  * - sent, but not confirmed yet
        #  ** - confirmed
        # an additional config parameter is a dictionary with previous qsl
        # information
        elif format == 'qsl':
            if not qsl_info:
                qsl_info = qslinfo.QSL()
                print_stat = True
            else:
                print_stat = False

            qsl_info.add_qsos(self.qsos, self.date)

            if print_stat:
                qsl_info.print_stat(handle)

        else:
            raise ValueError("Unrecognized output format")
コード例 #19
0
    'B': 49500
}, 1, ['A'], ContestType.PLURALITY)

stratum2 = Contest(7500+1500, {
    'A': 7500,
    'B': 1500
}, 1, ['A'], ContestType.PLURALITY)

overall_contest = Contest(45500+49500+7500+1500, {
    'A': 45500+7500,
    'B': 49500+1500
}, 1, ['A'], ContestType.PLURALITY)
"""

stratum1 = Contest(100000, {
    'A': 60000,
    'B': 40000
}, 1, ['A'], ContestType.PLURALITY)

stratum2 = Contest(50000, {
    'A': 32000,
    'B': 18000
}, 1, ['A'], ContestType.PLURALITY)

overall_contest = Contest(100000+50000, {
    'A': 32000+60000,
    'B': 18000+40000
}, 1, ['A'], ContestType.PLURALITY)


strata = [stratum1, stratum2]
コード例 #20
0
        i = 1
        for stratum in self.strata:
            stratum_lambda = stratum.contest_ballots / self.overall_contest.contest_ballots
            print("stratum " + str(i) + " lambda value: " +
                  str(stratum_lambda))
            lambda_.append(stratum_lambda)
            i += 1

        print("sum of lambda values: " + str(sum(lambda_)))
        return lambda_


# TESTING

stratum1 = Contest(45500 + 49500, {
    'A': 49500,
    'B': 45500
}, 1, ['A'], ContestType.PLURALITY)

stratum2 = Contest(9000, {
    'A': 7500,
    'B': 1500
}, 1, ['A'], ContestType.PLURALITY)

overall_contest = Contest(45500 + 49500 + 9000, {
    'A': 45500 + 7500,
    'B': 49500 + 1500
}, 1, ['A'], ContestType.PLURALITY)
strata = []
strata.append(stratum1)
strata.append(stratum2)
コード例 #21
0
ファイル: log2csv.py プロジェクト: kcs/SOTAnaplo
class Activation:
    """Class holding information about an activation or a chase
    Activations contain information about the date and place of activation,
    callsign used and all qsos.
    Also a link to the previous activation is stored
    In a chase multiple qsos can be merged from a single day.
    """

    def __init__(self, string, prev=None):
        """Initialize the activation from the string
        At least callsign, date, and sota reference are needed, other
        information is optional.
        If a previous activation is given then the callsign and date
        can be preserved from it, but new sota reference is mandatory.
        An asterisk instead of sota reference means a chase
        """
        self.previous = prev

        # start splitting the string into words
        w, pos, end = find_word(string)
        # callsign
        m = call.fullmatch(w)
        if m:
            self.callsign = w.upper()
            w, pos, end = find_word(string, end)
        elif prev:
            self.callsign = prev.callsign
        else:
            raise LogException("Error in activation definition, missing callsign", pos)
        # date
        m = date_reg.fullmatch(w)
        if m:
            try:
                self.date = date(int(m.group(1)), int(m.group(3)), int(m.group(4)))
            except ValueError:
                raise LogException("Error in activation definition, invalid date format", pos)
            w, pos, end = find_word(string, end)
        elif prev:
            self.date = prev.date
        else:
            raise LogException("Error in activation definition, missing date", pos)
        # sota reference is mandatory
        m = sota_ref.fullmatch(w)
        if m:
            self.ref = w.upper()
        elif w == '*':
            self.ref = ''
        else:
            raise LogException("Error in activation definition, invalid SOTA reference detected", pos)

        notes = string[end:].strip()

        m = contest.search(notes)
        if m:
            self.contest = Contest(m.group(1))
            notes = notes[:m.start()] + notes[m.end():]
        else:
            self.contest = None

        self.notes = notes
        self.qsos = []

        # TODO: other information
        self.wwff = None
        self.locator = None


    def add_qso(self, string):
        """Add a QSO to list of qsos
        Consider the last qso as the previous one for the new qso
        """
        prev_qso = self.qsos[-1] if self.qsos else None
        if self.contest:
            self.qsos.append(QSO(string, prev_qso, self.contest.exchange))
        else:
            self.qsos.append(QSO(string, prev_qso))


    def print_qsos(self, format='SOTA_v2', config=None, handle=None, qsl_info=None):
        if self.previous:
            self.previous.print_qsos(format, config, handle, qsl_info)

        # TODO: trace, remove it from final code
        #print("Processing {} from {} with callsign {}".format(
        #    "chase" if not self.ref else "activation of {}".format(self.ref),
        #   self.date.strftime("%Y-%m-%d"), self.callsign))

        # TODO: only SOTA_v2 is understood as of now
        if format == 'SOTA_v2':
            sota_line = ['v2', self.callsign, self.ref, self.date.strftime("%d/%m/%Y")] + [''] * 6
            for qso in self.qsos:
                sota_line[4] = '{:02}{:02}'.format(qso.time[0], qso.time[1])
                sota_line[5] = qso.freq
                sota_line[6] = qso.mode
                sota_line[7] = qso.callsign
                sota_line[8] = getattr(qso, 'ref', '')
                sota_line[9] = quote_text(qso.notes)
                #sota_line[9] = quote_text(' '.join((qso.sent, qso.rcvd, qso.notes)))
                print(','.join(sota_line), file=handle)
        # contest format: if a contest was specified for an activation
        # use the contest rules to determine the output format
        elif format == 'contest' and self.contest:
            self.contest.configure(self, config)
            for qso in self.qsos:
                self.contest.add_qso(self.callsign, self.date, qso)
            print(self.contest, file=handle)
        # qsl status format:
        # group callsigns by country and add qsl marker:
        #  * - sent, but not confirmed yet
        #  ** - confirmed
        # an additional config parameter is a dictionary with previous qsl
        # information
        elif format == 'qsl':
            if not qsl_info:
                qsl_info = qslinfo.QSL()
                print_stat = True
            else:
                print_stat = False

            qsl_info.add_qsos(self.qsos, self.date)

            if print_stat:
                qsl_info.print_stat(handle)

        else:
            raise ValueError("Unrecognized output format")
コード例 #22
0
        seconds = contest_cfg['duration'] % 60
        minutes = contest_cfg['duration'] / 60 % 60
        hours = contest_cfg['duration'] / 60 / 60 % 60

        logger.debug("Duration: %02d:%02d:%02d" % (hours, minutes, seconds))
        logger.debug("Problems: " + str(contest_cfg['prob_ids']))
        logger.debug("Penalty: %d points / wrong submission" %
                     contest_cfg['penalty'])

    problems = {
        prob_id: Problem(prob_id, options.contest_dir, logger)
        for prob_id in contest_cfg['prob_ids']
    }
    contest = Contest(options.delay, contest_cfg['duration'],
                      options.minutes_in, contest_cfg['prob_ids'],
                      contest_cfg['penalty'], logger)
    judge = Judge(contest, problems, options.contest_dir, options.num_judges,
                  logger)

    application = web.Application(
        [
            (r'/', IndexHandler),
            (r'/index.html', IndexHandler),
            (r'/auth/login', AuthLoginHandler),
            (r'/auth/logout', AuthLogoutHandler),
            (r'/api/v1/admin/(.*)', AdminHandler),
            (r'/api/v1/log/(.*)', LogHandler),
            (r'/api/v1/metadata', MetadataHandler),
            (r'/api/v1/updates', UpdatesHandler),
            (r'/api/v1/submit/(.*)/solution', SubmitSolutionHandler),