class Command(BaseCommand):
    """バトルイベント終了処理.
    """
    def handle(self, *args, **options):

        print '================================'
        print 'close_battleevent'
        print '================================'

        now = OSAUtil.get_now()

        model_mgr = ModelRequestMgr()
        redisdb = RedisModel.getDB()

        config = BackendApi.get_current_battleeventconfig(model_mgr)
        eventmaster = BackendApi.get_battleevent_master(model_mgr, config.mid)
        if eventmaster is None:
            print u'イベントが設定されていません'
            return
        print 'check eventmaster...OK'

        # イベント設定.
        if now < config.endtime:
            print u'イベントがまだ終了していません'
            return
        print 'check event endtime...OK'

        # メンテナンス確認.
        appconfig = BackendApi.get_appconfig(model_mgr)
        if not appconfig.is_maintenance():
            print u'メンテナンスモードにしてください'
            return
        print 'check maintenance...OK'

        rankmaster_dict = dict([
            (master.id, master)
            for master in BattleEventRankMaster.fetchValues(
                filters={'eventid': config.mid},
                fetch_deleted=True,
                using=settings.DB_READONLY)
        ])

        print '================================'
        print 'send groupranking prizes.'
        # 未受け取りのグループ内ランキング報酬を配布.
        BackendApi.battleevent_send_groupranking_prizes(eventmaster)

        print '================================'
        print 'reset daily ranking.'
        logintime_today = DateTimeUtil.toLoginTime(now)
        keylist = [
            BattleEventDailyRanking.makeKey(
                BattleEventDailyRanking.makeRankingId(logintime_today,
                                                      config.mid,
                                                      rankmaster.rank))
            for rankmaster in rankmaster_dict.values()
        ]
        if keylist:
            redisdb.delete(*keylist)

        offset = 0
        LIMIT = 500
        while True:
            grouplist = BattleEventGroupLog.fetchValues(filters={
                'eventid':
                config.mid,
                'cdate':
                datetime.date(logintime_today.year, logintime_today.month,
                              logintime_today.day)
            },
                                                        order_by='id',
                                                        offset=offset,
                                                        limit=LIMIT)
            if not grouplist:
                break
            offset += LIMIT

            for group in grouplist:
                rankmaster = rankmaster_dict.get(group.rankid)
                rankingid = BattleEventDailyRanking.makeRankingId(
                    logintime_today, config.mid, rankmaster.rank)

                pipe = redisdb.pipeline()
                for userdata in group.userdata:
                    if 0 < userdata.point:
                        BattleEventDailyRanking.create(
                            rankingid, userdata.uid, userdata.point).save(pipe)
                pipe.execute()

        print '================================'
        print 'close group.'
        while True:
            grouplist = BattleEventGroup.fetchValues(
                filters={'eventid': config.mid}, order_by='cdate', limit=500)
            if not grouplist:
                break

            for group in grouplist:
                eventrankmaster = rankmaster_dict[group.rankid]
                model_mgr = db_util.run_in_transaction(Command.tr_close,
                                                       eventmaster,
                                                       eventrankmaster,
                                                       group.id, now)
                model_mgr.write_end()
                print 'close %s' % group.id

        print '================================'
        print 'send daily ranking prizes.'
        date_today = datetime.date(logintime_today.year, logintime_today.month,
                                   logintime_today.day)
        rankmasterlist = rankmaster_dict.values()
        rankmasterlist.sort(key=lambda x: x.rank)
        for rankmaster in rankmasterlist:
            # 報酬を渡す.
            rankingid = BattleEventDailyRanking.makeRankingId(
                logintime_today, config.mid, rankmaster.rank)
            rankingprizes = rankmaster.rankingprizes
            textid = rankmaster.rankingprize_text

            for idx, data in enumerate(rankingprizes):
                prize_flag = (rankmaster.rank << 16) + idx
                pre_prize_flag = config.getDailyPrizeFlag(date_today)
                if prize_flag < pre_prize_flag:
                    print 'skip...%d' % idx
                    continue

                prizeidlist = data['prize']
                rank_min = data['rank_min']
                rank_max = data['rank_max']

                prizelist = BackendApi.get_prizelist(model_mgr, prizeidlist)
                uidlist = []

                for rank in xrange(rank_min, rank_max + 1):
                    data = BattleEventDailyRanking.fetchByRank(rankingid,
                                                               rank,
                                                               zero=False)
                    dic = dict(data)
                    uidlist.extend(dic.keys())
                    if len(set(uidlist)) != len(uidlist):
                        raise CabaretError(u'ランキング取得がなにかおかしい..%d' % rank)

                def tr():
                    model_mgr = ModelRequestMgr()
                    config = CurrentBattleEventConfig.getByKeyForUpdate(
                        CurrentBattleEventConfig.SINGLE_ID)
                    if config.getDailyPrizeFlag(date_today) != pre_prize_flag:
                        raise CabaretError(u'整合が取れていないので終了します')
                    for uid in uidlist:
                        BackendApi.tr_add_prize(model_mgr, uid, prizelist,
                                                textid)
                    config.daily_prize_flag = prize_flag + 1
                    config.daily_prize_date = date_today
                    model_mgr.set_save(config)
                    model_mgr.write_all()
                    return model_mgr, config

                try:
                    tmp_model_mgr, wrote_config = db_util.run_in_transaction(
                        tr)
                except CabaretError, err:
                    print 'error...%s' % err.value
                    return

                print 'save end...%d' % idx

                tmp_model_mgr.write_end()
                print 'cache end...%d' % idx

                config = wrote_config

        print '================================'
        print 'save rank uid set.'
        for rankmaster in rankmaster_dict.values():
            BackendApi.save_battleevent_rankuidset(rankmaster.eventid,
                                                   rankmaster.rank)

        print '================================'
        print 'update ranking:start'
        # ランキングを更新.
        offset = 0
        limit = 1000
        while True:
            recordlist = BattleEventScore.fetchValues(
                ['uid', 'point_total'],
                filters={'mid': config.mid},
                limit=limit,
                offset=offset)

            pipe = BattleEventRanking.getDB().pipeline()
            for record in recordlist:
                BattleEventRanking.create(config.mid, record.uid,
                                          record.point_total).save(pipe)
                if BackendApi.check_battleevent_beginer(
                        ModelRequestMgr(),
                        record.uid,
                        eventmaster,
                        config,
                        now,
                        using=settings.DB_READONLY):
                    BattleEventRankingBeginer.create(
                        config.mid, record.uid, record.point_total).save(pipe)
            pipe.execute()

            if len(recordlist) < limit:
                break
            offset += limit
        print 'update ranking:end'

        # 報酬を渡す.
        def sendRankingPrize(ranking_cls, rankingprizes, textid,
                             att_prize_flag):
            for idx, data in enumerate(rankingprizes):
                if idx < getattr(config, att_prize_flag):
                    print 'skip...%d' % idx
                    continue

                prizeidlist = data['prize']
                rank_min = data['rank_min']
                rank_max = data['rank_max']

                prizelist = BackendApi.get_prizelist(model_mgr, prizeidlist)
                uidlist = []

                for rank in xrange(rank_min, rank_max + 1):
                    data = ranking_cls.fetchByRank(eventmaster.id,
                                                   rank,
                                                   zero=False)
                    dic = dict(data)
                    uidlist.extend(dic.keys())
                    if len(set(uidlist)) != len(uidlist):
                        raise CabaretError(u'ランキング取得がなにかおかしい..%d' % rank)

                def tr():
                    model_mgr = ModelRequestMgr()
                    config = CurrentBattleEventConfig.getByKeyForUpdate(
                        CurrentBattleEventConfig.SINGLE_ID)
                    if getattr(config, att_prize_flag) != idx:
                        raise CabaretError(u'整合が取れていないので終了します')
                    for uid in uidlist:
                        BackendApi.tr_add_prize(model_mgr, uid, prizelist,
                                                textid)
                    setattr(config, att_prize_flag, idx + 1)
                    model_mgr.set_save(config)
                    model_mgr.write_all()
                    return model_mgr, config

                try:
                    tmp_model_mgr, wrote_config = db_util.run_in_transaction(
                        tr)
                except CabaretError, err:
                    print 'error...%s' % err.value
                    return

                print 'save end...%d' % idx

                tmp_model_mgr.write_end()
                print 'cache end...%d' % idx

                setattr(config, att_prize_flag,
                        getattr(wrote_config, att_prize_flag))
