Example #1
0
async def update_status(domain_id: str, doc_type: int, tid: objectid.ObjectId,
                        uid: int, rid: objectid.ObjectId,
                        pid: document.convert_doc_id, accept: bool,
                        score: int):
    """This method returns None when the modification has been superseded by a parallel operation."""
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    tdoc = await document.get(domain_id, doc_type, tid)
    tsdoc = await document.rev_push_status(domain_id, tdoc['doc_type'],
                                           tdoc['doc_id'], uid, 'journal', {
                                               'rid': rid,
                                               'pid': pid,
                                               'accept': accept,
                                               'score': score
                                           })
    if 'attend' not in tsdoc or not tsdoc['attend']:
        if tdoc['doc_type'] == document.TYPE_CONTEST:
            raise error.ContestNotAttendedError(domain_id, tid, uid)
        elif tdoc['doc_type'] == document.TYPE_HOMEWORK:
            raise error.HomeworkNotAttendedError(domain_id, tid, uid)
        else:
            raise error.InvalidArgumentError('doc_type')

    journal = _get_status_journal(tsdoc)
    stats = RULES[tdoc['rule']].stat_func(tdoc, journal)
    tsdoc = await document.rev_set_status(domain_id,
                                          tdoc['doc_type'],
                                          tid,
                                          uid,
                                          tsdoc['rev'],
                                          journal=journal,
                                          **stats)
    return tsdoc
Example #2
0
 async def post(self, *, ctype: str, **kwargs):
     if ctype == 'homework':
         await self._post_homework()
     elif ctype == 'contest':
         raise error.InvalidArgumentError('ctype')
         # await self._post_contest()
     else:
         raise error.InvalidArgumentError('ctype')
Example #3
0
 async def get(self, *, ctype: str):
     if ctype == 'homework':
         await self._get_homework()
     elif ctype == 'contest':
         await self._get_contest()
     else:
         raise error.InvalidArgumentError('ctype')
Example #4
0
async def get(domain_id: str, doc_type: int, tid: objectid.ObjectId):
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    tdoc = await document.get(domain_id, doc_type, tid)
    if not tdoc:
        raise error.DocumentNotFoundError(domain_id, doc_type, tid)
    return tdoc
Example #5
0
async def edit(domain_id: str, doc_type: int, tid: objectid.ObjectId,
               **kwargs):
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    if 'title' in kwargs:
        validator.check_title(kwargs['title'])
    if 'content' in kwargs:
        validator.check_content(kwargs['content'])
    if 'rule' in kwargs:
        if doc_type == document.TYPE_CONTEST:
            if kwargs['rule'] not in constant.contest.CONTEST_RULES:
                raise error.ValidationError('rule')
        elif doc_type == document.TYPE_HOMEWORK:
            if kwargs['rule'] not in constant.contest.HOMEWORK_RULES:
                raise error.ValidationError('rule')
    if 'begin_at' in kwargs and 'end_at' in kwargs:
        if kwargs['begin_at'] >= kwargs['end_at']:
            raise error.ValidationError('begin_at', 'end_at')
    if 'penalty_since' in kwargs:
        if 'begin_at' in kwargs and kwargs['penalty_since'] < kwargs[
                'begin_at']:
            raise error.ValidationError('penalty_since', 'begin_at')
        if 'end_at' in kwargs and kwargs['penalty_since'] > kwargs['end_at']:
            raise error.ValidationError('penalty_since', 'end_at')
    return await document.set(domain_id, doc_type, tid, **kwargs)
