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
Beispiel #2
0
    def handle(self, *args, **options):

        print '================================'
        print 'battleevent_aggregate'
        print '================================'

        now = OSAUtil.get_now()

        model_mgr = ModelRequestMgr()
        is_battle_open = BackendApi.is_battleevent_battle_open(
            model_mgr, settings.DB_READONLY, now, do_check_emergency=False)

        if is_battle_open:
            # こっちは緊急で修復する場合..
            tomorrow = now
            now = tomorrow - datetime.timedelta(days=1)
        else:
            tomorrow = now + datetime.timedelta(days=1)

        config = BackendApi.get_current_battleeventconfig(model_mgr)
        if config.mid == 0:
            print 'イベントが設定されていません.'
            return
        elif now < config.starttime:
            print 'イベントが始まっていません.'
            return
        elif config.endtime <= now:
            print 'イベントが終わっています.'
            return
        elif is_battle_open and not config.is_emergency:
            print 'バトル中です.'
            return

        eventmaster = BackendApi.get_battleevent_master(
            model_mgr, config.mid, using=settings.DB_READONLY)
        if eventmaster is None:
            print 'イベントが見つかりません.'
            return
        print 'check eventmaster...OK'

        redisdb = RedisModel.getDB()
        ALREADY_KEY = "battleevent_aggregate:end"

        # 対象の日付(月).
        logintime = DateTimeUtil.toLoginTime(tomorrow)
        cdate = datetime.date(logintime.year, logintime.month, logintime.day)
        print cdate.strftime("Create %Y/%m/%d")

        str_cdate_pre = redisdb.get(ALREADY_KEY)
        if str_cdate_pre:
            dt = DateTimeUtil.strToDateTime(str_cdate_pre, "%Y%m%d")
            cdate_pre = datetime.date(dt.year, dt.month, dt.day)
            if cdate_pre == cdate:
                print "already..."
                return

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

        print '================================'
        print 'check rankmax'
        rank_max = config.getRankMax(logintime)
        print 'rankmax=%s' % rank_max
        if rank_max is None:
            rankmaster_list = rankmaster_dict.values()
        else:
            rankmaster_list = [
                rankmaster for rankmaster in rankmaster_dict.values()
                if rankmaster.rank <= rank_max
            ]
        if not rankmaster_list:
            print 'rank:all closed'
            return

        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 or cdate <= grouplist[0].cdate:
                break

            for group in grouplist:
                if cdate <= group.cdate:
                    break

                eventrankmaster = rankmaster_dict[group.rankid]
                model_mgr = db_util.run_in_transaction(Command.tr_close,
                                                       eventmaster,
                                                       eventrankmaster,
                                                       group.id, now, rank_max)
                model_mgr.write_end()

                print 'close %s' % group.id

        print '================================'
        print 'send rankingprizes.'
        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