def query_pay_detail(self, gid, mi, request): conf = Context.Configure.get_game_item_json(gid, 'product.config') pids = [] for pid in conf.iterkeys(): pids.append('product_' + pid) start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') timess = Context.Stat.get_day_data(gid, fmt, *pids) kvs = {'product_100646': 0, 'product_100710': 0} for k, v in zip(pids, timess): pid = k.replace('product_', '') if pid in ('100646', '100647', '100648', '100649', '100650', '100651', '100652', '100653', '100654', '100655'): kvs['product_100646'] += Tool.to_int(v, 0) elif pid in ('100710', '100711', '100712', '100713', '100714', '100715', '100716'): kvs['product_100710'] += Tool.to_int(v, 0) else: kvs[k] = Tool.to_int(v, 0) mo.set_param(fmt, kvs) start_day = Time.next_days(start_day) return mo
def query_chip_produce(self, gid, mi, request): start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') kvs = Context.Stat.get_day_data(gid, fmt) task_total, catch_total = 0, 0 _kvs = {} for k, v in kvs.iteritems(): if k.startswith('in.chip.'): if k.startswith('in.chip.task.reward.'): task_total += int(v) elif k.startswith('in.chip.catch.fish.'): catch_total += int(v) else: _kvs[k] = int(v) _kvs['in.chip.task.reward'] = task_total _kvs['in.chip.catch.fish'] = catch_total _kvs['in.chip.buy.product'] = int(kvs.get('in.chip.buy.product', 0)) mo.set_param(fmt, _kvs) start_day = Time.next_days(start_day) return mo
def query_diamond_consume(self, gid, mi, request): start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') kvs = Context.Stat.get_day_data(gid, fmt) _kvs, total = {}, 0 for k, v in kvs.iteritems(): if k.startswith('out.diamond.'): if k.startswith('out.diamond.inner.buy.'): k = 'out.diamond.buy.' + k[-3:] elif k.startswith('out.diamond.table.buy.'): k = 'out.diamond.buy.' + k[-3:] if k in _kvs: _kvs[k] += int(v) else: _kvs[k] = int(v) total += int(v) _kvs['total'] = total mo.set_param(fmt, _kvs) start_day = Time.next_days(start_day) return mo
def query_chip_pump(self, gid, mi, request): room_types = (201, 202, 203) fields = [] for room_type in room_types: fields.append('out.chip.pump.%d' % room_type) fields.append('out.chip.buff.pump.%d' % room_type) fields.append('out.chip.red.pump.%d' % room_type) start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') chips = Context.Stat.get_day_data(gid, fmt, *fields) info = [] for i in range(0, len(chips), 3): total = 0 for j in range(3): if chips[i + j]: total += int(chips[i + j]) info.append(total) mo.set_param(fmt, info) start_day = Time.next_days(start_day) return mo
def query_chip_consume(self, gid, mi, request): room_types = (201, 202, 203) mini_games = (10002, 10003) fields = ['out.chip.attack'] for room_type in room_types: fields.append('out.chip.game.shot.bullet.%d' % room_type) for game in mini_games: fields.append('out.chip.game.%d' % game) start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') chips = Context.Stat.get_day_data(gid, fmt, *fields) attack = Tool.to_int(chips[0], 0) info = [] for chip in chips[1:]: if chip: info.append(int(chip)) else: info.append(0) info[2] += attack mo.set_param(fmt, info) start_day = Time.next_days(start_day) return mo
def check_bankrupt(cls, uid, gid): benefit_times, bankrupt_ts = Context.Daily.get_daily_data( uid, gid, 'benefit_times', 'bankrupt_ts') benefit_times = Tool.to_int(benefit_times, 0) wait, which = None, None if bankrupt_ts: # 已经在破产状态, 未领取 which = benefit_times + 1 wait = int(bankrupt_ts) - Time.current_ts() if wait < 0: wait = 0 else: conf = Context.Configure.get_game_item_json(gid, 'benefit.config') if benefit_times < len(conf['reward']): reward = conf['reward'][benefit_times] bankrupt_ts = Time.current_ts() + reward['wait'] Context.Daily.set_daily_data(uid, gid, 'bankrupt_ts', bankrupt_ts) wait = reward['wait'] which = benefit_times + 1 mo = MsgPack(Message.FISH_MSG_BANKRUPT | Message.ID_NTF) mo.set_param('userId', uid) if wait is not None: mo.set_param('wait', wait) if which is not None: mo.set_param('which', which) # 可以领取哪一次 return mo
def deliverOrder(self, mi, request): gid = mi.get_param('gameId') order_list = mi.get_param('orders') if not Entity.logined(request): return MsgPack.Error(0, Const.E_NOT_LOGIN, Const.ES_NOT_LOGIN) uid = request.getSession().userId orders = [] for orderId in order_list: orderInfo = self.getOrderInfo(orderId) if not orderInfo: continue userId = int(orderInfo['userId']) gameId = int(orderInfo['gameId']) state = int(orderInfo['state']) if userId != uid: Context.Log.warn('userId not match', userId, uid, orderId) continue if gameId != gid: Context.Log.warn('gameId not match', gameId, gid, orderId) continue if state == self.state_create: create_ts = Time.str_to_timestamp(orderInfo['createTime'], '%Y-%m-%d %X.%f') now_ts = Time.current_ts() if now_ts - create_ts > 3600: state = self.state_timeout orders.append({'id': orderId, 'state': state}) return MsgPack(0, {'orders': orders})
def query_summary(self, gid, mi, request): # 新增设备, 新增用户, 活跃用户, (新)付费玩家, (新)用户付费, 充值次数 start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') kvs = Context.Stat.get_day_data(gid, fmt) channel_info = {} for k, v in kvs.iteritems(): if (k.endswith('.new.device.count') or k.endswith('.new.user.count') or k.endswith('.login.user.count') or k.endswith('.new.pay.user.count') or k.endswith('.new.pay.user.pay_total') or k.endswith('.pay.user.count') or k.endswith('.pay.user.pay_total') or k.endswith('.user.pay.times')): channel, key = k.split('.', 1) if channel not in channel_info: channel_info[channel] = {} channel_info[channel][key] = int(v) mo.set_param(fmt, channel_info) start_day = Time.next_days(start_day) return mo
def on_exchange(self, uid, gid, mi): mo = MsgPack(Message.MSG_SYS_EXCHANGE | Message.ID_ACK) _id = mi.get_param('id') if not isinstance(_id, int): return mo.set_error(1, 'error param') conf = Context.Configure.get_game_item_json(gid, 'exchange.config') if _id >= len(conf): return mo.set_error(1, 'error id') info = conf[_id] to_type = info['type'] if to_type not in ('diamond', 'props', 'phone'): raise Exception( str(to_type) + '<----error type, please check config') real, final = Context.UserAttr.incr_coupon(uid, gid, -info['cost'], 'exchange.' + to_type) if real != -info['cost']: return mo.set_error(2, 'not enough') mo.set_param('coupon', final) record = { 'uid': uid, 'type': 'exchange', 'ts': Time.current_ts(), 'from': 'coupon', 'to': to_type, 'cost': info['cost'], 'count': info['count'], 'desc': info['desc'] } if info['type'] == 'diamond': # 兑换钻石 real, final = Context.UserAttr.incr_diamond( uid, gid, info['count'], 'exchange.diamond') mo.set_param('diamond', final) state = 1 elif info['type'] == 'props': # 兑换道具 real, final = FishProps.incr_props(uid, gid, info['id'], info['count'], 'exchange.props') mo.set_param('id', info['id']) mo.set_param('count', final) state = 1 record['id'] = info['id'] elif info['type'] == 'phone': state = 0 record['phone'] = mi.get_param('phone') else: raise Exception('something error, please check config') seq_num = Context.RedisMix.hash_incrby('game.%d.info.hash' % gid, 'exchange.history.seq', 1) Context.RedisCluster.hash_set(uid, 'history:%d:%d' % (gid, uid), seq_num, state) record = Context.json_dumps(record) Context.RedisMix.hash_mset('game.%d.exchange.record' % gid, seq_num, record) fmt = Time.current_time('%Y-%m-%d') Context.RedisStat.hash_set('history:%d:%s' % (gid, fmt), seq_num, uid) return mo
def check_forbidden(cls, uid, gid, token): Context.Log.info('gameId =', gid, 'userId =', uid, 'session =', token) if gid not in Context.GData.game_list: return 2, 'error gameId' if not token: return 1, 'error session' redis_session = Context.RedisCache.hash_get('token:%d' % uid, 'session') if redis_session != token: Context.Log.error('verify session failed', token, redis_session) return 1, 'error session' forbidden = Context.RedisMix.set_ismember('forbidden.user', uid) if forbidden: Context.Log.info('user is forbidden login', uid) return Enum.login_failed_forbidden, 'forbidden' disable = Context.RedisMix.set_ismember('game.%d.disable.user' % gid, uid) if disable: Context.Log.info('user is disable login', uid) return Enum.login_failed_forbidden, u'您的账号已被封停,如有疑问请联系客服' end_ts = Context.RedisMix.hash_get_int('game.%d.freeze.user' % gid, uid, 0) if end_ts: if end_ts > Time.current_ts(): Context.Log.info('user is freeze login', uid) when = Time.timestamp_to_str(end_ts, '%Y-%m-%d %H:%M') return Enum.login_failed_freeze, u'您的账号已被冻结,%s解封,如有疑问请联系客服' % when else: Context.RedisMix.hash_del('game.%d.freeze.user' % gid, uid) return Enum.login_success, ''
def query_diamond_produce(self, gid, mi, request): start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') kvs = Context.Stat.get_day_data(gid, fmt) _kvs = {} total, task_total, fall_total = 0, 0, 0 for k, v in kvs.iteritems(): if k.startswith('in.diamond.'): if k.startswith('in.diamond.task.reward.'): task_total += int(v) elif k.startswith('in.diamond.fish.fall.'): fall_total += int(v) else: _kvs[k] = int(v) total += int(v) _kvs['in.diamond.task.reward'] = task_total _kvs['in.diamond.fish.fall'] = fall_total _kvs['in.diamond.buy.product'] = int(kvs.get('in.diamond.buy.product', 0)) _kvs['total'] = total mo.set_param(fmt, _kvs) start_day = Time.next_days(start_day) return mo
def getLoginInfo(cls, request, cmd, uid, gid, param, userInfo, freshAccessToken, openid=None, open_token=None): session = Algorithm.md5_encode(Time.asctime() + request.getClientIP() + userInfo['userName']) Account.setUserToken(uid, gid, session) conn_server = Context.json_loads( Context.RedisCache.get('connect.server')) internet = conn_server[uid % len(conn_server)] dictInfo = { "session": session, "userId": uid, "sex": int(userInfo['sex']), "nick": userInfo['nick'], "avatar": userInfo['avatar'], "host": internet["domain"], "port": internet["port"], } if openid: dictInfo['openid'] = openid if open_token: dictInfo['open_token'] = open_token if freshAccessToken: data = '{"uid":%d,"ct":%d}' % (uid, Time.current_ts()) accessToken = Entity.encrypt(data) Account.updateUserInfo(uid, accessToken=accessToken) dictInfo['accessToken'] = accessToken kvs = { 'session_platform': param['platform'] or 'android', 'session_channel': param['channel'] or 'jiyu', 'session_ver': param['releaseVer'] or '1.0.1' } Context.Data.set_game_attrs_dict(uid, gid, kvs) Context.Log.report('user.login:', [uid, gid, kvs]) # 登录成功设置session值 session = request.getSession() session.setLogined(uid) return MsgPack(cmd, dictInfo)
def query_carrying(self, gid, mi, request): start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') _login, _total = Context.Stat.get_day_data(gid, fmt, 'login.carrying.volume.chip', 'carrying.volume.chip') _login = Tool.to_int(_login, 0) _total = Tool.to_int(_total, 0) mo.set_param(fmt, {'carrying': _login, 'total': _total}) start_day = Time.next_days(start_day) return mo
def on_join_table(self, gid, msg): ack = MsgPack(Message.MSG_SYS_JOIN_TABLE | Message.ID_ACK) tid = msg.get_param('tableId') self._info('player req to join table', tid) self.offline = False if self.tid > 0 and self.tid != tid: self.offline = True return ack.set_error(Enum.join_table_failed_multi) registry = Context.get_module(gid, 'registry') table = registry.create_table(gid, tid) if not table: self.offline = True return ack.set_error(Enum.join_table_failed_id) result = table.join_table(self.uid) if result != 0: self.offline = True return ack.set_error(result) self.table = table self.online_ts = Time.current_ts() sid = msg.get_param('seatId') if sid is not None: return self.on_sit_down(msg) return result
def set_location_status(self, uid, gid, status, fresh_time=None): key = 'location:%d:%d' % (gid, uid) if not fresh_time: fresh_time = Time.current_ts() self.ctx.RedisCache.hash_mset(key, 'status', status, 'fresh_ts', fresh_time) return True
def issue_benefit(self, uid, gid, limit=None): benefit_config = self.ctx.Configure.get_game_item_json( gid, 'benefit.config') if not benefit_config: return False chip = self.ctx.UserAttr.get_chip(uid, gid, 0) if limit is None: limit = benefit_config.get('limit', None) if limit is not None and chip >= limit: return False rewards = benefit_config['reward'] keys = [uid, gid, Time.tomorrow_start_ts(), len(rewards)] keys.extend([item['chip'] for item in rewards]) result = self.ctx.RedisCluster.execute_lua_alias( uid, 'issue_benefit', *keys) if result[0] <= 0: return False self.ctx.Log.report( 'chip.update: [%s, %s, %s, %s, issue.benefit, {}]' % (uid, gid, result[1], result[2])) return { 'which': result[0], # 领取第几次 'total': len(rewards), 'reward': result[1], 'chip': result[2], }
def get_login_info(cls, uid, gid): now_day = Time.up_days() last_login, ns_login = Context.Data.get_game_attrs( uid, gid, ['lastlogin', 'nslogin']) last_login = Tool.to_int(last_login, 0) ns_login = Tool.to_int(ns_login, 0) return now_day, last_login, ns_login
def set_daily_data(self, gid, *args, **kwargs): l = Tool.dict2list(kwargs) l.extend(args) if len(l) % 2 != 0: raise Exception('error param') key = '%s:%s:%s' % (self.prefix, gid, Time.current_time(self.format)) return self.ctx.RedisStat.hash_mset(key, *l)
def __pub_raffle_led(self, uid, gid, level, reward_info): if 'reward' in reward_info: reward = reward_info['reward'] name = None if 'chip' in reward: Context.Data.hincr_game(uid, gid, 'chip_pool', -reward['chip']) elif 'coupon' in reward: name = u'%d鱼券' % reward['coupon'] elif 'diamond' in reward: name = u'%d钻石' % reward['diamond'] elif 'props' in reward: props = reward['props'] for one in props: name = FishProps.get_props_desc(one['id']) break if name: nick = Context.Data.get_attr(uid, 'nick') if nick: led = u'恭喜%s玩家,在%s中抽中%s' % (nick.decode('utf-8'), level, name) mo = MsgPack(Message.MSG_SYS_LED | Message.ID_NTF) mo.set_param('game', { 'list': [led], 'ts': Time.current_ts() }) Context.GData.broadcast_to_system(mo)
def gm_push_led(self, gid, mi, request): msg = mi.get_param('msg') if not msg: # 清除led Context.RedisCache.delete('game.%d.led.list' % gid) else: led = Context.json_dumps({'led': msg, 'ts': Time.current_ts()}) Context.RedisCache.list_lpush('game.%d.led.list' % gid, led) return MsgPack(0)
def global_unlock(cls, uid, gid): lock = Context.RedisCache.hash_get_json('global.playing.lock', uid) if lock and lock['gid'] != gid: now_ts = Time.current_ts() if now_ts < lock['ts']: return False Context.RedisCache.hash_del('global.playing.lock', uid) return True
def on_server_heart_beat(self): now_ts = Time.current_ts() rc_del = [] for uid in Context.GData.map_client_connect: connection = Context.GData.map_client_connect[uid] if now_ts - connection.access_ts >= 60: rc_del.append(connection) for connection in rc_del: Context.Log.info('too long time no msg, terminate', connection.userId, connection.access_ts) connection.terminate_connection()
def incr_daily_data(self, uid, gid, field, delta=1): key = 'daily:%d:%d' % (gid, uid) tomorrow_ts = Time.tomorrow_start_ts() isNew = self.ctx.RedisCluster.hash_setnx(uid, key, 'expire_ts', tomorrow_ts) if isNew: self.ctx.RedisCluster.hash_incrby(uid, key, field, delta) self.ctx.RedisCluster.expire_at(uid, key, tomorrow_ts) return delta else: return self.ctx.RedisCluster.hash_incrby(uid, key, field, delta)
def query_user_info(self, gid, mi, request): uid = mi.get_param('userId') user_attrs = ['createTime', 'deviceId', 'nick', 'idType', 'userName', 'channel', 'platform'] kvs = Context.Data.get_attrs_dict(uid, user_attrs) game_attrs = ['pay_total', 'session_login', 'exp', 'barrel_level', 'chip', 'diamond', 'in_chip', 'out_chip'] _kvs = Context.Data.get_game_attrs_dict(uid, gid, game_attrs) kvs.update(_kvs) kvs['chip'] = int(kvs.get('chip', 0)) kvs['in_chip'] = int(kvs.get('in_chip', 0)) kvs['out_chip'] = int(kvs.get('out_chip', 0)) kvs['diamond'] = int(kvs.get('diamond', 0)) dt = Time.str_to_datetime(kvs['createTime'], '%Y-%m-%d %X.%f') kvs['createTime'] = Time.datetime_to_str(dt, '%Y-%m-%d %X') dt = Time.str_to_datetime(kvs['session_login'], '%Y-%m-%d %X.%f') kvs['session_login'] = Time.datetime_to_str(dt, '%Y-%m-%d %X') if int(kvs['idType']) == 13: kvs['phone'] = kvs['userName'] kvs['pay_total'] = int(kvs.get('pay_total', 0)) kvs['vip_level'] = FishAccount.get_vip_level(uid, gid, pay_total=int(kvs['pay_total'])) exp = int(kvs['exp']) kvs['level'], _ = FishAccount.get_exp_info(uid, gid, exp=exp) barrel_level = int(kvs['barrel_level']) kvs['barrel_multiple'] = FishAccount.trans_barrel_level(gid, barrel_level) l = (201, 202, 203, 204, 205, 211, 212, 213, 214, 215, 216, 217, 218, 219) _list = FishProps.get_props_list(uid, gid, l) props_map = dict(_list) props_list = [] for i in l: count = props_map.get(i, 0) props_list.append(count) kvs['props'] = props_list mo = MsgPack(0) mo.update_param(kvs) return mo
def register(self, param, request, openid, idType, channel): gid = param['gameId'] l = [] if param['deviceId']: l.append(param['deviceId']) if param['deviceId2']: l.append(param['deviceId2']) if param['mac']: l.append(param['mac']) if param['imei']: l.append(param['imei']) if param['imsi']: l.append(param['imsi']) if l: deviceId = l[0] else: deviceId = 'DEVID' + str(Time.current_ms()) platform = param['platform'] # channel = param['channel'] nickName = param['devName'] if param.get('nickName'): nickName = param.get('nickName') dictInfo = { 'idType': idType, 'deviceId': deviceId, 'userName': openid, 'nick': nickName, 'createIp': request.getClientIP(), 'token': '', 'platform': platform, 'channel': channel, 'openid': openid } uid = Account.createUser(dictInfo) if uid is None: return None key = 'game.%d.info.hash' % gid pipe_args = [] if l: field = '%s.new.device.count' % channel pipe_args.append(field) pipe_args.append(1) field = '%s.new.user.count' % channel pipe_args.append(field) pipe_args.append(1) Context.RedisMix.hash_mincrby(key, *pipe_args) Context.Stat.mincr_daily_data(gid, *pipe_args) return uid
def check_benefit(cls, uid, gid): conf = Context.Configure.get_game_item_json(gid, 'benefit.config') total_times = len(conf['reward']) benefit_times, bankrupt_ts = Context.Daily.get_daily_data( uid, gid, 'benefit_times', 'bankrupt_ts') benefit_times = Tool.to_int(benefit_times, 0) if benefit_times >= total_times: return total_times, total_times, 0, conf now_ts = Time.current_ts() if bankrupt_ts and bankrupt_ts >= now_ts: return total_times, benefit_times, 0, conf else: return total_times, benefit_times, now_ts - bankrupt_ts, conf
def freeze_user(self, gid, mi, request): uid = mi.get_param('userId') if not Context.UserAttr.check_exist(uid, gid): return MsgPack.Error(0, 1, 'not exist') days = mi.get_param('days') mo = MsgPack(0) if days is None: Context.RedisMix.hash_del('game.%d.freeze.user' % gid, uid) else: end_ts = Time.today_start_ts() + days * 3600 * 24 Context.RedisMix.hash_set('game.%d.freeze.user' % gid, uid, end_ts) mo.set_param('end_ts', end_ts) return mo
def mincr_daily_data(self, uid, gid, *args, **kwargs): key = 'daily:%d:%d' % (gid, uid) tomorrow_ts = Time.tomorrow_start_ts() isNew = self.ctx.RedisCluster.hash_setnx(uid, key, 'expire_ts', tomorrow_ts) if isNew: result = self.ctx.RedisCluster.hash_mincrby( uid, key, *args, **kwargs) self.ctx.RedisCluster.expire_at(uid, key, tomorrow_ts) return result else: return self.ctx.RedisCluster.hash_mincrby(uid, key, *args, **kwargs)
def gm_notice_global(self, gid, mi, request): led = mi.get_param('led') start = mi.get_param('start') end = mi.get_param('end') now_ts = Time.current_ts() if now_ts > end: return MsgPack(0) Context.RedisCache.hash_mset('global.notice', 'led', led, 'start', start, 'end', end) if now_ts >= start: self._do_notice(led, end) return MsgPack(0) TaskManager.set_timeout(self.do_notice, start-now_ts, led, end) return MsgPack(0)
def query_shot(self, gid, mi, request): room_types = (201, 202, 203) fields = [] for room_type in room_types: fields.append('shot.times.%d' % room_type) start = mi.get_param('start') end = mi.get_param('end') start_day = Time.str_to_datetime(start, '%Y-%m-%d') end_day = Time.str_to_datetime(end, '%Y-%m-%d') mo = MsgPack(0) while start_day <= end_day: fmt = Time.datetime_to_str(start_day, '%Y-%m-%d') values = Context.Stat.get_day_data(gid, fmt, *fields) info = [] for v in values: if v: info.append(int(v)) else: info.append(0) mo.set_param(fmt, info) start_day = Time.next_days(start_day) return mo