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): """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 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('/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 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 _save(self, pipe): redisdb = self.getDB() strdata = redisdb.hget(self.__class__.__name__, self.uid) data = None if strdata: try: data = cPickle.loads(strdata) if not isinstance(data, dict): data = None except: pass data = data or {} str_now = DateTimeUtil.dateTimeToStr(self.now) if data.has_key(self.gachaid): data[self.gachaid]['date'] = str_now else: items = list(data.items()) if self.__class__.RECORD_NUM_MAX <= len(items): # レコードの最大数を超えている. items.sort(key=lambda x: x[1]['date']) data = dict(items[1:]) data[self.gachaid] = { 'card': self.leadercard_mid, 'date': str_now, } strdata = cPickle.dumps(data) pipe.hset(self.__class__.__name__, self.uid, strdata)
def getPaymentFromCache(self, mid, stime, now): if DateTimeUtil.toBaseTime(now, 0) <= stime: return None client = localcache.Client() key = "view_gacha_payment_proceeds:%s:%s" % (mid, stime.strftime("%Y%m%d")) return client.get(key)
def check(self): url = self.response.get('redirect_url') if not url: raise AppTestError(u'リダイレクト先が設定されていない') elif url.find('/battleeventtop/') == -1: raise AppTestError(u'イベントTOPに遷移していない') model_mgr = ModelRequestMgr() rankrecord = BackendApi.get_battleevent_rankrecord(model_mgr, self.__eventmaster.id, self.__player0.id) if rankrecord is None: raise AppTestError(u'ランク情報が保存されていない') elif not rankrecord.groups: raise AppTestError(u'グループが設定されていない') groupid = rankrecord.groups[-1] group = BackendApi.get_battleevent_group(model_mgr, groupid) logintime = DateTimeUtil.toLoginTime(OSAUtil.get_now()) today = datetime.date(logintime.year, logintime.month, logintime.day) if group is None: raise AppTestError(u'グループが存在しない') elif not self.__player0.id in group.useridlist: raise AppTestError(u'グループに参加設定されていない') elif not self.__player0.id in group.useridlist: raise AppTestError(u'グループに参加設定されていない') elif group.cdate != today: raise AppTestError(u'グループの日付がおかしい')
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 setPaymentToCache(self, paymentlist, mid, stime, now): if DateTimeUtil.toBaseTime(now, 0) <= stime: return None client = localcache.Client() key = "view_gacha_payment_proceeds:%s:%s" % (mid, stime.strftime("%Y%m%d")) client.set(key, paymentlist)
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 __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 get_data(self): config_cls_list = (CurrentRaidEventConfig, CurrentScoutEventConfig, CurrentBattleEventConfig) # 各configの期間を見る. for config_cls in config_cls_list: config = config_cls.getByKey(config_cls.SINGLE_ID, using=backup_db) if config is None or config.mid < 1: continue s_time = DateTimeUtil.toBaseTime(config.starttime, 0) e_time = DateTimeUtil.toBaseTime( config.endtime + datetime.timedelta(days=1), 0) if s_time <= self.date < e_time: return self.get_data_by_range(s_time, e_time) return None
def getTodayCount(self): """今日の挨拶回数を取得. """ now = OSAUtil.get_now() if DateTimeUtil.judgeSameDays(self.ltime, now): return self.today else: return 0
def __procGoukon(self, eventmaster): """合コンバトルイベント. """ model_mgr = self.getModelMgr() eventid = eventmaster.id basetime = DateTimeUtil.toLoginTime(OSAUtil.get_now()) cdate = datetime.date(basetime.year, basetime.month, basetime.day) cur_group = self.getCurrentBattleGroup(do_search_log=False) # 設定済みの場合はイベントTOPへリダイレクト. if cur_group and cur_group.cdate == cdate: url = UrlMaker.battleevent_top(eventmaster.id) self.appRedirect(self.makeAppLinkUrlRedirect(url)) return # 最大ランク. config = BackendApi.get_current_battleeventconfig( model_mgr, using=settings.DB_READONLY) # 公開中のランク. rankmaster_list = BackendApi.get_battleevent_rankmaster_by_eventid( model_mgr, eventid, using=settings.DB_READONLY) rankmaster_list.sort(key=lambda x: x.rank) # 未設定で引数がある場合は書き込み. rank = str(self.request.get(Defines.URLQUERY_ID)) if rank.isdigit(): rank = int(rank) # ランクの公開確認. target_rankmaster = None for rankmaster in rankmaster_list: if rankmaster.rank == rank: target_rankmaster = rankmaster break if target_rankmaster: # 登録書き込み. v_player = self.getViewerPlayer() uid = v_player.id try: db_util.run_in_transaction(self.tr_write, config, eventmaster, uid, v_player.level, rankmaster_list, rank).write_end() except CabaretError, err: if err.code == CabaretError.Code.ALREADY_RECEIVED: pass elif settings_sub.IS_DEV: raise else: url = UrlMaker.mypage() self.appRedirect(self.makeAppLinkUrlRedirect(url)) return # 書き込み後はイベントTOPへ. url = UrlMaker.battleevent_top(eventmaster.id) self.appRedirect(self.makeAppLinkUrlRedirect(url)) return
def __set_save_event_play(self, uid, now, is_pc): """日別イベントプレイ数. イベントポイントを自分で稼いだユーザ数. """ self.__set_save( EventPlayDaily.create( DateTimeUtil.toLoginTime(now or OSAUtil.get_now()), uid, is_pc)) return self
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 __set_save_event_join(self, uid, now, is_pc): """日別イベント参加数. イベントTOPとルール説明を見たUU. """ self.__set_save( EventJoinDaily.create( DateTimeUtil.toLoginTime(now or OSAUtil.get_now()), uid, is_pc)) return self
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 addCount(self, cnt=1): """あいさつ回数を加算. """ now = OSAUtil.get_now() if not DateTimeUtil.judgeSameDays(self.ltime, now): self.yesterday = self.today self.today = 0 self.today += cnt self.total += cnt self.ltime = now
def set_increment_battleevent_member_count(self, rank, cnt=1, now=None): """バトルイベントランク別所属人数. """ logintime = DateTimeUtil.toLoginTime(now or OSAUtil.get_now()) def func(pipe): BattleEventMemberCount.incrby(logintime, rank, cnt, pipe) self.__append_process(BattleEventMemberCount.getDBName(), func) return self
def putFreeGachaFlag(self): """無料ガチャを引けるか. """ model_mgr = self.getModelMgr() v_player = self.getViewerPlayer() lasttime = BackendApi.get_freegachalasttime(v_player.id, model_mgr, using=settings.DB_READONLY) if not DateTimeUtil.judgeSameDays(OSAUtil.get_now(), lasttime): self.html_param['free_gacha'] = 1 self.__news_num += 1 url = OSAUtil.addQuery(UrlMaker.gacha(), Defines.URLQUERY_CTYPE, Defines.GachaConsumeType.GachaTopTopic.FREE) self.html_param['url_gacha'] = self.makeAppLinkUrl(url)
def get_data(self): """ユーザごとのガチャデータ. """ # 7日前. s_time = DateTimeUtil.toBaseTime(self.date - datetime.timedelta(days=7), 0) e_time = self.date # 過去1週間以内にログインしたユーザー. str_uidlist = WeeklyLoginSet.getUserIdListByRange(s_time, e_time) # 対象のガチャ. filters = { 'consumetype__in' : Defines.GachaConsumeType.PAYMENT_TYPES, } gachamasterlist = GachaMaster.fetchValues(filters=filters, order_by='id', using=backup_db) model_mgr = ModelRequestMgr() def checkSchedule(gachamaster): 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)): # 期間外. return False return True midlist = [gachamaster.id for gachamaster in gachamasterlist if checkSchedule(gachamaster)] self.__midlist = midlist redisdb = GachaLastStepSortSet.getDB() result = [] if midlist: for str_uid in str_uidlist: if not str_uid or not str(str_uid).isdigit(): continue uid = int(str_uid) tmp_model_mgr = ModelRequestMgr() idlist = [GachaPlayCount.makeID(uid, mid) for mid in midlist] # 回転数. countdict = BackendApi.get_model_dict(tmp_model_mgr, GachaPlayCount, idlist, using=backup_db, key=lambda x:x.mid) # 課金額. paydict = BackendApi.get_model_dict(tmp_model_mgr, GachaConsumePoint, idlist, using=backup_db, key=lambda x:x.mid) for mid in midlist: if not countdict.get(mid): continue cnt = countdict[mid].cnttotal pay = paydict[mid].point if paydict.get(mid) else 0 step = redisdb.zscore(GachaLastStepSortSet.makeKey(self.date, mid), uid) or 0 result.append((uid, mid, cnt, pay, step)) return result
def set_save_battleevent_result(self, uid, rank, grouprank, point, now=None): """イベント結果. """ logintime = DateTimeUtil.toLoginTime(now or OSAUtil.get_now()) self.__set_save( BattleEventResult.create(logintime, uid, rank, grouprank, point)) return self
def set_save_shop_buy(self, uid, is_pc, point, now=None): """日別イベントショップ購入数と消費ポイント. """ logintime = DateTimeUtil.toLoginTime(now or OSAUtil.get_now()) # 購入数. self.__set_save(EventShopPaymentUUDaily.create(logintime, uid, is_pc)) # 消費ポイント. def func(pipe, uid, date, point, is_pc): EventShopPaymentPointDaily.incrby(date, point, is_pc, pipe) DailyPaymentPointSet.incrby(uid, date, point, pipe) self.__append_process(EventShopPaymentPointDaily.getDBName(), func, uid, logintime, point, is_pc) return self
def process(self): args = self.getUrlArgs('/battleeventgrouplog/list/') eventid = args.getInt(0) model_mgr = self.getModelMgr() eventmaster = None if eventid: eventmaster = BackendApi.get_battleevent_master( model_mgr, eventid, using=settings.DB_READONLY) if eventmaster is None: self.redirectToTop() return cur_eventmaster = self.getCurrentBattleEvent(quiet=True) v_player = self.getViewerPlayer() uid = v_player.id basetime = DateTimeUtil.toLoginTime(OSAUtil.get_now()) cdate_max = datetime.date(basetime.year, basetime.month, basetime.day) if cur_eventmaster and cur_eventmaster.id == eventid: cdate_max -= datetime.timedelta(days=1) # グループ履歴ID. rankrecord = BackendApi.get_battleevent_rankrecord( model_mgr, eventid, uid, using=settings.DB_READONLY) obj_list = [] if rankrecord and rankrecord.groups: groupidlist = rankrecord.groups[:] num = len(groupidlist) for idx in xrange(num): obj = self.makeRankRecordObj(rankrecord, groupidlist[-(idx + 1)], logonly=True, cdate_max=cdate_max) if obj: obj_list.append(obj) self.html_param['battleevent_rank_list'] = obj_list self.putEventTopic(eventmaster.id) if eventmaster.is_goukon: self.writeAppHtml('gcevent/rankloglist') else: self.writeAppHtml('btevent/rankloglist')
def getCurrentBattleGroup(self, do_search_log=False): """現在発生中のイベントで参加しているグループを取得. """ if self.__current_event_group is None: basetime = DateTimeUtil.toLoginTime(OSAUtil.get_now()) cdate = datetime.date(basetime.year, basetime.month, basetime.day) rankrecord = self.getCurrentBattleRankRecord() if rankrecord and rankrecord.groups: model_mgr = self.getModelMgr() groupid = rankrecord.groups[-1] group = BackendApi.get_battleevent_group(model_mgr, groupid, using=settings.DB_READONLY) if do_search_log and (group is None or group.cdate != cdate): grouplog_dict = BackendApi.get_battleevent_grouplog_dict(model_mgr, rankrecord.groups, using=settings.DB_READONLY) for groupid in rankrecord.groups[::1]: group = grouplog_dict.get(groupid) if group: break self.__current_event_group = group return self.__current_event_group
def to_dict(self): """DBへ保存するために辞書にする. keyはコンストラクタの引数の名前. """ data = { 'damage': self.__damage, 'cnt': self.__damage_cnt, 'number': self.__number, 'feverendtime': DateTimeUtil.dateTimeToStr(self.__feverendtime), } if self.champagne: data['champagne'] = 1 if self.champagne_num_add: data.update(champagne_post=self.champagne_num_post, champagne_add=self.champagne_num_add) if self.material_num: data['material'] = self.material_num if self.tanzaku_num: data.update(tanzaku=self.tanzaku_num, tanzaku_post=self.tanzaku_num_post) return data