Example #6
0
async def add(domain_id: str, doc_type: int,
              title: str, content: str, owner_uid: int, rule: int,
              begin_at: lambda i: datetime.datetime.utcfromtimestamp(int(i)),
              end_at: lambda i: datetime.datetime.utcfromtimestamp(int(i)),
              pids=[], **kwargs):
  if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
    raise error.InvalidArgumentError('doc_type')
  validator.check_title(title)
  validator.check_content(content)

  if doc_type == document.TYPE_CONTEST:
    if rule not in constant.contest.CONTEST_RULES:
      raise error.ValidationError('rule')
  elif doc_type == document.TYPE_HOMEWORK:
    if rule not in constant.contest.HOMEWORK_RULES:
      raise error.ValidationError('rule')

  if begin_at >= end_at:
    raise error.ValidationError('begin_at', 'end_at')

  if doc_type == document.TYPE_HOMEWORK:
    if 'penalty_since' not in kwargs:
      raise error.ValidationError('penalty_since')
    if kwargs['penalty_since'] < begin_at:
      raise error.ValidationError('penalty_since', 'begin_at')
    if kwargs['penalty_since'] > end_at:
      raise error.ValidationError('penalty_since', 'end_at')
  # TODO(twd2): should we check problem existance here?
  return await document.add(domain_id, content, owner_uid, doc_type,
                            title=title, rule=rule,
                            begin_at=begin_at, end_at=end_at, pids=pids, attend=0,
                            **kwargs)
Example #7
0
    async def post(self,
                   *,
                   code: str,
                   uname: str,
                   password: str,
                   verify_password: str,
                   school_id: str = ''):
        doc = await token.get(code, token.TYPE_REGISTRATION)
        sid = None
        if not doc:
            raise error.InvalidTokenError(token.TYPE_REGISTRATION, code)
        if password != verify_password:
            raise error.VerifyPasswordError()
        if school_id.strip():
            if not school_id.isnumeric():
                raise error.InvalidArgumentError('school_id')
            sid = school_id.strip()

        uid = await system.inc_user_counter()
        await user.add(uid, uname, password, doc['mail'], self.remote_ip)
        if sid:
            await user.set_by_uid(uid, ojcId=sid)
        await token.delete(code, token.TYPE_REGISTRATION)
        await self.update_session(new_saved=False, uid=uid)
        self.json_or_redirect(self.reverse_url('domain_main'))
Example #8
0
 async def post(self, *, ctype: str, tid: objectid.ObjectId,
                pid: document.convert_doc_id, lang: str,
                code: objectid.ObjectId):
     doc_type = constant.contest.CTYPE_TO_DOCTYPE[ctype]
     # TODO(iceboy): rate limit base on ip.
     tdoc, pdoc = await asyncio.gather(
         contest.get(self.domain_id, doc_type, tid),
         problem.get(self.domain_id, pid))
     tsdoc = await contest.get_status(self.domain_id, doc_type,
                                      tdoc['doc_id'], self.user['_id'])
     if not tsdoc or tsdoc.get('attend') != 1:
         if ctype == 'contest':
             raise error.ContestNotAttendedError(tdoc['doc_id'])
         elif ctype == 'homework':
             raise error.HomeworkNotAttendedError(tdoc['doc_id'])
         else:
             raise error.InvalidArgumentError('ctype')
     if not self.is_ongoing(tdoc):
         if ctype == 'contest':
             raise error.ContestNotLiveError(tdoc['doc_id'])
         elif ctype == 'homework':
             raise error.HomeworkNotLiveError(tdoc['doc_id'])
         else:
             raise error.InvalidArgumentError('ctype')
     if pid not in tdoc['pids']:
         raise error.ProblemNotFoundError(self.domain_id, pid,
                                          tdoc['doc_id'])
     # TODO(tc-imba): only constant.record.CODE_TYPE_TAR is supported now
     rid = await record.add(self.domain_id,
                            pdoc['doc_id'],
                            constant.record.TYPE_SUBMISSION,
                            self.user['_id'],
                            lang,
                            code,
                            tid=tdoc['doc_id'],
                            hidden=False,
                            code_type=constant.record.CODE_TYPE_TAR)
     await contest.update_status(self.domain_id, tdoc['doc_id'],
                                 self.user['_id'], rid, pdoc['doc_id'],
                                 False, 0)
     if not self.can_show_record(tdoc):
         self.json_or_redirect(
             self.reverse_url('contest_detail',
                              ctype=ctype,
                              tid=tdoc['doc_id']))
     else:
         self.json_or_redirect(self.reverse_url('record_detail', rid=rid))