Exemple #2
0
    def process(self):

        args = self.getUrlArgs('/battleeventranking/')
        eventid = args.getInt(0)
        view_myrank = args.getInt(1) == 1

        model_mgr = self.getModelMgr()
        eventmaster = None
        if eventid:
            eventmaster = BackendApi.get_battleevent_master(
                model_mgr, eventid, using=settings.DB_READONLY)

        if eventmaster is None:
            if settings_sub.IS_LOCAL:
                raise CabaretError(u'引数がおかしい')
            self.redirectToTop()
            return

        # 開催中判定.
        cur_eventmaster = self.getCurrentBattleEvent(quiet=True)
        if cur_eventmaster and cur_eventmaster.id == eventid:
            is_opened = True
            if not self.checkBattleEventUser(do_check_battle_open=False,
                                             do_check_regist=False,
                                             do_check_emergency=False):
                return
        else:
            is_opened = False
        self.html_param['is_opened'] = is_opened

        # イベント情報.
        self.html_param['battleevent'] = Objects.battleevent(self, eventmaster)

        self.putEventTopic(eventid, 'ranking')

        v_player = self.getViewerPlayer()
        uid = v_player.id

        url_battleevent_ranking = UrlMaker.battleevent_ranking(eventid, False)
        url_battleevent_myrank = UrlMaker.battleevent_ranking(eventid, True)

        # 初心者判定.
        is_beginer = BackendApi.check_battleevent_beginer(
            model_mgr, uid, eventmaster, using=settings.DB_READONLY)
        self.html_param['is_beginer'] = is_beginer

        # ランキング.
        view_beginer = self.request.get(Defines.URLQUERY_BEGINER) == "1"
        if view_beginer and not is_beginer:
            view_myrank = False
        self.putRanking(uid,
                        eventid,
                        view_myrank,
                        url_battleevent_ranking,
                        url_battleevent_myrank,
                        view_beginer=view_beginer)

        if eventmaster.is_goukon:
            self.writeAppHtml('gcevent/ranking')
        else:
            self.writeAppHtml('btevent/ranking')
