async def post(self, *, cid: str, mail: str, tel: str, team_name: str, is_newbie: bool = False, member_id: str, member_id_number: str): validator.check_mail(mail) validator.check_tel(tel) validator.check_team_name(team_name) members = list( zip(self.request.POST.getall('member_id'), self.request.POST.getall('member_id_number'))) if len(members) > 3 or len(members) < 1: raise error.ValidationError('members') cdoc = await campaign.get(cid) if not cdoc['is_newbie'] and is_newbie: raise error.ValidationError('is_newbie') if not self.is_live(cdoc): raise error.CampaignNotInTimeError(cdoc['title']) for member in members: sdoc = await student.check_student_by_id(*member) if is_newbie and sdoc['grade'] != datetime.datetime.utcnow().year: raise error.StudentIsNotNewbieError(member[0]) members = [member[0] for member in members] await campaign.attend(cid, self.user['_id'], mail, tel, team_name, is_newbie, members) redirect_url = self.reverse_url('campaign_teams', cid=cid) self.json_or_redirect(redirect_url, redirect=redirect_url)
async def post(self, *, campaign_id: str, title: str, content: str, begin_at_date: str, begin_at_time: str, end_at_date: str, end_at_time: str, is_newbie: bool = False): validator.check_campaign_id(campaign_id) validator.check_title(title) validator.check_content(content) try: begin_at = datetime.datetime.strptime( begin_at_date + ' ' + begin_at_time, '%Y-%m-%d %H:%M') begin_at = self.timezone.localize(begin_at).astimezone( pytz.utc).replace(tzinfo=None) end_at = datetime.datetime.strptime( end_at_date + ' ' + end_at_time, '%Y-%m-%d %H:%M') end_at = self.timezone.localize(end_at).astimezone( pytz.utc).replace(tzinfo=None) except ValueError: raise error.ValidationError('begin_at_date', 'begin_at_time') if begin_at <= self.now or begin_at >= end_at: raise error.ValidationError('begin_at_date', 'begin_at_time') cid = await campaign.add(campaign_id, title, content, self.user['_id'], begin_at, end_at, is_newbie) self.json_or_redirect(self.reverse_url('campaign_detail', cid=cid))
def check_type_and_name(field, name): if not isinstance(field, multipart.BodyPartReader): raise error.ValidationError(name) disptype, parts = multipart.parse_content_disposition( field.headers.get('Content-Disposition')) if disptype != 'form-data' or parts.get('name') != name: raise error.ValidationError(name)
async def add(domain_id: str, title: str, content: str, owner_uid: int, rule: int, private: bool, begin_at: lambda i: datetime.datetime.utcfromtimestamp(int(i)), end_at: lambda i: datetime.datetime.utcfromtimestamp(int(i)), pids=[], **kwargs): validator.check_title(title) validator.check_content(content) if rule not in RULES: raise error.ValidationError('rule') if begin_at >= end_at: raise error.ValidationError('begin_at', 'end_at') # TODO: should we check problem existance here? tid = await system.inc_contest_counter() coll = db.Collection('contest') doc = { '_id': tid, 'domain_id': domain_id, 'title': title, 'content': content, 'owner_uid': owner_uid, 'rule': rule, 'private': private, 'begin_at': begin_at, 'end_at': end_at, 'pids': pids, 'attend': 0, **kwargs, } await coll.insert_one(doc) return tid
async def post(self, *, cid: str, title: str, content: str, begin_at_date: str, begin_at_time: str, end_at_date: str, end_at_time: str, is_newbie: bool = False): try: begin_at = datetime.datetime.strptime( begin_at_date + ' ' + begin_at_time, '%Y-%m-%d %H:%M') begin_at = self.timezone.localize(begin_at).astimezone( pytz.utc).replace(tzinfo=None) end_at = datetime.datetime.strptime( end_at_date + ' ' + end_at_time, '%Y-%m-%d %H:%M') end_at = self.timezone.localize(end_at).astimezone( pytz.utc).replace(tzinfo=None) except ValueError: raise error.ValidationError('begin_at_date', 'begin_at_time') if begin_at >= end_at: raise error.ValidationError('begin_at_date', 'begin_at_time') await campaign.edit(cid, title=title, content=content, begin_at=begin_at, end_at=end_at, is_newbie=is_newbie) self.json_or_redirect(self.reverse_url('campaign_detail', cid=cid))
async def post(self, *, tid: int, title: str, content: str, rule: int, private: bool = False, begin_at_date: str, begin_at_time: str, duration: float, pids: str): tdoc = await contest.get(self.domain_id, tid) if not self.own(tdoc, builtin.PERM_EDIT_CONTEST_SELF): self.check_perm(builtin.PERM_EDIT_CONTEST) try: begin_at = datetime.datetime.strptime( begin_at_date + ' ' + begin_at_time, '%Y-%m-%d %H:%M') begin_at = self.timezone.localize(begin_at).astimezone( pytz.utc).replace(tzinfo=None) end_at = begin_at + datetime.timedelta(hours=duration) except ValueError: raise error.ValidationError('begin_at_date', 'begin_at_time') if begin_at >= end_at: raise error.ValidationError('duration') pids = list(OrderedSet(map(int, pids.split(',')))) pdocs = await problem.get_multi(domain_id=self.domain_id, _id={ '$in': pids }, projection={ '_id': 1 }).sort('_id', 1).to_list(None) exist_pids = [pdoc['_id'] for pdoc in pdocs] if len(pids) != len(exist_pids): for pid in pids: if pid not in exist_pids: raise error.ProblemNotFoundError(self.domain_id, pid) await contest.edit(domain_id=self.domain_id, tid=tid, title=title, content=content, rule=rule, private=private, begin_at=begin_at, end_at=end_at, pids=pids) for pid in pids: await problem.set_hidden(self.domain_id, pid, True) self.json_or_redirect(self.reverse_url('contest_detail', tid=tid))
async def set_status_balloon(domain_id: str, tid: int, uid: int, pid: int, balloon: bool = True): tdoc = await get(domain_id, tid) if pid not in tdoc['pids']: raise error.ValidationError('pid') coll = db.Collection('contest.status') tsdoc = await coll.find_one_and_update( filter={ 'domain_id': domain_id, 'tid': tid, 'uid': uid, 'detail.pid': pid }, update={'$set': { 'detail.$.balloon': balloon }}, return_document=ReturnDocument.AFTER) udoc = await user.get_by_uid(uid) await bus.publish( 'balloon_change', json.encode({ 'uid': uid, 'uname': udoc['uname'], 'nickname': udoc.get('nickname', ''), 'tid': tid, 'pid': pid, 'letter': convert_to_letter(tdoc['pids'], pid), 'balloon': balloon })) return tsdoc
async def paginate(cursor, page: int, page_size: int): if page <= 0: raise error.ValidationError('page') count, page_docs = await asyncio.gather( cursor.count(), cursor.skip((page - 1) * page_size).limit(page_size).to_list(None) ) num_pages = (count + page_size - 1) // page_size return page_docs, num_pages, count
async def post_set_users(self, *, uid: int, role: str): try: uids = map(int, self.request.POST.getall('uid')) except ValueError: raise error.ValidationError('uid') if role: await domain.set_users_role(self.domain_id, uids, role) else: await domain.unset_users_role(self.domain_id, uids) self.json_or_redirect(self.url)
async def set_settings(self, **kwargs): for key, value in kwargs.items(): if key not in SETTINGS_BY_KEY: raise error.UnknownFieldError(key) setting = SETTINGS_BY_KEY[key] kwargs[key] = setting.factory(value) if setting.range and kwargs[key] not in setting.range: raise error.ValidationError(key) if self.has_priv(builtin.PRIV_USER_PROFILE): await user.set_by_uid(self.user['_id'], **kwargs) else: await self.update_session(**kwargs)
async def edit(campaign_id: str, **kwargs): coll = db.Collection('campaign') cdoc = await coll.find_one(campaign_id) if 'owner_uid' in kwargs: del kwargs['owner_uid'] if 'title' in kwargs: validator.check_title(kwargs['title']) if 'content' in kwargs: validator.check_content(kwargs['content']) begin_at = kwargs['begin_at'] if 'begin_at' in kwargs else cdoc['begin_at'] end_at = kwargs['end_at'] if 'end_at' in kwargs else cdoc['end_at'] if begin_at >= end_at: raise error.ValidationError('begin_at', 'end_at') return await coll.find_one_and_update(filter={'_id': campaign_id}, update={'$set': { **kwargs }}, return_document=ReturnDocument.AFTER)
async def add(campaign_id: str, title: str, content: str, owner_uid: int, begin_at: lambda i: datetime.datetime.utcfromtimestamp(int(i)), end_at: lambda i: datetime.datetime.utcfromtimestamp(int(i)), is_newbie: bool): validator.check_title(title) validator.check_content(content) validator.check_domain_id(campaign_id) if begin_at >= end_at: raise error.ValidationError('begin_at', 'end_at') coll = db.Collection('campaign') try: return (await coll.insert_one({ '_id': campaign_id, 'domain_id': builtin.DOMAIN_ID_SYSTEM, 'owner_uid': owner_uid, 'title': title, 'content': content, 'is_newbie': is_newbie, 'begin_at': begin_at, 'end_at': end_at })).inserted_id except errors.DuplicateKeyError: raise error.CampaignAlreadyExistError(campaign_id) from None
def check_password(s): if not is_password(s): raise error.ValidationError('password')
def check_role(s): if not is_role(s): raise error.ValidationError('role')
def check_title(s): if not is_title(s): raise error.ValidationError('title')
def check_category_name(s): if not is_id(s): raise error.ValidationError('category_name')
def check_node_name(s): if not is_id(s): raise error.ValidationError('node_name')
def check_domain_id(s): if not is_domain_id(s): raise error.ValidationError('domain_id')
def check_campaign_id(s): if not is_campaign_id(s): raise error.ValidationError('campaign_id')
def check_time_second_limit(s): if s < 1 or s > 10: raise error.ValidationError('time')
def check_memory_mb_limit(s): if s < 32 or s > 1024: raise error.ValidationError('memory')
async def update_status(domain_id: str, tid: int, uid: int, rid: objectid.ObjectId, pid: int, accept: bool): tdoc = await get(domain_id, tid) if pid not in tdoc['pids']: raise error.ValidationError('pid') coll = db.Collection('contest.status') tsdoc = await coll.find_one_and_update( filter={ 'domain_id': domain_id, 'tid': tid, 'uid': uid }, update={ '$push': { 'journal': { 'rid': rid, 'pid': pid, 'accept': accept } }, '$inc': { 'rev': 1 } }, return_document=ReturnDocument.AFTER) if not tsdoc: return {} if 'attend' not in tsdoc or not tsdoc['attend']: raise error.ContestNotAttendedError(domain_id, tid, uid) # Sort and uniquify journal of the contest status, by rid. key_func = lambda j: j['rid'] journal = [ list(g)[-1] for _, g in itertools.groupby(sorted(tsdoc['journal'], key=key_func), key=key_func) ] stats = RULES[tdoc['rule']].stat_func(tdoc, journal) psdict = {} for detail in tsdoc.get('detail', []): psdict[detail['pid']] = detail for detail in stats.get('detail', []): detail['balloon'] = psdict.get(detail['pid'], { 'balloon': False }).get('balloon', False) tsdoc = await coll.find_one_and_update( filter={ 'domain_id': domain_id, 'tid': tid, 'uid': uid }, update={ '$set': { 'journal': journal, **stats }, '$inc': { 'rev': 1 } }, return_document=ReturnDocument.AFTER) await bus.publish('contest_notification-' + str(tid), json.encode({'type': 'rank_changed'})) if accept and not psdict.get(pid, {'accept': False})['accept']: await set_status_balloon(domain_id, tid, uid, pid, False) return tsdoc
def check_uid(s): if not is_uid(s): raise error.ValidationError('uid')
def check_uname(s): if not is_uname(s): raise error.ValidationError('uname')
def check_content(s): if not is_content(s): raise error.ValidationError('content')
def check_tel(s): if not is_tel(s): raise error.ValidationError('tel')
def check_lang(s): if not is_lang(s): raise error.ValidationError('lang')
def check_description(s): if not is_description(s): raise error.ValidationError('description')
def check_team_name(s): if not is_team_name(s): raise error.ValidationError('team_name')
def check_mail(s): if not is_mail(s): raise error.ValidationError('mail')