Example #9
0
 async def get(self, *, ctype: str, tid: objectid.ObjectId,
               pid: document.convert_doc_id):
     doc_type = constant.contest.CTYPE_TO_DOCTYPE[ctype]
     uid = self.user['_id'] if self.has_priv(
         builtin.PRIV_USER_PROFILE) else None
     tdoc, pdoc = await asyncio.gather(
         contest.get(self.domain_id, doc_type, tid),
         problem.get(self.domain_id, pid, uid))
     tsdoc, udoc = await asyncio.gather(
         contest.get_status(self.domain_id, doc_type, tdoc['doc_id'],
                            self.user['_id']),
         user.get_by_uid(tdoc['owner_uid']))
     attended = tsdoc and tsdoc.get('attend') == 1
     if not self.is_finished(tdoc):
         if not attended:
             if ctype == 'contest':
                 raise error.ContestNotAttendedError(tdoc['doc_id'])
             elif ctype == 'homework':
                 raise error.HomeworkNotAttendedError(tdoc['doc_id'])
             else:
                 raise error.InvalidArgumentError('ctype')
         if not self.is_ongoing(tdoc):
             if ctype == 'contest':
                 raise error.ContestNotLiveError(tdoc['doc_id'])
             elif ctype == 'homework':
                 raise error.HomeworkNotLiveError(tdoc['doc_id'])
             else:
                 raise error.InvalidArgumentError('ctype')
     if pid not in tdoc['pids']:
         raise error.ProblemNotFoundError(self.domain_id, pid,
                                          tdoc['doc_id'])
     path_components = self.build_path(
         (self.translate('page.contest_main.{0}.title'.format(ctype)),
          self.reverse_url('contest_main', ctype=ctype)),
         (tdoc['title'],
          self.reverse_url('contest_detail', ctype=ctype, tid=tid)),
         (pdoc['title'], None))
     self.render('problem_detail.html',
                 tdoc=tdoc,
                 pdoc=pdoc,
                 tsdoc=tsdoc,
                 udoc=udoc,
                 attended=attended,
                 page_title=pdoc['title'],
                 path_components=path_components)
Example #10
0
 def wrapped(self, **kwargs):
     for key, value in kwargs.items():
         try:
             kwargs[key] = func.__annotations__[key](value)
         except KeyError:
             raise error.UnknownArgumentError(key)
         except Exception:
             raise error.InvalidArgumentError(key)
     return func(self, **kwargs)
Example #11
0
def get_multi(domain_id: str, doc_type: int, fields=None, **kwargs):
    # TODO(twd2): projection.
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    return document.get_multi(domain_id=domain_id,
                              doc_type=doc_type,
                              fields=fields,
                              **kwargs) \
                   .sort([('doc_id', -1)])
Example #12
0
async def get_dict_status(domain_id, uid, doc_type, tids, *, fields=None):
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    result = dict()
    async for tsdoc in get_multi_status(domain_id=domain_id,
                                        uid=uid,
                                        doc_type=doc_type,
                                        doc_id={'$in': list(set(tids))},
                                        fields=fields):
        result[tsdoc['doc_id']] = tsdoc
    return result
Example #13
0
async def get_status(domain_id: str,
                     doc_type: int,
                     tid: objectid.ObjectId,
                     uid: int,
                     fields=None):
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    return await document.get_status(domain_id,
                                     doc_type,
                                     doc_id=tid,
                                     uid=uid,
                                     fields=fields)
Example #14
0
async def get_and_list_status(domain_id: str, doc_type: int, tid: objectid.ObjectId, fields=None):
  # TODO(iceboy): projection, pagination.
  if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
    raise error.InvalidArgumentError('doc_type')
  tdoc = await get(domain_id, doc_type, tid)
  tsdocs = await document.get_multi_status(domain_id=domain_id,
                                           doc_type=doc_type,
                                           doc_id=tdoc['doc_id'],
                                           fields=fields) \
                         .sort(RULES[tdoc['rule']].status_sort) \
                         .to_list()
  return tdoc, tsdocs
Example #15
0
async def attend(domain_id: str, doc_type: int, tid: objectid.ObjectId, uid: int):
  # TODO(iceboy): check time.
  if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
    raise error.InvalidArgumentError('doc_type')
  try:
    await document.capped_inc_status(domain_id, doc_type, tid,
                                     uid, 'attend', 1, 0, 1)
  except errors.DuplicateKeyError:
    if doc_type == document.TYPE_CONTEST:
      raise error.ContestAlreadyAttendedError(domain_id, tid, uid) from None
    elif doc_type == document.TYPE_HOMEWORK:
      raise error.HomeworkAlreadyAttendedError(domain_id, tid, uid) from None
  return await document.inc(domain_id, doc_type, tid, 'attend', 1)