Exemple #3
0
    def process(self):

        self.__execute_end_worklist = []

        model_mgr = self.getModelMgr()

        config = BackendApi.get_current_battleeventconfig(
            model_mgr, using=settings.DB_READONLY)

        args = self.getUrlArgs('/battleeventtop/')
        eventid = str(args.get(0))
        eventmaster = None

        if eventid and eventid.isdigit():
            eventid = int(eventid)
        elif config:
            eventid = config.mid

        if eventid:
            eventmaster = BackendApi.get_battleevent_master(
                model_mgr, eventid, using=settings.DB_READONLY)

        if eventmaster is None:
            raise CabaretError(u'Event Closed.',
                               CabaretError.Code.EVENT_CLOSED)
            return

        self.__eventmaster = eventmaster
        eventid = eventmaster.id
        cur_eventmaster = self.getCurrentBattleEvent(quiet=True)

        v_player = self.getViewerPlayer()
        uid = v_player.id

        is_open = cur_eventmaster and eventid == cur_eventmaster.id

        self.setFromPage(Defines.FromPages.BATTLEEVENT, eventid)

        if is_open:
            # 開催中.
            if self.isBattleOpen():
                # バトルが開いている時.
                self.procOpened()
            else:
                # バトルが閉じている時.
                self.procBattleClosed()
            # イベント参加KPI保存.
            BackendApi.save_kpi_battleevent_join(uid, self.is_pc)
        else:
            self.procClosed()

        if self.response.isEnd:
            return

        self.html_param['player'] = Objects.player(self, v_player)

        # イベント情報.
        battleevent = Objects.battleevent(self, eventmaster)
        self.html_param['battleevent'] = battleevent

        # バトルチケットの使用期限
        if is_open:
            self.html_param[
                'battle_ticket_expiry_date'] = self.get_battle_ticket_expiry_date(
                    config.ticket_endtime)

        BackendApi.check_battleevent_piececollection_userdata_and_create(
            model_mgr, uid, eventid)
        self.html_param['allrarity_piece'] = self.create_piece_image_paths(
            uid, eventid)

        # トピック.
        self.putEventTopic(eventid)

        # バトル履歴.
        if not eventmaster.is_goukon:
            loglist = BackendApi.get_battleevent_battlelog_list(
                model_mgr, uid, limit=1, using=settings.DB_READONLY)
            if loglist:
                func_battleloginfo = BackendApi.make_battleevent_battleloginfo(
                    self, loglist, do_execute=False)
                if func_battleloginfo:

                    def put_battleloginfo():
                        self.html_param['battleloglist'] = func_battleloginfo()

                    self.addExecuteApiWork(put_battleloginfo)

        # バトル履歴のリンク.
        self.html_param['url_battleevent_battlelog'] = self.makeAppLinkUrl(
            UrlMaker.battleevent_loglist())
        tradeshop_urlparam = OSAUtil.addQuery(
            UrlMaker.trade(), Defines.URLQUERY_CTYPE,
            Defines.GachaConsumeType.GachaTopTopic.TICKET)
        self.html_param['url_battleticket_trade'] = self.makeAppLinkUrl(
            tradeshop_urlparam)
        battleticket = BackendApi.get_additional_gachaticket_nums(
            model_mgr,
            v_player.id,
            [Defines.GachaConsumeType.GachaTicketType.BATTLE_TICKET],
            using=settings.DB_READONLY)
        if battleticket:
            battle_ticket_num = battleticket[
                Defines.GachaConsumeType.GachaTicketType.BATTLE_TICKET].num
        else:
            battle_ticket_num = 0
        self.html_param['battleticket'] = {
            'name':
            Defines.GachaConsumeType.NAMES[
                Defines.GachaConsumeType.BATTLE_TICKET],
            'num':
            battle_ticket_num,
            'unit':
            Defines.ItemType.UNIT[Defines.ItemType.ADDITIONAL_GACHATICKET],
        }

        # グループ履歴のリンク.
        self.html_param['url_battleevent_grouplog'] = self.makeAppLinkUrl(
            UrlMaker.battleevent_grouploglist(eventid))

        if not self.html_param.has_key('battleevent_rank'):
            # ランク情報がないのでデフォルトのを設定.
            if config.isFirstDay():
                rankmaster = BackendApi.get_battleevent_rankmaster(
                    model_mgr,
                    eventid,
                    eventmaster.rankstart,
                    using=settings.DB_READONLY)
            else:
                rankmaster = BackendApi.get_battleevent_rankmaster(
                    model_mgr,
                    eventid,
                    eventmaster.rankbeginer,
                    using=settings.DB_READONLY)
            self.html_param['battleevent_rank'] = Objects.battleevent_rank(
                self, None, rankmaster, None)

        self.executeApiWithWork()

        # 初心者フラグ.
        is_beginer = BackendApi.check_battleevent_beginer(
            model_mgr, uid, eventmaster, config, using=settings.DB_READONLY)
        self.html_param['is_beginer'] = is_beginer

        # ユーザーデータのチェック, カウントの取得
        user_cvictory_count = self.check_user_continue_victory_data(
            uid, eventid)
        self.put_user_continue_victory_data(user_cvictory_count)

        # ランキング.
        view_myrank = False
        view_beginer = self.request.get(Defines.URLQUERY_BEGINER) == "1"
        if not view_beginer or is_beginer:
            view_myrank = self.request.get(Defines.URLQUERY_FLAG) == "1"
        url_ranking = OSAUtil.addQuery(UrlMaker.battleevent_top(eventid),
                                       Defines.URLQUERY_FLAG, "0")
        url_myrank = OSAUtil.addQuery(UrlMaker.battleevent_top(eventid),
                                      Defines.URLQUERY_FLAG, "1")
        self.putRanking(uid,
                        eventid,
                        view_myrank,
                        url_ranking,
                        url_myrank,
                        view_beginer=view_beginer)

        if eventmaster.is_goukon:
            self.writeAppHtml('gcevent/top')
        else:
            self.writeAppHtml('btevent/top')