local ProtocolZhanJi = class("ProtocolZhanJi") --[[ table中的key在经过json转换之后,全部都会变成string,所以在使用的时候都使用string --]] local InterfaceKey = { brief = "gamb.brief", -- 获取简要的战绩列表信息 detail = "gamb.replay", -- 获取某一局的详细战绩 } function ProtocolZhanJi:ctor() -- 添加分发事件的组件 cc.GameObject.extend(self) self:addComponent(require("luaScript.cc.components.behavior.EventProtocol"):new()):exportMethods() self.phpUrl = getGlobalPhpUrl() -- 保存到本地的文件名,所有子游戏必须重写并且保证不冲突 self.fileName = ""; -- 是否茶馆模式 self.isClubMode = false -- 每页以及每次拉取最大数量 self.numPrePage = 20; -- 茶馆战绩最多保存几天内的数据 self.numMaxDay = 7; -- 所有的战绩保存在这里 self.zhanjiInfoList = {} end -- 子游戏的战绩协议应该重写此接口 function ProtocolZhanJi:init() end -- 从本地文件读取以前的战绩信息 function ProtocolZhanJi:loadFromFile() local jsonString = loadStringFromFile(self.fileName) if jsonString then self.zhanjiInfoList = json.decode(jsonString) or {} end end -- 保存战绩信息到本地文件 function ProtocolZhanJi:saveToFile() if self.isClubMode then -- 茶馆在存储之前要先剔除那些过期的战绩 -- 首先计算出N天前0点0分0秒对应的时间戳 local timeBegin = endtime - self.numMaxDay * 24 * 3600 local dateBegin = os.date("*t", timeBegin) dateBegin.hour = 0; dateBegin.min = 0; dateBegin.sec = 0; timeBegin = os.time(dateBegin); -- 逐个比较文件中的数据,剔除过期的内容 for k,v in pairs(self.zhanjiInfoList) do local endtime = tonumber(v.endtime) or 0 if endtime < timeBegin then self.zhanjiInfoList[k] = nil end end end local jsonString = json.encode(self.zhanjiInfoList) saveStringToFile(jsonString, self.fileName) -- PC端另外再存一份数据以方便查看 if cc.Application:getInstance():getTargetPlatform() == 0 then table.saveToLocFile(self.zhanjiInfoList, self.fileName..".lua") end end -- 检查战绩列表,找到需要下载的战绩进行下载 function ProtocolZhanJi:checkAndDownload(idxList) local idxListDownload = {} if idxList then for k,v in pairs(idxList) do if not self.zhanjiInfoList[v] then table.insert(idxListDownload, v) end end end if table.nums(idxListDownload) >0 then self:getZhanjiBrief(idxListDownload) else self:dispatchEvent({name = "getZhanjiBriefResponse"}) end end -- 获取指定房间的战绩概要 -- 因为所有子游戏和茶馆的概要信息结构都是一致的。所以可以都使用同一个接口 -- 如果发现某个游戏的概要信息结构不一样,请通知服务器改动 function ProtocolZhanJi:getZhanjiBrief(idxListDownload) local strList local cnt = 0; for k,v in pairs(idxListDownload) do cnt = cnt + 1 if cnt < self.numPrePage then if not strList then strList = tostring(v) else strList = strList..","..tostring(v) end end end local tt = { action = InterfaceKey.brief, -- 接口名 app = getAppId(), -- appId uid = app.user.loginInfo.uid, -- userId idx = strList, -- 索引id,以","分割 } logD("ProtocolZhanJi:getZhanjiList()", table.tostring(tt)) httpPost(self.phpUrl, tt, handler(self, self.getZhanjiBriefResponse)); end function ProtocolZhanJi:getZhanjiBriefResponse(status, response) logD("ProtocolZhanJi:getZhanjiBriefResponse()", status, response) local ret, ttResult = checkPhpResponse(status, response) if not ret then logE("ProtocolZhanJi:getZhanjiBriefResponse()", tostring(ttResult)) return end -- 解析服务器下发的战绩信息 if ttResult.gamb then for pid, info in pairs(ttResult.gamb) do if table.nums(info) > 0 then local zhanjiInfo = {} zhanjiInfo.pid = pid; zhanjiInfo.gameid = info.gameid; -- 游戏ID zhanjiInfo.gext = info.gext; -- 游戏拓展属性 zhanjiInfo.roomid = info.roomid; -- 房间号 zhanjiInfo.fbound = info.fbound; -- 完成的局数 zhanjiInfo.nbound = info.nbound; -- 需要完成的局数 zhanjiInfo.endtime = info.endtime; -- 完成时间,unix时间戳 zhanjiInfo.baseChips = tostring(info.baseChips); -- 底分 zhanjiInfo.nCards = info.nCards; -- 消耗房卡 -- 总输赢 zhanjiInfo.tscore = {} if info.tscore then for uid, score in pairs(info.tscore) do zhanjiInfo.tscore[tostring(uid)] = tonumber(score) end end -- 每个玩家的输赢次数 zhanjiInfo.tgamb = {} if info.tgamb then for uid, wInfo in pairs(info.tgamb) do zhanjiInfo.tgamb[tostring(uid)] = {win = tonumber(wInfo.w) or 0, lose = tonumber(wInfo.l) or 0}; end end -- 每一局的详细信息 zhanjiInfo.detail = {} if info.detail then for jushu, jushuInfo in pairs(info.detail) do local jsInfo = {} -- 每一局下面可能有多轮,所以这里还有一次循环 for lunshu, lunshuInfo in pairs(jushuInfo) do local lsInfo = {} -- 本轮基本信息 lsInfo.flag = lunshuInfo.flag or 0 -- 0=正常结束 1=吃臭牌 2=吃牌不比 3=无牌赔包子 4=胡臭牌 7=黄庄 8=长时间自动解散 9=解散游戏 , 如果为0、8、9则表示正常结束 lsInfo.subid = lunshuInfo.subid or "" -- 此次小局结束的日志id lsInfo.endtime = lunshuInfo.endtime or 0 -- 结束时间 -- 本轮结算信息 lsInfo.score = {} if lunshuInfo.score then for uid, fenshu in pairs(lunshuInfo.score) do lsInfo.score[tostring(uid)] = tonumber(fenshu) end end jsInfo[tostring(lunshu)] = lsInfo end zhanjiInfo.detail[tostring(jushu)] = jsInfo end end self.zhanjiInfoList[pid] = zhanjiInfo end end end -- 保存玩家信息 if ttResult.user then for uid, info in pairs(ttResult.user) do local name = tostring(info.n) or tostring(uid) local head = tostring(info.h) or "" local sex = tonumber(info.s) or 0 -- 添加玩家信息到管理器 if app.playerInfoManager then app.playerInfoManager:addPlayerInfo(tostring(uid), name, head, sex); end end end -- 保存到文件 self:saveToFile() -- 发送事件 self:dispatchEvent({name = "getZhanjiBriefResponse" , result = ttResult}) end -- 获取指定房间、指定轮数的战绩详情 -- 对于像黄十八、麻将这种,某一局可能出现吃包子需要打多轮或者详细信息量非常大的情况,必须指定subid -- 类似扑克这种详情量比较小,可以一次拉取所有局数的数据的,才使用 subid = 0 function ProtocolZhanJi:getZhanJiDetail(pid, subid, endcallback) -- 如果连这个战绩的概要信息都没有的话,就不要拉取详细信息了 local zhanjiInfo = self.zhanjiInfoList[pid] if not zhanjiInfo then self:dispatchEvent({name = "getZhanJiDetailResponse"}) return end -- 判断本地是否有这个详情,有就不用更新了 local needDownload = false; if zhanjiInfo.detail then if subid == 0 then for k,v in pairs(zhanjiInfo.detail) do if not v.user then needDownload = true end end else if not zhanjiInfo.detail[subid] or not zhanjiInfo.detail[subid].user then needDownload = true end end end if not needDownload then self:dispatchEvent({name = "getZhanJiDetailResponse"}) if endcallback then endcallback(); end return end -- 没有这个战绩的详情,还是要从服务器下载 local tt = { action = InterfaceKey.detail, app = getAppId(), -- appId uid = app.user.loginInfo.uid, -- userId idx = pid, -- 日志ID subid = subid, -- 小局id 如果需要idx全部战绩,此时subid=0,单个则传subid } logD("ProtocolZhanJi:getZhanJiDetail", table.tostring(tt)) httpPost(self.phpUrl, tt, function(status, response) self:getZhanJiDetailResponse(status, response, pid, subid, endcallback) end ) end function ProtocolZhanJi:getZhanJiDetailResponse(status, response, pid, subid, endcallback) logD("ProtocolZhanJi:getZhanJiDetailResponse()", status, response, pid) local ret, ttResult = checkPhpResponse(status, response) if not ret then logE("ProtocolZhanJi:getZhanJiDetailResponse()", tostring(ttResult)) return end local zhanjiInfo = self.zhanjiInfoList[pid] if zhanjiInfo and zhanjiInfo.detail then if subid == 0 then for jushu, lunshuInfo in pairs(ttResult) do local jsInfo = zhanjiInfo.detail[tostring(jushu)] if jsInfo then local lsInfo = jsInfo["1"] if lsInfo then for k,v in pairs(lunshuInfo) do lsInfo[k] = v end end end end else for jushu, jushuInfo in pairs(zhanjiInfo.detail) do for lunshu, lunshuInfo in pairs(jushuInfo) do if lunshuInfo.subid == subid then for k,v in pairs(ttResult) do lunshuInfo[k] = v end end end end end end -- 更新本地文件 self:saveToFile(); -- 发送事件 self:dispatchEvent({name = "getZhanJiDetailResponse"}) -- 执行可能存在的回调 if endcallback then endcallback(); end end return ProtocolZhanJi