Example #16
0
 async def get_scoreboard(self, doc_type: int, tid: objectid.ObjectId, is_export: bool=False):
   if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
     raise error.InvalidArgumentError('doc_type')
   tdoc, tsdocs = await get_and_list_status(self.domain_id, doc_type, tid)
   if not self.can_show_scoreboard(tdoc):
     if doc_type == document.TYPE_CONTEST:
       raise error.ContestScoreboardHiddenError(self.domain_id, tid)
     elif doc_type == document.TYPE_HOMEWORK:
       raise error.HomeworkScoreboardHiddenError(self.domain_id, tid)
   udict, dudict, pdict = await asyncio.gather(
       user.get_dict([tsdoc['uid'] for tsdoc in tsdocs]),
       domain.get_dict_user_by_uid(self.domain_id, [tsdoc['uid'] for tsdoc in tsdocs]),
       problem.get_dict(self.domain_id, tdoc['pids']))
   ranked_tsdocs = RULES[tdoc['rule']].rank_func(tsdocs)
   rows = RULES[tdoc['rule']].scoreboard_func(is_export, self.translate, tdoc,
                                                      ranked_tsdocs, udict, dudict, pdict)
   return tdoc, rows, udict
Example #17
0
async def recalc_status(domain_id: str, doc_type: int, tid: objectid.ObjectId):
  if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
    raise error.InvalidArgumentError('doc_type')
  tdoc = await document.get(domain_id, doc_type, tid)
  async with document.get_multi_status(domain_id=domain_id,
                                       doc_type=doc_type,
                                       doc_id=tdoc['doc_id']) as tsdocs:
    async for tsdoc in tsdocs:
      if 'journal' not in tsdoc or not tsdoc['journal']:
        continue
      journal = _get_status_journal(tsdoc)
      stat_func = RULES[tdoc['rule']].stat_func
      if asyncio.iscoroutinefunction(stat_func):
        stats = await stat_func(tdoc, journal)
      else:
        stats = RULES[tdoc['rule']].stat_func(tdoc, journal)
      await document.rev_set_status(domain_id, doc_type, tid, tsdoc['uid'], tsdoc['rev'],
                                    return_doc=False, journal=journal, **stats)
Example #18
0
 async def get(self, *, start: str='', uid_or_name: str='', pid: str='', tid: str='', status: str=''):
   if not self.has_priv(builtin.PRIV_VIEW_JUDGE_STATISTICS):
     start = ''
   if start:
     try:
       start = objectid.ObjectId(start)
     except Exception:
       raise error.InvalidArgumentError('start')
   else:
     start = None
   query = await self.get_filter_query(uid_or_name, pid, tid, status)
   # TODO(iceboy): projection, pagination.
   rdocs = await record.get_all_multi(**query, end_id=start,
     get_hidden=self.has_priv(builtin.PRIV_VIEW_HIDDEN_RECORD)).sort([('_id', -1)]).limit(50).to_list()
   # TODO(iceboy): projection.
   udict, dudict, pdict = await asyncio.gather(
       user.get_dict(rdoc['uid'] for rdoc in rdocs),
       domain.get_dict_user_by_uid(domain_id=self.domain_id, uids=(rdoc['uid'] for rdoc in rdocs)),
       problem.get_dict_multi_domain((rdoc['domain_id'], rdoc['pid']) for rdoc in rdocs))
   # statistics
   statistics = None
   if self.has_priv(builtin.PRIV_VIEW_JUDGE_STATISTICS):
     ts = calendar.timegm(datetime.datetime.utcnow().utctimetuple())
     day_count, week_count, month_count, year_count, rcount = await asyncio.gather(
         record.get_count(objectid.ObjectId(
             struct.pack('>i', ts - 24 * 3600) + struct.pack('b', -1) * 8)),
         record.get_count(objectid.ObjectId(
             struct.pack('>i', ts - 7 * 24 * 3600) + struct.pack('b', -1) * 8)),
         record.get_count(objectid.ObjectId(
             struct.pack('>i', ts - 30 * 24 * 3600) + struct.pack('b', -1) * 8)),
         record.get_count(objectid.ObjectId(
             struct.pack('>i', ts - int(365.2425 * 24 * 3600)) + struct.pack('b', -1) * 8)),
         record.get_count())
     statistics = {'day': day_count, 'week': week_count, 'month': month_count,
                   'year': year_count, 'total': rcount}
   url_prefix = '/d/{}'.format(urllib.parse.quote(self.domain_id))
   query_string = urllib.parse.urlencode(
     [('uid_or_name', uid_or_name), ('pid', pid), ('tid', tid)])
   self.render(
       'record_main.html', rdocs=rdocs, udict=udict, dudict=dudict, pdict=pdict,
       statistics=statistics, filter_uid_or_name=uid_or_name, filter_pid=pid, filter_status=status, filter_tid=tid,
       socket_url=url_prefix + '/records-conn?' + query_string, # FIXME(twd2): magic
       query_string=query_string)
