def _get_loguserdata(self, cursor): # try: # cursor.execute("select uid, ctime, data from cabaret_userloggacha where '2015-09-29'<ctime and ctime<'2015-10-02 14:00:00';") # row = cursor.fetchall() # except: # pass filters = dict( ctime__gt=DateTimeUtil.strToDateTime('2015-09-29', '%Y-%m-%d'), ctime__lt=DateTimeUtil.strToDateTime('2015-10-02 14:00:00', '%Y-%m-%d %H:%M:%S')) loguserdata = {} # for uid, ctime, log in row: for model in UserLogGacha.fetchValues(filters=filters): uid, ctime, logdata = model.uid, model.ctime, model.data # obj = ObjectField() # logdata = obj.to_python(log) mid = logdata.get('mid') prizeid = logdata.get('seat_prizeid') if prizeid == 600301 and mid == 1086: if loguserdata.get(uid): loguserdata[uid].append(ctime.replace(tzinfo=None)) else: loguserdata[uid] = [ctime.replace(tzinfo=None)] for v in loguserdata.values(): v.sort() return loguserdata
def handle(self, *args, **options): print '================================' print 'aggregate_paymententry' print '================================' # 対象の日付(月). str_date = args[0] if str_date == 'auto': first = DateTimeUtil.strToDateTime(OSAUtil.get_now().strftime("%Y%m"), "%Y%m") str_date = (first - datetime.timedelta(days=1)).strftime("%Y%m") target_date = DateTimeUtil.strToDateTime(str_date, "%Y%m") print target_date # 出力先. output_dir = args[1] path = os.path.join(output_dir, target_date.strftime("paymententry_%Y%m.csv")) # 書き込むデータをここに溜め込む. writer = Command.Writer(path) writer.add(','.join([u'ペイメントID', u'単価', u'購入個数', u'合計ポイント'])) self.aggregate(writer, GachaPaymentEntry, target_date) self.aggregate(writer, ShopPaymentEntry, target_date) writer.output(overwrite=False) print '================================' print 'all done..'
def _get_loguserdata(self): model_mgr = ModelRequestMgr() gachamasteridlist = [557, 558, 559] # ステップガチャ 5,6,7 gachamasters = model_mgr.get_models(GachaMaster, gachamasteridlist, using=settings.DB_READONLY) continuitydict = {master.id:master.continuity for master in gachamasters} loguserdata = {} # the error occured between 2017-02-09 16:00:00 and 2017-02-10 14:00:00 # therefore we filter the User Log using this parameters filters = dict(ctime__gte=DateTimeUtil.strToDateTime('2017-02-09 16:00:00', '%Y-%m-%d %H:%M:%S'), ctime__lte=DateTimeUtil.strToDateTime('2017-02-10 14:00:00', '%Y-%m-%d %H:%M:%S')) tmpdict = {continuity:defaultdict(int) for continuity in continuitydict.values()} for model in UserLogGacha.fetchValues(filters=filters): uid, ctime, logdata = model.uid, model.ctime, model.data continuity = logdata.get('continuity') if continuity in continuitydict.values(): tmpdict[continuity][uid] += 1 """ ID's form PrizeMaster 611045 => 5STEP目は「琥珀のかんざし」 611044 => 6STEP目は「花魁のかんざし」 400401 => 7STEP目は「ティアラ」 """ loguserdata[611045] = tmpdict.pop(8) loguserdata[611044] = tmpdict.pop(11) loguserdata[400401] = tmpdict.pop(19) return loguserdata
def get_data(self): # 前月の最終日. e_date = DateTimeUtil.strToDateTime( self.date.strftime("%Y%m01"), "%Y%m%d") - datetime.timedelta(days=1) # 前月の1日. s_date = DateTimeUtil.strToDateTime(e_date.strftime("%Y%m01"), "%Y%m%d") return self.get_data_by_range(s_date, e_date)
def process(self): model_mgr = self.getModelMgr() appconfig = BackendApi.get_appconfig(model_mgr, using=settings.DB_READONLY) if appconfig.is_maintenance(): # メンテ中は実行しない. self.send(200, 'maintenance') return args = self.getUrlArgs('/aggregate_paymententry/') str_target_date = args.get(0) if str_target_date: target_date = DateTimeUtil.strToDateTime(str_target_date, "%Y%m") else: # 未指定の場合は前月分. last_date = DateTimeUtil.strToDateTime(OSAUtil.get_now().strftime("%Y%m"), "%Y%m") - datetime.timedelta(days=1) target_date = DateTimeUtil.strToDateTime(last_date.strftime("%Y%m"), "%Y%m") def makeWriter(name): # 出力先. path = os.path.join(settings_sub.KPI_ROOT, target_date.strftime("paymententry/paymententry_"+name+"_%Y%m.csv")) # 書き込むデータをここに溜め込む. writer = Handler.Writer(path) writer.add(','.join([u'ペイメントID', u'単価', u'購入個数', u'合計ポイント', u'executedTime'])) return writer writer_sp = makeWriter("sp") writer_pc = makeWriter("pc") model_cls_list = ( GachaPaymentEntry, ShopPaymentEntry, ) self.__logs = [] for model_cls in model_cls_list: self.work(model_cls, target_date, writer_sp, writer_pc) if self.response.isEnd: return print 'all end' writer_sp.output() writer_pc.output() print 'all output' self.__logs.insert(0, 'OK') print 'log insert' self.send(200, '\n'.join(self.__logs)) print 'complete'
def get_data(self): """FQ5課金ユーザ. """ # 1日のDate. s_time = DateTimeUtil.strToDateTime(self.date.strftime("%Y%m01"), "%Y%m%d") # 集計終了時間. e_time = DateTimeUtil.toBaseTime(self.date, 23, 59, 59) # 対象のガチャ. filters = { 'consumetype__in': Defines.GachaConsumeType.PAYMENT_TYPES, } gachamasterlist = GachaMaster.fetchValues(filters=filters, order_by='id', using=backup_db) model_mgr = ModelRequestMgr() result = [] for gachamaster in gachamasterlist: if gachamaster.schedule: # 期間チェック. master = model_mgr.get_model(ScheduleMaster, gachamaster.schedule, using=backup_db) if master and ((master.stime <= master.etime <= s_time) or (e_time < master.stime <= master.etime)): # 期間外. continue # FQ5UU. cnt = FQ5PaymentSet.countByRange(s_time, e_time, gachamaster.id) result.append((gachamaster.id, cnt)) return result
def __init__(self, uid, damage=0, cnt=0, number=0, feverendtime=None, champagne=False, champagne_post=0, champagne_add=0, material=0, tanzaku=0, tanzaku_post=0): self.__uid = uid self.__damage = damage self.__damage_cnt = cnt self.__number = number if not feverendtime: feverendtime = OSAUtil.get_datetime_min() elif not isinstance(feverendtime, datetime.datetime): feverendtime = DateTimeUtil.strToDateTime(feverendtime) self.__feverendtime = feverendtime self.__champagne = bool(champagne) self.__champagne_post = champagne_post self.__champagne_add = champagne_add self.__material_num = material self.__tanzaku = tanzaku self.__tanzaku_post = tanzaku_post
def handle(self, *args, **options): print '================================' print 'aggregate_paymentusermap' print '================================' # 対象の日付(月). str_date = args[0] target_date = DateTimeUtil.strToDateTime(str_date, "%Y%m") print target_date # 出力先. output_dir = args[1] path = os.path.join(output_dir, target_date.strftime("paymentusermap_%Y%m.csv")) # 書き込むデータをここに溜め込む. writer = Command.Writer(path) writer.add(','.join([u'ユーザID', u'消費ポイント'])) dest_map = {} self.aggregate(GachaPaymentEntry, target_date, dest_map) self.aggregate(ShopPaymentEntry, target_date, dest_map) for data in dest_map.items(): writer.add(u'%s,%s' % data) writer.output(overwrite=False) print '================================' print 'all done..'
def work(self, model_cls, target_date, writer_sp, writer_pc): s_executed_date = target_date e_executed_date = DateTimeUtil.strToDateTime((s_executed_date + datetime.timedelta(days=31)).strftime("%Y%m"), "%Y%m") # 前後1日を余分に. s_date = s_executed_date - datetime.timedelta(days=1) e_date = e_executed_date + datetime.timedelta(days=1) filters = { 'state' : PaymentData.Status.COMPLETED, 'ctime__gte' : s_date, 'ctime__lt' : e_date, } LIMIT = 500 offset = 0 while True: model_mgr = ModelRequestMgr() modellist = model_cls.fetchValues(filters=filters, limit=LIMIT, offset=offset, order_by='ctime', using=backup_db) for model in modellist: player = BackendApi.get_player(self, model.uid, [], using=settings.DB_READONLY, model_mgr=model_mgr) try: record = BackendApi.get_restful_paymentrecord(self, model.id, player.dmmid) except: if not settings_sub.IS_DEV: raise else: # クロスプロモで共有した環境のレコード. continue if record.executeTime is None or not (s_executed_date <= record.executeTime < e_executed_date): # 集計対象の日付ではない. continue persons = BackendApi.get_dmmplayers(self, [player], using=settings.DB_READONLY, do_execute=False) person = persons[player.dmmid] if person and getattr(person, 'userType', None) == "staff": # 優待アカウント. self.__logs.append("%s=>staff" % model.id) continue if str(record.paymentItems[0].itemId).isdigit(): writer = writer_sp else: writer = writer_pc writer.add(','.join([model.id, str(model.price), str(model.inum), str(model.price*model.inum), record.executeTime.strftime("%Y-%m-%d %H:%M:%S")])) self.__logs.append(model.id) offset += LIMIT if len(modellist) < LIMIT: break
def datetime_to_sql_week(self, dt): """週間データのカラムのパーティション用のSQLに変換. """ if isinstance(dt, datetime.datetime): dt = DateTimeUtil.strToDateTime(dt.strftime("%Y-%m-01 00:00:00"), "%Y-%m-%d %H:%M:%S") endtime = BackendApi.to_cabaretclub_section_endtime(dt) v = endtime.strftime("%Y%W") else: v = dt return v
def process(self): model_mgr = self.getModelMgr() appconfig = BackendApi.get_appconfig(model_mgr, using=settings.DB_READONLY) if appconfig.is_maintenance(): # メンテ中は送信しない. self.send(200, 'maintenance') return args = self.getUrlArgs('/paymentlog_post/') str_target_date = args.get(0) if str_target_date: target_date = DateTimeUtil.strToDateTime( str_target_date, Handler.TARGET_DATE_FORMAT) else: # 未指定の場合は前日分. target_date = DateTimeUtil.toBaseTime( OSAUtil.get_now() - datetime.timedelta(days=1), 0) model_cls_list = ( GachaPaymentEntry, ShopPaymentEntry, ) post_nums = { str_target_date: { 'sp': 0, 'pc': 0, } } self.__logs = [] for model_cls in model_cls_list: overwrite_sp = post_nums[str_target_date].get('sp', 0) < 1 overwrite_pc = post_nums[str_target_date].get('pc', 0) < 1 tmp_post_nums = self.work(model_cls, target_date, overwrite_sp, overwrite_pc) or {} for str_date, nums in tmp_post_nums.items(): dic = post_nums[str_date] = post_nums.get(str_date) or {} for k, v in nums.items(): dic[k] = dic.get(k, 0) + v if self.response.isEnd: return # 送信した件数. self.__logs.append(u'nums:') for str_date, nums in post_nums.items(): self.__logs.append( u'%s:sp=%s,pc=%s' % (str_date, nums.get('sp', 0), nums.get('pc', 0))) self.__logs.insert(0, 'OK') self.send(200, '\n'.join(self.__logs))
def checkAggregateEnd(self, targettime): redisdb = RedisModel.getDB() ALREADY_KEY = "battleevent_aggregate:end" # 対象の日付(月). logintime = DateTimeUtil.toLoginTime(targettime) cdate = datetime.date(logintime.year, logintime.month, logintime.day) 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: # 集計が正常に終わっている. return True return False
def handle(self, *args, **options): print '================================' print 'select_userlog' print '================================' target = args[0] model_cls = self.getModelClass(target) str_ctime_min = args[1] ctime_min = DateTimeUtil.strToDateTime(str_ctime_min, "%Y-%m-%d %H:%M:%S") getter = eval(args[2]) LIMIT = 3000 uid_max = Player.max_value('id', using=backup_db) for uid in xrange(1, uid_max + 1): filters = {'uid': uid, 'ctime__gte': ctime_min} offset = 0 num = 0 while True: modellist = model_cls.fetchValues(filters=filters, order_by='ctime', limit=LIMIT, offset=offset, using=backup_db) if not modellist: break offset += len(modellist) for model in modellist: num += getter(model) if num: print '%d,%d' % (uid, num) print '================================' print 'all done..'
class RaidBoss(): """レイドボス. """ # 協力者報酬が適用開始される時間. DEMIWORLD_OPEN_TIME = DateTimeUtil.strToDateTime("201402031600", "%Y%m%d%H%M") # HPが仕様変更される時間. if settings_sub.IS_DEV: HP_UPDATE_TIME = DateTimeUtil.strToDateTime("201402061430", "%Y%m%d%H%M") else: HP_UPDATE_TIME = DateTimeUtil.strToDateTime("201402071430", "%Y%m%d%H%M") # ダメージ履歴のバージョン. DAMAGE_RECORDVERSION = 1 # レイドイベント報酬で通常のも受け取れるようになった時間. if settings_sub.IS_DEV: RAIDEVENT_PRIZE_UPDATETIME = DateTimeUtil.strToDateTime( "201402261300", "%Y%m%d%H%M") else: RAIDEVENT_PRIZE_UPDATETIME = DateTimeUtil.strToDateTime( "201402281500", "%Y%m%d%H%M") def __init__(self, raid, master, eventraidmaster=None): self.__raid = raid self.__master = master self.__eventraidmaster = None self.__records = {} self.__combo_cnt = 0 self.__combo_etime = OSAUtil.get_datetime_min() self.setEventRaidMaster(eventraidmaster) combodata = self.__getDBComboData() if combodata: self.__combo_cnt = combodata['cnt'] self.__combo_etime = combodata['etime'] @property def id(self): return self.raid.id @property def raid(self): return self.__raid @property def master(self): return self.__master @property def raideventraidmaster(self): return self.__eventraidmaster if isinstance( self.__eventraidmaster, RaidEventRaidMaster) else None @property def scouteventraidmaster(self): return self.__eventraidmaster if isinstance( self.__eventraidmaster, ScoutEventRaidMaster) else None @property def produceeventraidmaster(self): return self.__eventraidmaster if isinstance( self.__eventraidmaster, ProduceEventRaidMaster) else None @property def hp(self): return self.raid.hp @property def defense(self): return self.get_defense() @property def ctype(self): return self.master.ctype @property def weakbonus(self): return self.master.weakbonus @property def timebonusflag(self): """タイムボーナスフラグ. """ return self.raid.timebonusflag @property def fastflag(self): """秘宝ボーナスフラグ. """ return self.raid.fastflag @property def combo_cnt(self): return self.__combo_cnt @property def combo_etime(self): return self.__combo_etime def __getDBDamageRecordData(self): """Raid.damage_recordの中身のバージョンを見て取得. """ damage_record = self.raid.getDamageRecord() version = damage_record.get('VERSION', None) if version == 1: # コンボボーナス時間追加バージョン. records = damage_record['records'] = damage_record.get( 'records', {}) return records else: # リリース時のバージョン. return damage_record def __getDBComboData(self): """コンボ情報を取得. """ damage_record = self.raid.getDamageRecord() version = damage_record.get('VERSION', None) if version == 1: # コンボボーナス時間追加バージョン. return damage_record.get('combo') else: # リリース時のバージョン. return None def __saveDBDamageRecordData(self, records): """Raid.damage_recordの中身のバージョンをつけて保存. """ self.raid.setDamageRecord({ 'VERSION': RaidBoss.DAMAGE_RECORDVERSION, 'records': records, 'combo': { 'cnt': self.__combo_cnt, 'etime': self.__combo_etime or OSAUtil.get_now(), }, }) def setEventRaidMaster(self, eventraidmaster): if eventraidmaster and eventraidmaster.mid != self.master.id: raise CabaretError(u'不正な設定を行っている') self.__eventraidmaster = eventraidmaster def get_maxhp(self): """最大HP. """ if (self.raid.ctime or OSAUtil.get_now()) < RaidBoss.HP_UPDATE_TIME: # 旧仕様. return max( 1, (self.master.hpbase + self.raid.level * self.master.hpgrowth) * self.raid.hprate / 100) elif self.raideventraidmaster: lvband = max(0, int(self.raid.level / 10 - 1)) cnt = lvband * (lvband + 1) / 2 pre = cnt * 10 - lvband return max(1, (self.master.hpbase + pre * 10 * self.master.hpgrowth + self.master.hpgrowth * 10 * (self.raid.level - 1)) * self.raid.hprate / 100) else: return max( 1, (self.master.hpbase + self.raid.level * self.master.hpgrowth) * self.raid.hprate / 100) def get_defense(self): """防御力. """ return self.master.defensebase + self.raid.level * self.master.defensegrowth def get_member_num(self): """参加人数. """ cnt = 0 for uid in self.getDamageRecordUserIdList(): if 0 < self.getDamageRecord(uid).damage_cnt: cnt += 1 return cnt def get_cabaretking(self): """キャバ王の秘宝. """ return self.master.cabaretkingbase + self.raid.level * self.master.cabaretkinggrowth def get_demiworld(self): """キャバ王の秘宝(救援). """ if self.raid.ctime < RaidBoss.DEMIWORLD_OPEN_TIME: # 公開前に発生したレイドについては0 return 0 else: return self.master.demiworldbase + self.raid.level * self.master.demiworldgrowth def get_owner_eventpoint(self): """発見者のイベントポイント. """ point = 0 if self.raideventraidmaster: if self.timebonusflag: point = self.raideventraidmaster.ownerpoint_timebonus + self.raid.level * self.raideventraidmaster.ownerpoint_timebonus_growth else: point = self.raideventraidmaster.ownerpoint + self.raid.level * self.raideventraidmaster.ownerpoint_growth return int(point * self.raid.evpointrate / 100) def get_mvp_eventpoint(self): """MVPのイベントポイント. """ point = 0 if self.raideventraidmaster: if self.timebonusflag: point = self.raideventraidmaster.mvppoint_timebonus + self.raid.level * self.raideventraidmaster.mvppoint_timebonus_growth else: point = self.raideventraidmaster.mvppoint + self.raid.level * self.raideventraidmaster.mvppoint_growth return int(point * self.raid.evpointrate / 100) def is_big(self): """大ボスフラグ. """ return self.raideventraidmaster and self.raideventraidmaster.big def is_produceevent_bigboss(self): """プロデュースイベント大ボスフラグ """ return self.produceeventraidmaster and self.produceeventraidmaster.big def getDamageRecordUserIdList(self): """ダメージ履歴にあるユーザーIDを取得. """ damage_record = self.__getDBDamageRecordData() uidlist = list( set(list(self.__records.keys()) + list(damage_record.keys()))) return uidlist def is_help_sent(self): """救援依頼を送ったか. """ return 1 < len(self.getDamageRecordUserIdList()) def getLastDamageRecord(self): """最後のダメージ履歴. """ uidlist = self.getDamageRecordUserIdList() recordlist = [self.getDamageRecord(uid) for uid in uidlist] if recordlist: recordlist.sort(key=operator.attrgetter('number'), reverse=True) record = recordlist[0] if 0 < record.damage_cnt: return record return None def getDamageRecordList(self): """ダメージ履歴を全て取得. """ uidlist = self.getDamageRecordUserIdList() recordlist = [self.getDamageRecord(uid) for uid in uidlist] recordlist.sort(key=operator.attrgetter('damage'), reverse=True) return recordlist def getDamageRecord(self, uid): """ダメージ履歴を取得. """ if self.__records.has_key(uid): return self.__records[uid] damage_record = self.__getDBDamageRecordData() data = damage_record.get(uid, None) if data is None: record = RaidDamageRecord(uid) else: record = RaidDamageRecord(uid, **data) self.__records[uid] = record return record def addUser(self, uid): """ダメージ履歴に追記. """ return self.getDamageRecord(uid) def addDamageRecord(self, uid, damage, feverendtime=None): """ダメージ履歴に追記. """ lastrecord = self.getLastDamageRecord() if lastrecord: number = lastrecord.number + 1 else: number = 1 record = self.getDamageRecord(uid) record.addDamage(damage) record.setNumber(number) if feverendtime: record.updateFeverTime(feverendtime) def refrectDamageRecord(self): """ダメージ履歴の更新分を反映. """ damage_record = self.__getDBDamageRecordData() for record in self.__records.values(): damage_record[record.uid] = record.to_dict() self.__saveDBDamageRecordData(damage_record) def getMVPList(self): """MVPユーザIDを取得. """ recordlist = self.getDamageRecordList() recordlist.sort(key=lambda x: x.damage, reverse=True) uidlist = [] damage = 0 for record in recordlist: if record.damage == 0 or record.damage < damage: break uidlist.append(record.uid) damage = record.damage return uidlist def getBorderDamageForPrizeGet(self): """報酬獲得に必要なダメージ. """ if not self.raideventraidmaster: return 0 maxhp = self.get_maxhp() border = int(maxhp * 3 / 100) return border def getHelpEventPoints(self, uid=None): """協力者のイベントポイント. ユーザIDがキー, ポイントが値. """ data = {} if not self.raideventraidmaster: return data maxhp = self.get_maxhp() border = self.getBorderDamageForPrizeGet() if uid is None: recordlist = self.getDamageRecordList() else: recordlist = [] record = self.getDamageRecord(uid) if record: recordlist.append(record) maxpoint = self.get_mvp_eventpoint() oid = self.raid.oid for record in recordlist: damage = record.damage if damage < border: continue elif record.uid == oid: continue # MVP報酬×貢献度(ボスに与えたダメージ割合)×5. data[record.uid] = int( min(maxpoint * damage * 5 / maxhp, maxpoint / 2)) return data def getCurrentComboCount(self, now=None): """現在のコンボ数. """ now = now or OSAUtil.get_now() if now < self.combo_etime: return self.combo_cnt else: return 0 def setComboData(self, cnt, etime): """コンボ数を設定. """ self.__combo_cnt = cnt self.__combo_etime = etime def addComboCount(self, uid, seconds, now=None, cnt=1): """コンボ数を加算. """ now = now or OSAUtil.get_now() cur_cnt = self.getCurrentComboCount(now) if 0 < cur_cnt: lastrecord = self.getLastDamageRecord() if lastrecord and lastrecord.uid == uid: # 直前に同じ人が接客しているので加算しない. return self.setComboData(cur_cnt + cnt, now + datetime.timedelta(seconds=seconds)) def get_tanzaku_number(self, uid): if self.scouteventraidmaster is None: return None elif uid == self.raid.oid: return self.scouteventraidmaster.tanzaku_number if self.scouteventraidmaster.tanzaku_rate else None else: return self.scouteventraidmaster.tanzaku_help_number if self.scouteventraidmaster.tanzaku_help_rate else None
def makeProceeds(self, master): """ガチャの課金情報を集計. """ model_mgr = self.getModelMgr() appstime = DateTimeUtil.strToDateTime("20131224", "%Y%m%d") dest = { 'id': master.id, 'name': master.name, } schedulemaster = None if master.schedule: schedulemaster = BackendApi.get_schedule_master( model_mgr, master.schedule, using=settings.DB_READONLY) now = OSAUtil.get_now() if schedulemaster: stime = max(appstime, schedulemaster.stime) etime = min(now, schedulemaster.etime) else: stime = appstime etime = now table = {} filters = { 'state': PaymentData.Status.COMPLETED, 'iid': master.id, } cur_stime = stime useridset_total = set() count_total = 0 while cur_stime < etime: filters['ctime__gte'] = cur_stime filters['ctime__lt'] = DateTimeUtil.toBaseTime( cur_stime + datetime.timedelta(days=1), 0) paymentlist = self.getPaymentFromCache(master.id, cur_stime, now) if paymentlist is None: paymentlist = GachaPaymentEntry.fetchValues( ['uid', 'inum', 'price'], filters=filters, using=settings.DB_READONLY) self.setPaymentToCache(paymentlist, master.id, cur_stime, now) str_month = cur_stime.strftime("%Y%m") uidset = set([payment.uid for payment in paymentlist]) cnt = len(paymentlist) monthdata = table[str_month] = table.get(str_month) or { 'total': 0, 'datalist': [], 'name': cur_stime.strftime(u"%Y年%m月"), 'count': 0, 'uu': set() } monthdata['count'] += cnt monthdata['uu'] |= uidset useridset_total |= uidset count_total += cnt price = sum( [payment.inum * payment.price for payment in paymentlist]) monthdata['datalist'].append({ 'day': cur_stime.day, 'price': price, 'uu': uidset, 'count': cnt, }) monthdata['total'] += price cur_stime = filters['ctime__lt'] monthlist = table.keys() monthlist.sort() dest['table'] = [table[month] for month in monthlist] dest['total'] = sum([data['total'] for data in dest['table']]) dest['uu'] = useridset_total dest['count'] = count_total return dest
def handle(self, *args, **options): print '================================' print 'recov_takeover' print '================================' is_update = 0 < len(args) and args[0] == 'update' # 修正対象のcardidのリスト. if settings_sub.IS_DEV: tmp_cards = Card.fetchValues(filters={'mid__gte': 23203, 'mid__lte': 23205}) TARGET_CARDID_LIST = [card.id for card in tmp_cards] else: tmp_cards = Card.fetchValues(filters={'mid__gte': 23203, 'mid__lte': 23205}) TARGET_CARDID_LIST = [card.id for card in tmp_cards] # TARGET_CARDID_LIST = ( # 243554710460995, # 259875586181903, # 264149078647399, # 267898585091933, # 289150083275628, # 303770151954557, # 326108276855142, # 2370821955526, # 59785944768327, # 97268124365984, # 164467182686565, # 191985038136826, # 207399675767609, # 207399675767612, # 226937481993457, # 253566279230399, # 298779399950377, # 326348795024926, # 407317518485754, # 425957676551555, # ) # 対象のキャストが本番で公開された時間. CTIME_MIN = DateTimeUtil.strToDateTime('201603181400', "%Y%m%d%H%M") model_mgr = ModelRequestMgr() for cardid in TARGET_CARDID_LIST: # カードを取得. card = Card.getByKey(cardid) if card is None: print '%s...None' % cardid continue cardmaster = BackendApi.get_cardmasters([card.mid], model_mgr).get(card.mid) # このカードのハメ管理履歴を絞り込み. log_dict = {} for model in UserLogEvolution.fetchValues(filters={'uid':card.uid,'ctime__gte':CTIME_MIN}, order_by='ctime'): if cardid == model.data['material']['id']: print '%s...material' % cardid break elif cardid != model.data['base']['id']: continue log_dict[model.data['base']['mid']] = model midlist = BackendApi.get_cardmasterid_by_albumhklevel(model_mgr, cardmaster.album) masters = dict([(model.hklevel, model) for model in BackendApi.get_cardmasters(midlist, model_mgr).values()]) tmp_basecard = None for hklevel in xrange(1, cardmaster.hklevel): basemaster = masters[hklevel] logdata = log_dict[basemaster.id] tmp_basecard = CardSet(tmp_basecard.card if tmp_basecard else Card.makeInstance(cardid), basemaster) tmp_basecard.card.mid = basemaster.id tmp_basecard.card.level = logdata.data['base']['level'] takeover = tmp_basecard.get_evolution_takeover() takeover *= 2 tmp_basecard.card.takeover += takeover if card.takeover == tmp_basecard.card.takeover: print '%s...equal' % cardid continue if is_update: def tr(cardid, master, takeover): card = Card.getByKeyForUpdate(cardid) if master.id != card.mid: # これは危険. raise CabaretError() model_mgr = ModelRequestMgr() card.takeover = takeover; model_mgr.set_save(card) def writeEnd(): BackendApi.save_cardidset(CardSet(card, master)) model_mgr.add_write_end_method(writeEnd) model_mgr.write_all() return model_mgr try: db_util.run_in_transaction(tr, tmp_basecard.id, cardmaster, tmp_basecard.card.takeover).write_end() except CabaretError: print '%s...danger' % cardid continue print '%s...update %s=>%s' % (cardid, card.takeover, tmp_basecard.card.takeover) print '================================' print 'all done..'
def str_to_pkey(cls, st): return DateTimeUtil.datetimeToDate(DateTimeUtil.strToDateTime( st, dtformat="%Y-%m-%d"), logintime=False)
def handle(self, *args, **options): print '================================' print 'create_benchmark_csv' print '================================' USER_ID_START = OSAUtil.BENCH_USER_ID_START USER_NUM = 0 if args: USER_NUM = int(args[0]) USER_NUM = max(OSAUtil.BENCH_USER_ID_NUM, USER_NUM) print '================================' print 'USER_NUM=%d' % USER_NUM LEVEL = 1 GOLD = 100000 GACHA_PT = 3000 CARD_NUM = 100 CARD_LIMIT = CARD_NUM + 50 FRIEND = 50 FRIEND_REQUEST = 50 FRIEND_EMPTY = 50 FRIENDLIMIT = FRIEND + FRIEND_REQUEST * 2 + FRIEND_EMPTY RAID_ENDTIME = DateTimeUtil.strToDateTime("20150101", "%Y%m%d") RAIDLOG = 100 GREETLOG = 100 PRESENT = int(100 / len(Defines.ItemType.PRESENT_TYPES.keys())) PRESENT_LIMITTIME = DateTimeUtil.strToDateTime("20150101", "%Y%m%d") ITEM_RNUM = 50 ITEM_VNUM = 50 DECK_CAPACITY = 1000000 CABARET_TREASURE = 100000 TREASURE_NUM = 20 OUTPUT_DIR = os.path.join(settings_sub.TMP_DOC_ROOT, 'dummy') csvmgr = ModelCSVManager(OUTPUT_DIR) model_mgr = ModelRequestMgr() # 各種マスターデータ. levelexpmaster = model_mgr.get_model(PlayerLevelExpMaster, LEVEL) item_all = model_mgr.get_mastermodel_all(ItemMaster) card_all = [master for master in model_mgr.get_mastermodel_all(CardMaster) if master.ckind == Defines.CardKind.NORMAL and master.hklevel == 1] happeningall = model_mgr.get_mastermodel_all(HappeningMaster) arealist = model_mgr.get_mastermodel_all(AreaMaster, order_by='id')[:2] scoutlist = ScoutMaster.fetchValues(filters={'area__in':[area.id for area in arealist]}, order_by='id') treasure_gold_all = model_mgr.get_mastermodel_all(TreasureGoldMaster) treasure_silver_all = model_mgr.get_mastermodel_all(TreasureSilverMaster) treasure_bronze_all = model_mgr.get_mastermodel_all(TreasureBronzeMaster) now = OSAUtil.get_now() print '================================' print 'players..' class ModelList: def __init__(self): self.modellist_all = [] def add(self, modellist): csvmgr.setModelList(modellist) modellist_all = ModelList() for i in xrange(USER_NUM): modellist = [] uid = i + USER_ID_START # プレイヤー作成. player = self.install(uid) # タイプ決定とか. self.regist(player, levelexpmaster, GOLD, GACHA_PT, FRIENDLIMIT, CARD_LIMIT, DECK_CAPACITY, CABARET_TREASURE) modellist.append(player.getModel(Player)) for model_cls in ModelPlayer.Meta.MODELS: p = player.getModel(model_cls) if p: modellist.append(p) # スカウト完了. for scout in scoutlist: playdata = ScoutPlayData.makeInstance(ScoutPlayData.makeID(uid, scout.id)) playdata.progress = scout.execution modellist.append(playdata) # フレンドの近況. logdata = ScoutClearLog.makeData(player.id, scout.id) modellist.append(logdata) for area in arealist: model = AreaPlayData.makeInstance(AreaPlayData.makeID(uid, area.id)) model.clevel = levelexpmaster.level modellist.append(model) # フレンドの近況. logdata = BossWinLog.makeData(player.id, area.id) modellist.append(logdata) # カード付与. playercard = player.getModel(PlayerCard) cardidlist = [] for _ in xrange(CARD_NUM): playercard.card += 1 cardid = Card.makeID(uid, playercard.card) cardmaster = random.choice(card_all) card = BackendApi.create_card_by_master(cardmaster) card.id = cardid card.uid = uid modellist.append(card) cardidlist.append(cardid) # デッキ設定. deck = Deck() deck.id = uid deck.set_from_array(cardidlist[:Defines.DECK_CARD_NUM_MAX]) modellist.append(deck) # カード獲得フラグ. for cardmaster in card_all: cardacquisition = CardAcquisition.makeInstance(CardAcquisition.makeID(uid, cardmaster.id)) cardacquisition.maxlevel = cardmaster.maxlevel modellist.append(cardacquisition) albumacquisition = AlbumAcquisition.makeInstance(AlbumAcquisition.makeID(uid, cardmaster.album)) modellist.append(albumacquisition) # アイテム. for itemmaster in item_all: item = Item.makeInstance(Item.makeID(uid, itemmaster.id)) item.rnum = ITEM_RNUM item.vnum = ITEM_VNUM modellist.append(item) # レイド履歴. states = (Defines.HappeningState.END, Defines.HappeningState.MISS, Defines.HappeningState.CANCEL) for lognumber in xrange(RAIDLOG): happeningmaster = random.choice(happeningall) raidmaster = BackendApi.get_raid_master(model_mgr, happeningmaster.boss) self.putRaidLog(modellist, player, happeningmaster, raidmaster, states[lognumber % len(states)]) # レイド. happeningmaster = random.choice(happeningall) raidmaster = BackendApi.get_raid_master(model_mgr, happeningmaster.boss) self.putRaid(modellist, player, happeningmaster, raidmaster, RAID_ENDTIME) # プレゼント. def putPresent(itype, itemid, itemvalue): presentlist = BackendApi.create_present(model_mgr, 0, uid, itype, itemid, itemvalue, Defines.TextMasterID.ACCESS_BONUS, PRESENT_LIMITTIME, do_set_save=False) modellist.extend(presentlist) presentlist = BackendApi.create_present(model_mgr, 0, uid, itype, itemid, itemvalue, Defines.TextMasterID.ACCESS_BONUS, now, do_set_save=False) modellist.extend(presentlist) for _ in xrange(PRESENT): putPresent(Defines.ItemType.GOLD, 0, 1000) putPresent(Defines.ItemType.GACHA_PT, 0, 10) putPresent(Defines.ItemType.ITEM, random.choice(item_all).id, 1) putPresent(Defines.ItemType.CARD, random.choice(card_all).id, 1) putPresent(Defines.ItemType.RAREOVERTICKET, 0, 1) putPresent(Defines.ItemType.TRYLUCKTICKET, 0, 1) putPresent(Defines.ItemType.MEMORIESTICKET, 0, 1) putPresent(Defines.ItemType.GACHATICKET, 0, 1) putPresent(Defines.ItemType.GOLDKEY, 0, 1) putPresent(Defines.ItemType.SILVERKEY, 0, 1) # 宝箱. def makeTreasure(masterlist, model_cls, etime): master = random.choice(masterlist) model = model_cls() model.uid = uid model.mid = master.id model.etime = etime modellist.append(model) for _ in xrange(TREASURE_NUM): makeTreasure(treasure_gold_all, TreasureGold, now) makeTreasure(treasure_gold_all, TreasureGold, PRESENT_LIMITTIME) makeTreasure(treasure_silver_all, TreasureSilver, now) makeTreasure(treasure_silver_all, TreasureSilver, PRESENT_LIMITTIME) makeTreasure(treasure_bronze_all, TreasureBronze, now) makeTreasure(treasure_bronze_all, TreasureBronze, PRESENT_LIMITTIME) modellist_all.add(modellist) print 'complete uid=%d' % uid print '================================' print 'friends..' # ユーザーがそろっていないと作れないレコード. for i in xrange(USER_NUM): modellist = [] uid = i + USER_ID_START # フレンド設定. self.putFriends(modellist, uid, USER_ID_START, USER_NUM, FRIEND, FRIEND_REQUEST) # あいさつ履歴. fid = uid for _ in xrange(GREETLOG): fid = ((fid - USER_ID_START + 1) % USER_NUM) + USER_ID_START while fid == uid: fid = ((fid - USER_ID_START + 1) % USER_NUM) + USER_ID_START model = GreetLog() model.fromid = fid model.toid = uid modellist.append(model) modellist_all.add(modellist) print 'complete uid=%d' % uid csvmgr.output() print '================================' print 'all done..'
def work(self, model_cls, target_date, overwrite_sp=True, overwrite_pc=True): self.__logs.append('overwrite_sp=%s,overwrite_pc=%s' % (overwrite_sp, overwrite_pc)) s_date = target_date - datetime.timedelta(seconds=7200) e_date = target_date + datetime.timedelta(days=1, seconds=2700) str_target_date = target_date.strftime(Handler.TARGET_DATE_FORMAT) filters = { 'state': PaymentData.Status.COMPLETED, 'ctime__gte': s_date, 'ctime__lt': e_date, } LIMIT = PaymentLogRequestData.ENTRY_NUM_MAX offset = 0 overwrite_flags = { 'sp': overwrite_sp, 'pc': overwrite_pc, } request_key_format = target_date.strftime( 'PaymentLog:%Y%m%d:{device}:{offset}') post_nums = { str_target_date: { 'sp': 0, 'pc': 0, } } def addPostNum(executedtime, device, cnt=1): str_date = executedtime.strftime(Handler.TARGET_DATE_FORMAT) nums = post_nums[str_date] = post_nums.get(str_date) or { 'sp': 0, 'pc': 0, } nums[device] += cnt while True: modellist = model_cls.fetchValues(['id', 'uid', 'price', 'inum'], filters=filters, limit=LIMIT, offset=offset, order_by='ctime', using=settings.DB_READONLY) if len(modellist) < 1: break requestdata_table = {} def getRequestData(device, executedtime): str_date = executedtime.strftime(Handler.TARGET_DATE_FORMAT) if str_target_date != str_date: # 当日のレコードのみにする. return None requestdata = requestdata_table.get(device) if requestdata is None: requestdata = PaymentLogRequestData( executedtime, device, overwrite_flags[device]) requestdata_table[device] = requestdata return requestdata model_mgr = ModelRequestMgr() for model in modellist: # PC版をリリース前にPaymentEntryにdevice判定用のカラムを付けた方がいいかも.->と思ったけど結局executedTimeを取らなきゃいけなくなったのでこのままで. player = BackendApi.get_player(self, model.uid, [], using=settings.DB_READONLY, model_mgr=model_mgr) record = BackendApi.get_restful_paymentrecord( self, model.id, player.dmmid) is_pc = False if not str(record.paymentItems[0].itemId).isdigit(): # 無理やりだけど.. is_pc = True executedtime = record.executeTime if not isinstance(executedtime, datetime.datetime): executedtime = DateTimeUtil.strToDateTime( executedtime, "%Y-%m-%d %H:%M:%S") device = 'pc' if is_pc else 'sp' requestdata = getRequestData(device, executedtime) if requestdata: requestdata.addPaymentEntry(model.id, model.price, model.inum) self.__logs.append(u'%s' % model.id) addPostNum(executedtime, device) for requestdata in requestdata_table.values(): if len(requestdata.paymentList) < 1: continue request = self.osa_util.makeApiRequest(ApiNames.PaymentLog, requestdata) reqkey = request_key_format.format(device=requestdata.device, offset=offset) self.addAppApiRequest(reqkey, request) overwrite_flags[requestdata.device] = False ret_data = self.execute_api() if ret_data: try: for reqkey in ret_data.keys(): response_data = ret_data[reqkey].get() if not response_data['is_success']: raise AppError('PaymentLogApi Error:%s:data=%s' % (response_data['message'], response_data['data'])) except urllib2.HTTPError, er: if er.fp is None: error_message = str(er) else: error_message = er.read() error_message = 'HttpError:%s' % error_message self.addlogerror('PaymentLog Failure:%s' % error_message) self.send(200, error_message) return except AppError, er: error_message = 'AppError:%s' % er.value self.addlogerror('PaymentLog Failure:%s' % error_message) self.send(200, error_message) return except Exception: DbgLogger.write_error(self.osa_util.logger.to_string()) raise
def _proc_view_record(self): """シリアルコードのレコード情報を表示. """ CONTENT_NUM_PER_PAGE = 100 # ページング. page = int(self.request.get('_page') or 0) # 検索条件を取得. serchtype = self.request.get('_serchtype') # 検索する日付. str_target_date = self.request.get('_date') # 検索用の値を取得. value = self.request.get('_value') or '' mid = self.request.get('_mid') or '' shareserial = self.request.get('_share') == '1' int_value = None if value.isdigit(): int_value = int(value) self.html_param['_serchtype'] = serchtype self.html_param['_date'] = str_target_date self.html_param['_value'] = value self.html_param['_mid'] = mid self.html_param['shareserial'] = shareserial # シリアルコードの検索条件. filters = None if serchtype == 'uid': if int_value: filters = { 'uid' : int_value, } elif serchtype == 'dmmid': if value: uid = BackendApi.dmmid_to_appuid(self, [value], using=backup_db).get(value) if uid: filters = { 'uid' : uid, } elif serchtype == 'serial': if value: arr = list(set(value.split(','))) filters = { 'serial__in' : arr, } elif serchtype == 'mid': target_date = None if str_target_date: try: target_date = DateTimeUtil.strToDateTime(str_target_date, "%Y-%m-%d") except: pass if target_date is None: self.putAlertToHtmlParam(u'日付はyyyy-mm-ddで入力してください', AlertCode.ERROR) return if mid and mid.isdigit(): mid = int(mid) master = BackendApi.get_serialcampaign_master(self.getModelMgr(), mid, using=backup_db) if master and master.share_serial == shareserial: filters = { 'mid' : mid, 'itime__gte' : target_date, 'itime__lt' : target_date + datetime.timedelta(days=1), } # シリアルコードを取得. serialcode_list = None has_next = False if filters: offset = page * CONTENT_NUM_PER_PAGE limit = CONTENT_NUM_PER_PAGE + 1 model_cls = ShareSerialLog if shareserial else SerialCode serialcode_list = model_cls.fetchValues(filters=filters, order_by='-itime', limit=limit, offset=offset, using=backup_db) has_next = CONTENT_NUM_PER_PAGE < len(serialcode_list) serialcode_list = serialcode_list[:CONTENT_NUM_PER_PAGE] # 見つからなかった. if not serialcode_list: self.putAlertToHtmlParam(u'シリアルコードが見つかりませんでした', AlertCode.WARNING) return # テーブルのタイトル. self.__init_table(u'シリアルコード情報') self.__add_table_title('mid', u'キャンペーンID') self.__add_table_title('user', u'ユーザ') self.__add_table_title('serial', u'シリアルコード') self.__add_table_title('itime', u'入力した時間') self.__add_table_title('point', u'生涯課金額') self.__add_table_title('paymentlog', u'入力後2ヶ月間の購入履歴') # テーブルの作成. uidlist = list(set([serialcode.uid for serialcode in serialcode_list if 0 < serialcode.uid])) playerpoint_dict = dict([(model.id, model.point_total) for model in PlayerConsumePoint.getByKey(uidlist, using=backup_db)]) url_paymentlog = OSAUtil.addQuery(UrlMaker.view_paymentlog(), '_logtype', 'gacha') url_paymentlog = OSAUtil.addQuery(url_paymentlog, '_is_complete', '1') url_paymentlog = OSAUtil.addQuery(url_paymentlog, '_serchtype', 'uid') for serialcode in serialcode_list: if serialcode.uid: url = UrlMaker.view_player(serialcode.uid) celldata_user = self.__make_table_celldata(serialcode.uid, self.makeAppLinkUrl(url)) stime = serialcode.itime etime = serialcode.itime + datetime.timedelta(days=60) url = OSAUtil.addQuery(url_paymentlog, '_value', serialcode.uid) url = OSAUtil.addQuery(url, '_stime', urllib.quote(stime.strftime('%Y/%m/%d %H:%M:%S'), '')) url = OSAUtil.addQuery(url, '_etime', urllib.quote(etime.strftime('%Y/%m/%d %H:%M:%S'), '')) celldata_paymentlog = self.__make_table_celldata(u'購入履歴≫', self.makeAppLinkUrl(url)) else: celldata_user = self.__make_table_celldata(u'未入力') celldata_paymentlog = self.__make_table_celldata(u'----') row = { 'mid' : self.__make_table_celldata(serialcode.mid), 'user' : celldata_user, 'serial' : self.__make_table_celldata(serialcode.serial), 'itime' : self.__make_table_celldata(serialcode.itime.strftime("%Y/%m/%d %H:%M:%S")), 'point' : self.__make_table_celldata(playerpoint_dict.get(serialcode.uid, 0)), 'paymentlog' : celldata_paymentlog, } self.__add_table_data(row) # ページング. url_prev = None url_next = None page_query_params = { '_proc' : 'view_record', '_serchtype' : serchtype, '_value' : value, } if 0 < page: url_prev = self.__make_url_self(_page=page-1, **page_query_params) if has_next: url_next = self.__make_url_self(_page=page+1, **page_query_params) self.html_param['url_prev'] = url_prev self.html_param['url_next'] = url_next
def handle(self, *args, **options): print '================================' print 'aggregate_cabaretclub_weekly' print '================================' last_week_starttime = BackendApi.to_cabaretclub_section_starttime( OSAUtil.get_now() - datetime.timedelta(days=7)) str_year_and_week = args[0] if 0 < len(args) else None if str_year_and_week: week = int(str_year_and_week[4:]) first_of_year = DateTimeUtil.strToDateTime( "%s%02d" % (str_year_and_week[:4], Defines.CABARETCLUB_EVENT_DATE_CHANGE_TIME), "%Y%H") # 0週目. zero = BackendApi.to_cabaretclub_section_starttime(first_of_year) starttime = zero + datetime.timedelta(days=week * 7) if last_week_starttime < starttime: print u'未完了の週なので集計は行えません' return else: # 指定がない場合は前回の週. starttime = last_week_starttime print "target:%s" % starttime.strftime("%Y%W") endtime = BackendApi.to_cabaretclub_section_endtime(starttime) section_lasttime = endtime - datetime.timedelta(microseconds=1) model_mgr = ModelRequestMgr() self.update_eventconfig_previous_mid(model_mgr, starttime) # 店舗のマスターデータ. cabaclubstoremaster_dict = dict([ (cabaclubstoremaster.id, cabaclubstoremaster) for cabaclubstoremaster in model_mgr.get_mastermodel_all( CabaClubStoreMaster, fetch_deleted=True, using=backup_db) ]) # ユーザIDの最大値. uid_max = PlayerTreasure.max_value('id', using=backup_db) for uid in xrange(1, uid_max + 1): # 所持している店舗.ここはreadonlyで大丈夫. store_list = CabaClubStorePlayerData.fetchByOwner( uid, using=settings.DB_READONLY) if store_list: # この週に更新された店舗数. update_store_cnt = 0 # Activeな店舗を週の終了時間まですすめる. for store in store_list: cabaclubstoremaster = cabaclubstoremaster_dict[store.mid] if not store.is_open: # 閉じるときに集計しているので必要なし. if starttime <= store.utime: update_store_cnt += 1 continue store_set = CabaclubStoreSet(cabaclubstoremaster, store) lasttime = min( section_lasttime, store_set.get_limit_time() - datetime.timedelta(microseconds=1)) if (lasttime - store.utime).total_seconds( ) < cabaclubstoremaster.customer_interval: # 獲得時間が経過していないので更新する必要が無い. if starttime <= store.utime: update_store_cnt += 1 continue def tr_advance_the_time(uid, cabaclubstoremaster, now): """店舗の時間をすすめる. """ model_mgr = ModelRequestMgr() BackendApi.tr_cabaclubstore_advance_the_time_with_checkalive( model_mgr, uid, cabaclubstoremaster, now) model_mgr.write_all() model_mgr.write_end() try: db_util.run_in_transaction(tr_advance_the_time, uid, cabaclubstoremaster, lasttime) except CabaretError, err: if err.code == CabaretError.Code.ALREADY_RECEIVED: # ユーザー自信が更新した可能性. pass else: DbgLogger.write_error(err.value) raise update_store_cnt += 1 if 0 < update_store_cnt: # 売り上げに応じた名誉ポイントを配布. def tr_send_point(uid, starttime): """名誉ポイントの配布. """ model_mgr = ModelRequestMgr() scoredata_weekly = CabaClubScorePlayerDataWeekly.getByKeyForUpdate( CabaClubScorePlayerDataWeekly.makeID( uid, starttime)) if scoredata_weekly is None or scoredata_weekly.flag_aggregate: return 0 # 配布する数を計算. cabaclub_honor = int( math.ceil(scoredata_weekly.proceeds / 1000.0)) if 0 < cabaclub_honor: # 報酬付与. prizedata = PrizeData.create( cabaclub_honor=cabaclub_honor) BackendApi.tr_add_prize( model_mgr, uid, [prizedata], Defines.TextMasterID.CABARETCLUB_WEEKLY_PRIZE) # 重複防止. scoredata_weekly.flag_aggregate = True model_mgr.set_save(scoredata_weekly) model_mgr.write_all() model_mgr.write_end() return cabaclub_honor cabaclub_honor = db_util.run_in_transaction( tr_send_point, uid, starttime) print '%s...honor=%d' % (uid, cabaclub_honor) else: print '%s...not updated' % uid
def to_datetime(st): try: return DateTimeUtil.strToDateTime(st, '%Y/%m/%d %H:%M:%S') except: return None
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
def handle(self, *args, **options): print '================================' print 'recov_present' print '================================' IS_TEST = args[0] != 'write' # 問題の発生時間. # targetstime = DateTimeUtil.strToDateTime("2014-06-13 00:00:00", "%Y-%m-%d %H:%M:%S") print 'TEST_MODE=%s' % IS_TEST """間違えて配った新店舗ランキング報酬を削除. とりあえずredisだけ.MySQLは直接消す. """ targetstime = DateTimeUtil.strToDateTime("2014-11-18 15:00:00", "%Y-%m-%d %H:%M:%S") for present in Present.fetchValues(['id', 'toid', 'itype'], { 'textid': 144, 'ctime__gte': targetstime }): BackendApi.remove_present(present.toid, present.id, present.itype) print 'delete...(%s,%s,%s)' % (present.toid, present.id, present.itype) # worked = (660,1661,3581,3720,8126,9614,16668,17376,17509,21214,22047,24504,24561,28933,29917,30368,32027,32498,32769,33609,34236,34841,40884,41124,42399,43762,44215,48391,48677,49798,50201,51676,52670,53295,55290,55910,56477,56838,57510,58601,59730,60412,63282,67219,69693,73282,73500,75072,78939,82382,83309,85689,86435,88635,90980,94654,99140,99325,103059,105616,105626,105964,111016,112823,114409,120378,121419,134001,134259,135012,136129,139024,139036,139055,139057,139066,139088,139115,139116,139121,139151,139159,139162,139200,139323,139331,139332,139335,139364,139367,139386,139451,139453,139523,139540,139582,139583,139606,139610,139618,139625,139627,139675,139694,139703,139721,139722,139727,139733,139746,139815,139820,139850,139854,139857,139871,139892,139912,139932,139970,140006,140047,140054,140061,140070,140076,140113,140117,140160,140175,140189,140224,140233,140240,140266,140328,140329,140363,140366,140412,140418,140419,140453,140459,140475,140493,140503,140518,140557,140612,140618,140644,140646,140666,140671,140692,140695,140735,140739,140743,140775,140792,140809,140842,140871,140884,140888,140892,140893,140897,140939,140985,140986,140993,141006,141015,141030,141051,141064,141074,141109,141130,141139,141161,141175,141182,141197,141203,141211,141221,141225,141227,141229,141249,141284,141292,141332,141346,141351,141368,141400,141414,141444,141462,141533,141541,141542,141578,141583,141585,141604,141703,141708,141719,141736,141754,141762,141783,141792,141794,141795,141796,141810,141817,141818,141834,141844,141867,141891,141893,141901) # # if settings_sub.IS_DEV: # LIMIT = 1 # else: # LIMIT = 500 # itemid = Defines.ItemEffect.CARD_BOX_EXPANSION # # """ # ・全プレID:10を受け取ったユーザーのアイテム所持数を1個減らす。減らせない場合はプレゼントを削除。 # ・2014-06-13 00:00:00以降に全プレID:9を受け取ったユーザーのアイテム所持数を4個増やす。 # """ # # # 全プレID:10を受け取ったユーザーのアイテム所持数を1個減らす。減らせない場合はプレゼントを削除. # offset = 0 # filters = { # 'mid' : 10, # } # # unable_nums = {} # # print 'start ID=10' # while True: # modellist = PresentEveryoneReceiveMypage.fetchValues(filters=filters, order_by='id', limit=LIMIT, offset=offset) # if not modellist: # break # # delete_num = 0 # for model in modellist: # uid = model.uid # # # 所持数確認. # item = Item.getByKey(Item.makeID(uid, itemid)) # if item and 0 < item.vnum: # if not IS_TEST: # def tr_item(modelid, uid, itemid): # # 所持数を減らす. # model_mgr = ModelRequestMgr() # BackendApi.tr_add_item(model_mgr, uid, itemid, -1) # # # 受け取りフラグを消す. # model = PresentEveryoneReceiveMypage.getByKeyForUpdate(modelid) # model_mgr.set_delete(model) # # model_mgr.write_all() # return model_mgr # db_util.run_in_transaction(tr_item, model.id, uid, itemid).write_end() # delete_num += 1 # print '%s=>item' % uid # else: # # プレゼントを探す. # present = Present.getValues(filters={'toid':uid,'itype':Defines.ItemType.ITEM,'ivalue':itemid,'inum':1}) # if present is None: # # ここに来るのは受取済みで使用済み. # unable_nums[uid] = 1 # print 'unable %s' % uid # else: # if not IS_TEST: # def tr_present(modelid, uid, presentid): # model_mgr = ModelRequestMgr() # # # プレゼントを消す. # present = Present.getByKeyForUpdate(presentid) # model_mgr.set_delete(present) # # # 受け取りフラグを消す. # model = PresentEveryoneReceiveMypage.getByKeyForUpdate(modelid) # model_mgr.set_delete(model) # # def writeEnd(): # BackendApi.remove_present(uid, presentid) # model_mgr.add_write_end_method(writeEnd) # # model_mgr.write_all() # return model_mgr # db_util.run_in_transaction(tr_present, model.id, uid, present.id).write_end() # delete_num += 1 # print '%s=>present %d' % (uid, present.id) # offset += LIMIT - delete_num # # 2014-06-13 00:00:00以降に全プレID:9を受け取ったユーザーのアイテム所持数を4個増やす. # offset = 0 # filters = { # 'mid' : 9, # 'rtime__gte' : targetstime, # } # print 'start ID=9' # while True: # modellist = PresentEveryoneReceiveMypage.fetchValues(filters=filters, order_by='id', limit=LIMIT, offset=offset) # offset += LIMIT # if not modellist: # break # # uidlist = list(set([model.uid for model in modellist])) # for uid in uidlist: # add_num = 4 - unable_nums.get(uid, 0) # if not IS_TEST: # def tr(uid, itemid, add_num): # model_mgr = ModelRequestMgr() # BackendApi.tr_add_item(model_mgr, uid, itemid, add_num) # model_mgr.write_all() # return model_mgr # db_util.run_in_transaction(tr, uid, itemid, add_num).write_end() # print 'add item:%s=>%d' % (uid, add_num) # # # 2014-05-23 16:00:00以降に全プレID:7を受け取ったユーザーのアイテム所持数を1個減らす.減らせない場合はプレゼントを消す. # targetstime = DateTimeUtil.strToDateTime("2014-05-23 16:00:00", "%Y-%m-%d %H:%M:%S") # # offset = 0 # filters = { # 'mid' : 7, # 'rtime__gte' : targetstime, # } # print 'start ID=7' # while True: # modellist = PresentEveryoneReceiveMypage.fetchValues(filters=filters, order_by='id', limit=LIMIT, offset=offset) # if not modellist: # break # # delete_num = 0 # for model in modellist: # uid = model.uid # if uid in worked: # # 処理済み. # continue # # # 所持数確認. # item = Item.getByKey(Item.makeID(uid, itemid)) # if item and 0 < item.vnum: # if not IS_TEST: # def tr_item(modelid, uid, itemid): # # 所持数を減らす. # model_mgr = ModelRequestMgr() # BackendApi.tr_add_item(model_mgr, uid, itemid, -1) # # # 受け取りフラグを消す. # model = PresentEveryoneReceiveMypage.getByKeyForUpdate(modelid) # model_mgr.set_delete(model) # # model_mgr.write_all() # return model_mgr # db_util.run_in_transaction(tr_item, model.id, uid, itemid).write_end() # delete_num += 1 # print '%s=>item' % uid # else: # # プレゼントを探す. # present = Present.getValues(filters={'toid':uid,'itype':Defines.ItemType.ITEM,'ivalue':itemid,'inum':1}) # if present is None: # # ボックス上限を減らす. # if not IS_TEST: # def tr_player(modelid, uid): # model_mgr = ModelRequestMgr() # # player = PlayerDeck.getByKeyForUpdate(uid) # player.cardlimititem = max(0, player.cardlimititem - 20) # model_mgr.set_save(player) # # # 受け取りフラグを消す. # model = PresentEveryoneReceiveMypage.getByKeyForUpdate(modelid) # model_mgr.set_delete(model) # # model_mgr.write_all() # return model_mgr # db_util.run_in_transaction(tr_player, model.id, uid).write_end() # delete_num += 1 # print 'box %s' % uid # else: # if not IS_TEST: # def tr_present(modelid, uid, presentid): # model_mgr = ModelRequestMgr() # # # プレゼントを消す. # present = Present.getByKeyForUpdate(presentid) # model_mgr.set_delete(present) # # # 受け取りフラグを消す. # model = PresentEveryoneReceiveMypage.getByKeyForUpdate(modelid) # model_mgr.set_delete(model) # # def writeEnd(): # BackendApi.remove_present(uid, presentid) # model_mgr.add_write_end_method(writeEnd) # # model_mgr.write_all() # return model_mgr # db_util.run_in_transaction(tr_present, model.id, uid, present.id).write_end() # delete_num += 1 # print '%s=>present %d' % (uid, present.id) # offset += LIMIT - delete_num print '================================' print 'all done..'
def handle(self, *args, **options): print '================================' print 'support' print '================================' # 出力先. path = OSAUtil.get_now().strftime(args[0]) # 書き込むデータをここに溜め込む. writer = Command.Writer(path) # レイドマスター. model_mgr = ModelRequestMgr() raid_all = dict([(master.id, master) for master in model_mgr.get_mastermodel_all(RaidMaster, using=settings.DB_READONLY)]) eventraid_all = dict([(master.mid, master) for master in model_mgr.get_mastermodel_all(RaidEventRaidMaster, using=settings.DB_READONLY)]) # 対象のユーザ. UIDLIST = [16268, 29339] UIDSET = set(UIDLIST) UNKNOWNS = [ 56272661512882, 56272661512893, 87759066759449, 99127845191766, 128943508160593, 136047384068178, 137099651055617, 137550622621716, 143374598275073, 149615185756161, 157689724272723, 165957536317441, 172352742621192, 183549722361857, 193870528774147, ] # 対象の時間. filters = { 'ctime__gte' : DateTimeUtil.strToDateTime("2014-01-07 15:00:00", "%Y-%m-%d %H:%M:%S"), 'ctime__lt' : DateTimeUtil.strToDateTime("2014-01-13 19:00:00", "%Y-%m-%d %H:%M:%S"), 'hp' : 0, } LIMIT = 1000 offset = 0 timebonus_time_min = DateTimeUtil.strToDateTime("2014-01-13 17:00:00", "%Y-%m-%d %H:%M:%S") timebonus_time_max = DateTimeUtil.strToDateTime("2014-01-13 19:00:00", "%Y-%m-%d %H:%M:%S") # 対象のハプニング. while True: raidlist = Raid.fetchValues(filters=filters, order_by='id', limit=LIMIT, offset=offset) for raid in raidlist: raidboss = RaidBoss(raid, raid_all[raid.mid], eventraid_all.get(raid.mid)) if raid.id in UNKNOWNS: print raid.id uidset = set(raidboss.getDamageRecordUserIdList()) targetlist = list(UIDSET & uidset) if not targetlist: continue helppoints = raidboss.getHelpEventPoints() for uid in targetlist: owner = 0 mvp = 0 helppoint = 0 if uid == raidboss.raid.oid: # 発見者報酬. owner = raidboss.get_owner_eventpoint() else: # 協力者報酬. helppoint = helppoints.get(uid, 0) # MVP報酬. mvpuidlist = raidboss.getMVPList() for mvpuid in mvpuidlist: if uid == mvpuid: mvp += raidboss.get_mvp_eventpoint() if not (owner or mvp or helppoint): print raidboss.id else: text = '%s,%s,%s,%s,%s' % (uid, owner, mvp, helppoint, raid.ctime.strftime("%Y-%m-%d %H:%M")) writer.add(text) # print text if len(raidlist) < LIMIT: break offset += LIMIT writer.output(overwrite=False) print '================================' print 'all done..'