Example #19
0
def get_multi_status(doc_type: int, *, fields=None, **kwargs):
    if doc_type not in [document.TYPE_CONTEST, document.TYPE_HOMEWORK]:
        raise error.InvalidArgumentError('doc_type')
    return document.get_multi_status(doc_type=doc_type,
                                     fields=fields,
                                     **kwargs)
Example #20
0
 async def get(self, *, ctype: str, tid: objectid.ObjectId,
               pid: document.convert_doc_id):
     doc_type = constant.contest.CTYPE_TO_DOCTYPE[ctype]
     uid = self.user['_id'] if self.has_priv(
         builtin.PRIV_USER_PROFILE) else None
     tdoc, pdoc = await asyncio.gather(
         contest.get(self.domain_id, doc_type, tid),
         problem.get(self.domain_id, pid, uid))
     tsdoc, udoc = await asyncio.gather(
         contest.get_status(self.domain_id, doc_type, tdoc['doc_id'],
                            self.user['_id']),
         user.get_by_uid(tdoc['owner_uid']))
     attended = tsdoc and tsdoc.get('attend') == 1
     if not attended:
         if ctype == 'contest':
             raise error.ContestNotAttendedError(tdoc['doc_id'])
         elif ctype == 'homework':
             raise error.HomeworkNotAttendedError(tdoc['doc_id'])
         else:
             raise error.InvalidArgumentError('ctype')
     if not self.is_ongoing(tdoc):
         if ctype == 'contest':
             raise error.ContestNotLiveError(tdoc['doc_id'])
         elif ctype == 'homework':
             raise error.HomeworkNotLiveError(tdoc['doc_id'])
         else:
             raise error.InvalidArgumentError('ctype')
     if pid not in tdoc['pids']:
         raise error.ProblemNotFoundError(self.domain_id, pid,
                                          tdoc['doc_id'])
     if self.can_show_record(tdoc):
         rdocs = await record.get_user_in_problem_multi(uid, self.domain_id, pdoc['doc_id'], get_hidden=True) \
           .sort([('_id', -1)]) \
           .limit(10) \
           .to_list()
     else:
         rdocs = []
     if not self.prefer_json:
         path_components = self.build_path(
             (self.translate('page.contest_main.{0}.title'.format(ctype)),
              self.reverse_url('contest_main', ctype=ctype)),
             (tdoc['title'],
              self.reverse_url('contest_detail', ctype=ctype, tid=tid)),
             (pdoc['title'],
              self.reverse_url(
                  'contest_detail_problem', ctype=ctype, tid=tid, pid=pid)),
             (self.translate('page.contest_detail_problem_submit.{0}.title'.
                             format(ctype)), None))
         languages = filter_language(pdoc.get('languages') or [])
         default_lang = len(languages) and list(languages.keys())[0] or ''
         self.render('problem_submit.html',
                     tdoc=tdoc,
                     pdoc=pdoc,
                     rdocs=rdocs,
                     tsdoc=tsdoc,
                     udoc=udoc,
                     attended=attended,
                     page_title=pdoc['title'],
                     path_components=path_components,
                     languages=languages,
                     default_lang=default_lang)
     else:
         self.json({'rdocs': rdocs})