Commit a18c7fd0cb52b7f64aa85b0e7db0702f3d179e81

Authored by liuzujun
2 parents 606318cb 06c7246e

Merge branch 'cn/develop' into cn/publish/release

* cn/develop:
  按500人分线
  fix: 一番赏 修复广播capsuleId 为空的问题
  fix: 一番赏 修复king赏bug
  fix: 一番赏 特殊赏的抽奖记录的数据结构修改
  fix: 一番赏 打开激励奖导致抽奖逻辑性阻塞的bug
  feat: 一番赏 特殊赏 通知 1. 服务器主动通知 Capsule_notifyChange = 856 2. 客户端主动获获取 Capsule_specialRewardRpc = 857 3. 客户端消除特殊赏通知指令 Capsule_clearSpecialNtyRpc = 862
  fix: 一番赏 优化; 抽奖记录分页;抽扭蛋机,返回值更新
  fix: 一番赏 增加rank,刷新机制完善,修复capsuled 55行报错。
  fix: 一番赏 增加drawEndTime,优化获取奖励剩余数量。
  fix: 一番赏 屏蔽初始化日志
src/ProtocolCode.lua
... ... @@ -281,10 +281,12 @@ actionCodes = {
281 281 Capsule_drawRpc = 854, --抽扭蛋机
282 282 --Capsule_switchRoomRpc = 855, --切换扭蛋机房间
283 283 Capsule_notifyChange = 856, -- 通知信息变动
284   - Capsule_payReward = 857, -- 特殊赏 奖励通知
  284 + Capsule_specialRewardRpc = 857, -- 获取 未领取特殊赏通知 主动
285 285 Capsule_exitRpc = 858, -- 退出
286 286 Capsule_getDataRpc = 859, --获取扭蛋机信息
287   - Capsule_convertCapsuleRpc = 890, --兑换消耗票
  287 + Capsule_convertCapsuleRpc = 860, --兑换消耗票
  288 + Capsule_pageRecordRpc = 861, --抽奖记录分页查询
  289 + Capsule_clearSpecialNtyRpc = 862, --消除特殊赏通知
288 290 }
289 291  
290 292 rpcResponseBegin = 10000
... ...
src/actions/CapsuleAction.lua
... ... @@ -51,7 +51,7 @@ function _M.joinRpc(agent, data)
51 51 if typ == 1 then
52 52 ret = skynet.call(agent.capsule_serv, "lua", "join", roleId, capsuleId)
53 53 elseif typ == 0 then
54   - ret = role:joinCapsule()
  54 + ret = role:joinCapsule(roleId, capsuleId)
55 55 end
56 56 SendPacket(actionCodes.Capsule_joinRpc, MsgPack.pack(ret))
57 57 return true
... ... @@ -96,7 +96,7 @@ function _M.drawRpc(agent, data)
96 96 local full = msg.full or 0-- 0=单次,1=十连抽 2=全收
97 97 local cares = msg.cares
98 98  
99   - local ret, token, reward, change, rewardByGoods, capsule
  99 + local ret, token, change, drawReward, capsule
100 100  
101 101 --检查库存
102 102 if typ == 1 then
... ... @@ -127,26 +127,23 @@ function _M.drawRpc(agent, data)
127 127  
128 128 --开始抽奖
129 129 if typ == 1 then
130   - ret, reward, rewardByGoods, capsule = skynet.call(agent.capsule_serv, "lua", "draw_capsule", roleId, capsuleId, full, cares)
  130 + ret, drawReward, capsule = skynet.call(agent.capsule_serv, "lua", "draw_capsule", roleId, capsuleId, full, cares)
131 131 else
132   - ret, reward, rewardByGoods, capsule= role:drawCapsule(capsuleId, full, cares)
  132 + ret, drawReward, capsule = role:drawCapsule(capsuleId, full, cares)
133 133 end
134 134 if ret < 5 then
135 135 return ret
136 136 end
137 137  
138   - --dump(rewardByGoods)
139   - --dump(capsule)
140   -
141 138 if ret == 5 then
142   - SendPacket(actionCodes.Capsule_drawRpc, MsgPack.pack({change = reward, capsule = capsule}))
  139 + SendPacket(actionCodes.Capsule_drawRpc, MsgPack.pack({change = drawReward, capsule = capsule}))
143 140 return true
144 141 end
145 142  
146   - -- rewardByGoods是抽到的扭蛋信息,reward是抽扭蛋后获得的所有奖励信息。
147   - if rewardByGoods and next(rewardByGoods) then
148   - reward, change = role:award(reward, {log = {desc = "CapsuleReward", int1 = tonumber(capsuleId), int2 = roleId}})
149   - SendPacket(actionCodes.Capsule_drawRpc, MsgPack.pack({reward = rewardByGoods, capsule = capsule}))
  143 + if drawReward["reward"] and next(drawReward["reward"]) then
  144 + _, change = role:award(drawReward["reward"], {log = {desc = "CapsuleReward", int1 = tonumber(capsuleId), int2 = roleId}})
  145 + drawReward["capsule"] = capsule
  146 + SendPacket(actionCodes.Capsule_drawRpc, MsgPack.pack(drawReward))
150 147 else
151 148 return ret
152 149 end
... ... @@ -164,7 +161,7 @@ function _M.getDataRpc(agent, data)
164 161 if typ == 1 then
165 162 capsule = skynet.call(agent.capsule_serv, "lua", "capsule_data", roleId, capsuleId)
166 163 else
167   - capsule = role:getCapsuleData(capsuleId)
  164 + capsule = role:getCapsuleData(roleId, capsuleId)
168 165 end
169 166 if not capsule then return 1 end
170 167  
... ... @@ -195,4 +192,61 @@ function _M.convertCapsuleRpc(agent, data)
195 192 return true
196 193 end
197 194  
  195 +function _M.pageRecordRpc(agent, data)
  196 + local role = agent.role
  197 + local msg = MsgPack.unpack(data)
  198 + local idx = msg.idx
  199 + local up = msg.up or 0
  200 + local capsuleId = msg.capsule_id
  201 + local typ = msg.typ --0=独享,1= 公开
  202 +
  203 + local record
  204 + if typ == 1 then
  205 + record = skynet.call(agent.capsule_serv, "lua", "page_record", capsuleId, up, idx)
  206 + else
  207 + record = role:pageRecord(capsuleId, up, idx)
  208 + end
  209 + if not record then return 1 end
  210 +
  211 + SendPacket(actionCodes.Capsule_pageRecordRpc, MsgPack.pack({record = record}))
  212 + return true
  213 +end
  214 +
  215 +function _M.specialRewardRpc(agent, data)
  216 + local role = agent.role
  217 + local msg = MsgPack.unpack(data)
  218 + local capsuleId = msg.capsule_id
  219 + local typ = msg.typ or 1 --0=独享,1= 公开
  220 + local roleId = role:getProperty("id")
  221 +
  222 + local ret
  223 + if typ == 1 then
  224 + ret = skynet.call(agent.capsule_serv, "lua", "get_special_nty", roleId, capsuleId)
  225 + else
  226 + ret = role:getSpecialNotify(roleId, capsuleId)
  227 + end
  228 + if not ret or not next(ret) then return 1 end
  229 +
  230 + SendPacket(actionCodes.Capsule_specialRewardRpc, MsgPack.pack({special= ret}))
  231 + return true
  232 +end
  233 +
  234 +function _M.clearSpecialNtyRpc(agent, data)
  235 + local role = agent.role
  236 + local msg = MsgPack.unpack(data)
  237 + local capsuleId = msg.capsule_id
  238 + local typ = msg.typ --0=独享,1= 公开
  239 + local good_ids = msg.good_ids
  240 + local roleId = role:getProperty("id")
  241 +
  242 + local ret
  243 + if typ == 1 then
  244 + ret = skynet.call(agent.capsule_serv, "lua", "clear_special_nty", roleId, capsuleId, good_ids)
  245 + end
  246 + if not ret or not next(ret) then return 1 end
  247 +
  248 + SendPacket(actionCodes.Capsule_clearSpecialNtyRpc, MsgPack.pack({}))
  249 + return true
  250 +end
  251 +
198 252 return _M
199 253 \ No newline at end of file
... ...
src/actions/RoleAction.lua
... ... @@ -288,7 +288,9 @@ function _M.loginRpc( agent, data )
288 288  
289 289 -- 注册全服广播
290 290 if not role._channelIdx then
291   - local channel = math.randomInt(1, 1)
  291 + local online = datacenter.get("onlineCount") or 0
  292 + local channel = math.floor(online / 500) + 1
  293 + --local channel = math.randomInt(1, 1)
292 294 role._channelIdx = channel
293 295 end
294 296 if not mcast_util.channel_world() then
... ...
src/models/Capsule.lua
... ... @@ -44,8 +44,8 @@ Capsule.schema = {
44 44 goods = {"table", {}}, --奖励池
45 45 specials = {"table", {}}, --特殊赏
46 46 incentive = {"table", {}}, --激励奖
47   - incentiveRecord = {"table", {}}, --激励奖记录
48   - specialsRecord= {"table", {}}, --特殊赏领取记录
  47 + incentiveRecord = {"table", {}}, --激励奖记录 {roleId = {}, roleId={}}
  48 + specialsRecord= {"table", {}}, --特殊赏领取记录 {1={},2={}} key=触发特殊赏的 抽奖次数, v=特殊赏商品 table
49 49 resetTimes = {"number", 0}, --每日一次手动重置的机会
50 50 hideTime = {"number", 0} , --隐藏时间
51 51 drawEndTime = {"number", 0}, --抽完时间
... ... @@ -136,8 +136,6 @@ function Capsule:init()
136 136 local coin = ichibankuji["token"]:toArray(true, "=")
137 137 self:setProperties({coin = coin[1] or 0, token = coin, hideTime = ichibankuji.hide_time, goods = goods, specials = specials, incentive = incentive})
138 138  
139   - skynet.error("初始化完成")
140   - dump(self:data())
141 139 end
142 140  
143 141 function Capsule:isShow()
... ... @@ -147,6 +145,56 @@ function Capsule:isShow()
147 145 return true
148 146 end
149 147  
  148 +function Capsule:resetTimeOut(curTime, now)
  149 + now = now or skynet.timex()
  150 + local cur4Time = curTime or (specTime({hour = 4},now))
  151 +
  152 + local interval
  153 + if cur4Time > now then
  154 + interval = cur4Time - now
  155 + elseif cur4Time < now then
  156 + local nextTime = dayLater(now)
  157 + interval = nextTime - now
  158 + elseif cur4Time == now then
  159 + self:init()
  160 + self:create()
  161 +
  162 + local nextTime = dayLater(now)
  163 + interval = nextTime - now
  164 + end
  165 + interval = (interval + 1)* 100
  166 + skynet.timeout(interval, handler(self,self.resetTimeOut))
  167 +end
  168 +
  169 +function Capsule:reset4TimeOut(curTime, now)
  170 + now = now or skynet.timex()
  171 + local interval
  172 + if curTime > now then
  173 + interval = curTime - now
  174 + elseif curTime < now then
  175 + local nextTime = dayLater(now)
  176 + interval = nextTime - now
  177 + elseif curTime == now then
  178 + self:init()
  179 + self:create()
  180 +
  181 + return false
  182 + end
  183 + interval = (interval + 1)* 100
  184 + skynet.timeout(interval, handler(self,self.reset4TimeOut))
  185 +end
  186 +
  187 +function Capsule:checkTime(resetArr, now)
  188 + if resetArr[1] == "3" then
  189 + local cur4Time = specTime({hour = 4},now)
  190 + if now == cur4Time then return true end
  191 + self:resetTimeOut(cur4Time, now)
  192 + elseif resetArr[1] == "4" then
  193 + if now == resetArr[2] then return true end
  194 + self:reset4TimeOut(resetArr[2], now)
  195 + end
  196 +end
  197 +
150 198 function Capsule:refreshing(now)
151 199 local id = self:getProperty("id")
152 200 local room = self:getProperty("room")
... ... @@ -175,11 +223,10 @@ function Capsule:refreshing(now)
175 223 end
176 224 return false
177 225  
178   - elseif resetArr[1] == "3" then
179   -
180   - elseif resetArr[1] == "4" then
181   - if now >= resetArr[2] then return true end
  226 + else
  227 + self:checkTime(resetArr, now)
182 228 end
  229 +
183 230 end
184 231  
185 232 return false
... ... @@ -276,7 +323,7 @@ function Capsule:checkSpecialFlag(typ)
276 323 return spKey, special
277 324 end
278 325  
279   -local function getSpecialRoleNotify(rewardRecord, count, award, spKey, typ, now)
  326 +local function getSpecialReward(rewardRecord, count, award, spKey, typ, now)
280 327 local rewardByRole = {}
281 328 while(count > 0 and next(rewardRecord)) do
282 329 local roleId = math.randWeight(rewardRecord, "amount")
... ... @@ -287,19 +334,9 @@ local function getSpecialRoleNotify(rewardRecord, count, award, spKey, typ, now)
287 334  
288 335 if tmp["amount"] <= 0 then rewardRecord[roleId] = nil end
289 336  
290   - tmp = rewardByRole[roleId] or {}
291   - if not next(tmp) then
292   - local name = getNameByRoleId(roleId)
293   - tmp[spKey] = {name = name, good_id = spKey, typ = RewardType.SPECIAL, award = award, amount = 1, quality = typ, create_time= now}
294   - else
295   - if not tmp[spKey] then
296   - local name = getNameByRoleId(roleId)
297   - tmp[spKey] = {name = name, good_id = spKey, typ = RewardType.SPECIAL, award = award, amount = 1, quality = typ, create_time= now}
298   - else
299   - tmp[spKey].amount = tmp[spKey].amount + 1
300   - end
301   - end
302   - rewardByRole[roleId] = tmp
  337 + local name = getNameByRoleId(roleId)
  338 + tmp = {name = name, good_id = spKey, typ = RewardType.SPECIAL, award = award, amount = 1, quality = typ, create_time= now}
  339 + table.insert(rewardByRole, tmp)
303 340  
304 341 count = count - 1
305 342 end
... ... @@ -308,20 +345,11 @@ local function getSpecialRoleNotify(rewardRecord, count, award, spKey, typ, now)
308 345 end
309 346  
310 347  
311   -local rewardToNtyFunc = function(notify, tmpReward)
312   - for key, val in pairs(tmpReward or {}) do
313   - if not notify[key] then
314   - notify[key] = clone(val)
315   - else
316   - for k, v in pairs(val) do
317   - if not notify[key][k] then
318   - notify[key][k] = v
319   - else
320   - notify[key][k] = notify[key][k].amount + v.amount
321   - end
322   - end
323   -
324   - end
  348 +local rewardToRecordFunc = function(specialsRecord, recordAmount, rewardByRole)
  349 + if not specialsRecord[recordAmount] then
  350 + specialsRecord[recordAmount] = rewardByRole
  351 + else
  352 + table.insert(specialsRecord[recordAmount], rewardByRole)
325 353 end
326 354 end
327 355  
... ... @@ -359,12 +387,12 @@ function Capsule:getTop(record, recordAmount,now)
359 387 end
360 388 end
361 389  
362   - local rewardByRole, count = getSpecialRoleNotify(topRecord, special["amount"], special["award"], spKey, SpecialType.TOP,now)
  390 + local rewardByRole, count = getSpecialReward(topRecord, special["amount"], special["award"], spKey, SpecialType.TOP,now)
363 391  
364 392 special["amount"] = count
365 393 specials[spKey] = special
366 394  
367   - rewardToNtyFunc(specialsRecord, rewardByRole)
  395 + rewardToRecordFunc(specialsRecord, recordAmount, rewardByRole)
368 396  
369 397 self:setProperties({specialsRecord = specialsRecord, specials = specials})
370 398 return rewardByRole
... ... @@ -379,14 +407,13 @@ function Capsule:getCore(record, recordAmount,now)
379 407 local specials = self:getProperty("specials") or {}
380 408 local specialsRecord = self:getProperty("specialsRecord") or {}
381 409  
382   - if self:getGoodsAmount() > 0 then return nil end
383 410  
384   - local np = special["np"]
385   - if np > recordAmount then return nil end
  411 +
  412 + local count = special["np"]
  413 + if count > recordAmount then return nil end
386 414  
387 415  
388   - local left = math.ceil((np - recordAmount)/2) or 0
389   - local count = np
  416 + local left = math.ceil((count - recordAmount)/2) or 0
390 417 local roleRecord = {}
391 418 for i, v in ipairs(record) do
392 419 if count <= 0 then break end
... ... @@ -409,29 +436,26 @@ function Capsule:getCore(record, recordAmount,now)
409 436  
410 437 end
411 438  
412   - local rewardByRole, count = getSpecialRoleNotify(roleRecord, special["amount"], special["award"], spKey, SpecialType.CORE,now)
  439 + local rewardByRole, count = getSpecialReward(roleRecord, special["amount"], special["award"], spKey, SpecialType.CORE,now)
413 440  
414 441 special["amount"] = count
415 442 specials[spKey] = special
416 443  
417   - rewardToNtyFunc(specialsRecord, rewardByRole)
  444 + rewardToRecordFunc(specialsRecord, recordAmount, rewardByRole)
418 445 self:setProperties({specialsRecord = specialsRecord, specials = specials})
419 446 return rewardByRole
420 447 end
421 448  
422   -function Capsule:getLast(record,now)
  449 +function Capsule:getLast(record, recordAmount, now)
423 450 local spKey, special = self:checkSpecialFlag(SpecialType.LAST)
424 451 if not special then return nil end
425 452  
426 453 local specials = self:getProperty("specials") or {}
427 454 local specialsRecord = self:getProperty("specialsRecord") or {}
428 455  
429   - if self:getGoodsAmount() > 0 then return nil end
430   -
431 456 table.sort(record, function(a, b) return a.create_time > b.create_time end)
432 457  
433   - local np = special["np"]
434   - local count = np
  458 + local count = special["np"]
435 459 local roleRecord = {}
436 460 for _, v in ipairs(record) do
437 461 if count <= 0 then break end
... ... @@ -452,25 +476,23 @@ function Capsule:getLast(record,now)
452 476 end
453 477 end
454 478  
455   - local rewardByRole, count = getSpecialRoleNotify(roleRecord, special["amount"], special["award"], spKey, SpecialType.LAST,now)
  479 + local rewardByRole, count = getSpecialReward(roleRecord, special["amount"], special["award"], spKey, SpecialType.LAST,now)
456 480  
457 481 special["amount"] = count
458 482 specials[spKey] = special
459 483  
460   - rewardToNtyFunc(specialsRecord, rewardByRole)
  484 + rewardToRecordFunc(specialsRecord, recordAmount, rewardByRole)
461 485 self:setProperties({specialsRecord = specialsRecord, specials = specials})
462 486 return rewardByRole
463 487 end
464 488  
465   -function Capsule:getJoker(record,now)
  489 +function Capsule:getJoker(record, recordAmount, now)
466 490 local spKey, special = self:checkSpecialFlag(SpecialType.JOKER)
467 491 if not special then return nil end
468 492  
469 493 local specials = self:getProperty("specials") or {}
470 494 local specialsRecord = self:getProperty("specialsRecord") or {}
471 495  
472   - if self:getGoodsAmount() > 0 then return nil end
473   -
474 496 local roleRecord = {}
475 497 for _, v in ipairs(record) do
476 498 if not roleRecord[v.roleId]then
... ... @@ -480,44 +502,55 @@ function Capsule:getJoker(record,now)
480 502 end
481 503 end
482 504  
483   - local rewardByRole, count = getSpecialRoleNotify(roleRecord, special["amount"], special["award"], spKey, SpecialType.JOKER,now)
  505 + local rewardByRole, count = getSpecialReward(roleRecord, special["amount"], special["award"], spKey, SpecialType.JOKER,now)
484 506  
485 507 special["amount"] = count
486 508 specials[spKey] = special
487 509  
488   - rewardToNtyFunc(specialsRecord, rewardByRole)
  510 + rewardToRecordFunc(specialsRecord, recordAmount, rewardByRole)
489 511 self:setProperties({specialsRecord = specialsRecord, specials = specials})
490 512 return rewardByRole
491 513 end
492 514  
493   -function Capsule:getKing(record,now)
  515 +function Capsule:getKing(record, recordAmount, now)
494 516 local spKey, special = self:checkSpecialFlag(SpecialType.KING)
495 517 if not special then return nil end
496 518  
497 519 local specials = self:getProperty("specials") or {}
498 520 local specialsRecord = self:getProperty("specialsRecord") or {}
499   -
500   - if self:getGoodsAmount() > 0 then return nil end
  521 + local rank = self:getProperty("rank") or {}
  522 + if not next(rank) then return nil end
501 523  
502 524 local roleRecord = {}
503   - for _, v in ipairs(record) do
504   - if not roleRecord[v.roleId]then
505   - roleRecord[v.roleId] = {amount = v.amount }
506   - else
507   - roleRecord[v.roleId] = {amount = (roleRecord[v.roleId]["amount"] or 0) + v.amount}
508   - end
  525 +
  526 + for roleId, count in pairs(rank) do
  527 + table.insert(roleRecord, {roleId = roleId, count = count})
  528 + end
  529 + table.sort(roleRecord, function(a, b) return a.count > b.count end)
  530 +
  531 + local count = math.min(special["amount"], #roleRecord)
  532 +
  533 + local rewardByRole = {}
  534 + local index = 1
  535 + while (count > 0 ) do
  536 + count = count - 1
  537 + local tmp = roleRecord[index]
  538 + if not tmp then break end
  539 + index = index + 1
  540 +
  541 + local name = getNameByRoleId(tmp.roleId)
  542 + table.insert(rewardByRole, {name = name, good_id = spKey, typ = RewardType.SPECIAL, award = special["award"], amount = 1, SpecialType.KING, create_time= now})
509 543 end
510 544  
511   - local rewardByRole, count = getSpecialRoleNotify(roleRecord, special["amount"], special["award"], spKey, SpecialType.KING,now)
512 545 special["amount"] = count
513 546 specials[spKey] = special
514 547  
515   - rewardToNtyFunc(specialsRecord, rewardByRole)
  548 + rewardToRecordFunc(specialsRecord, recordAmount, rewardByRole)
516 549 self:setProperties({specialsRecord = specialsRecord, specials = specials})
517 550 return rewardByRole
518 551 end
519 552  
520   -function Capsule:checkSpecialReward( now)
  553 +function Capsule:checkSpecialReward(now, goodsAmount)
521 554 local specials = self:getProperty("specials") or {}
522 555 if not next(specials) then return nil end
523 556 local record = self:getProperty("record") or {}
... ... @@ -529,18 +562,19 @@ function Capsule:checkSpecialReward( now)
529 562  
530 563 local notify = self:getTop(record, recordAmount,now) or {}
531 564  
532   - local coreReward = self:getCore(record, recordAmount, now)
533   - rewardToNtyFunc(notify, coreReward)
  565 + if goodsAmount == 0 then
  566 + local coreReward = self:getCore(record, recordAmount, now)
  567 + rewardToRecordFunc(notify, recordAmount, coreReward)
534 568  
535   - local lastReward = self:getLast(record, now)
536   - rewardToNtyFunc(notify, lastReward)
  569 + local lastReward = self:getLast(record, recordAmount, now)
  570 + rewardToRecordFunc(notify, recordAmount, lastReward)
537 571  
538   - local jokerReward = self:getJoker(record, now)
539   - rewardToNtyFunc(notify, jokerReward)
540   -
541   - local kingReward = self:getKing(record, now)
542   - rewardToNtyFunc(notify, kingReward)
  572 + local jokerReward = self:getJoker(record, recordAmount, now)
  573 + rewardToRecordFunc(notify, recordAmount, jokerReward)
543 574  
  575 + local kingReward = self:getKing(record, recordAmount, now)
  576 + rewardToRecordFunc(notify, recordAmount, kingReward)
  577 + end
544 578  
545 579 return notify
546 580 end
... ... @@ -608,12 +642,44 @@ function Capsule:checkIncentive(roleId, name, now)
608 642  
609 643 end
610 644 end
611   - table.insert(incentiveByRole, notify)
  645 + for k, v in pairs(notify) do
  646 + if not incentiveByRole[k] then
  647 + incentiveByRole[k] = v
  648 + else
  649 + incentiveByRole[k].amount = incentiveByRole[k].amount + v.amount
  650 + end
  651 + end
612 652 incentiveRecord[roleId] = incentiveByRole
613 653 self:setProperty("incentiveRecord", incentiveRecord)
614 654  
615   - --TODO 先屏蔽
616   - return {}
  655 + return incentiveByRole
  656 +end
  657 +
  658 +local rewardCollect = function(reward, goods)
  659 + for _, v in pairs(goods) do
  660 + for id, count in pairs(v.award:toNumMap()) do
  661 + reward[id] = (reward[id] or 0) + count * v.amount
  662 + end
  663 + end
  664 +end
  665 +
  666 +local rewardCollectByRoleId = function(roleId, reward, goods)
  667 + local tmp = {}
  668 + for _, val in pairs(goods) do
  669 + for _, v in ipairs(val) do
  670 + if v.roleId == roleId then
  671 + for id, count in pairs(v.award:toNumMap()) do
  672 + reward[id] = (reward[id] or 0) + count * v.amount
  673 + end
  674 + if not tmp[v.good_id] then
  675 + tmp[v.good_id] = v
  676 + else
  677 + tmp[v.good_id].amount = tmp[v.good_id].amount + v.amount
  678 + end
  679 + end
  680 + end
  681 + end
  682 + return tmp
617 683 end
618 684  
619 685 function Capsule:drawByCount(roleId, count)
... ... @@ -621,6 +687,8 @@ function Capsule:drawByCount(roleId, count)
621 687  
622 688 local goods = self:getProperty("goods") or {}
623 689 local record = self:getProperty("record") or {}
  690 + local rank = self:getProperty("rank") or {}
  691 + local rankRole = rank[roleId] or 0
624 692 local recordByRole = self:getProperty("recordByRole") or {}
625 693 local roleRecord = recordByRole[roleId] or {}
626 694  
... ... @@ -630,9 +698,8 @@ function Capsule:drawByCount(roleId, count)
630 698 local goods_id = ichibankuji["goods_id"]
631 699 local now = skynet.timex()
632 700  
633   - --奖励, 通知信息
634   - local notify= {}
635   - notify[roleId] = {}
  701 + --奖励,普通奖品信息
  702 + local goodsByUsual= {}
636 703  
637 704 local name = getNameByRoleId(roleId)
638 705 while (goods and next(goods) and count > 0) do
... ... @@ -643,15 +710,18 @@ function Capsule:drawByCount(roleId, count)
643 710 if good and good.amount > 0 then
644 711 good.amount = good.amount - 1
645 712  
  713 + --插入rank
  714 + rankRole = rankRole + 1
  715 +
646 716 --插入记录
647 717 local tmpNotify = {roleId = roleId, name= name, good_id = good_id, typ = RewardType.GOODS, award = good.award, amount = 1, quality = good.quality, create_time= now}
648 718 table.insert(record, tmpNotify)
649 719  
650 720 --作为奖励记录+通知
651   - if not notify[roleId][good_id] then
652   - notify[roleId][good_id] = tmpNotify
  721 + if not goodsByUsual[good_id] then
  722 + goodsByUsual[good_id] = tmpNotify
653 723 else
654   - notify[roleId][good_id].amount = notify[roleId][good_id].amount + 1
  724 + goodsByUsual[good_id].amount = goodsByUsual[good_id].amount + 1
655 725 end
656 726  
657 727 --记录角色的抽奖记录 计算激励奖需要用到
... ... @@ -666,48 +736,46 @@ function Capsule:drawByCount(roleId, count)
666 736 end
667 737  
668 738 end
  739 +
  740 + --奖励池重新赋值
  741 + rank[roleId] = rankRole
669 742 recordByRole[roleId] = roleRecord
670   - self:setProperties({recordByRole = recordByRole, record = record, goods = goods})
  743 + self:setProperties({recordByRole = recordByRole, record = record, goods = goods, rank = rank})
671 744  
672   - local tmpNotify = self:checkIncentive(roleId, name, now)
673   - for k, v in pairs(tmpNotify) do
674   - if not notify[roleId][k] then
675   - notify[roleId][k] = v
676   - else
677   - notify[roleId][k].amount = notify[roleId][k].amount + v.amount
678   - end
679   - end
  745 + --奖励收集
  746 + local reward = {}
  747 + rewardCollect(reward, goodsByUsual)
680 748  
681   - local speciNotify = self:checkSpecialReward(now)
682   - rewardToNtyFunc(notify, speciNotify)
683   -
684   - local reward, rewardByGoods = {}, {}
685   - for key, val in pairs(notify) do
686   - if key == roleId then
687   - for k, v in pairs(val) do
688   - for id, count in pairs(v.award:toNumMap()) do
689   - reward[id] = (reward[id] or 0) + count
690   - end
691   - rewardByGoods[k] = v
692   - end
693   - end
  749 + local goodsByIncentive = self:checkIncentive(roleId, name, now)
  750 + rewardCollect(reward, goodsByIncentive)
694 751  
  752 + local goodsAmount = self:getGoodsAmount()
  753 + if goodsAmount == 0 then
  754 + self:setProperty("drawEndTime", now)
695 755 end
696   - return reward, rewardByGoods, notify
  756 +
  757 + local goodsBySpecial = self:checkSpecialReward(now, goodsAmount)
  758 + local specialByRole = rewardCollectByRoleId(roleId, reward, goodsBySpecial)
  759 +
  760 + return {reward = reward, usual = goodsByUsual, incentive = goodsByIncentive, specials = goodsBySpecial, special = specialByRole}
697 761 end
698 762  
699 763 function Capsule:drawAll(roleId)
700 764 local goods = self:getProperty("goods") or {}
701 765 local record = self:getProperty("record") or {}
  766 + local rank = self:getProperty("rank") or {}
  767 + local rankRole = rank[roleId] or 0
702 768 local recordByRole = self:getProperty("recordByRole") or {}
703 769 local roleRecord = recordByRole[roleId] or {}
704 770 local now = skynet.timex()
705 771  
706 772 local name = getNameByRoleId(roleId)
707   - local notify = {}
708   - notify[roleId] = {}
  773 + local goodsByUsual = {}
709 774 for good_id, good in pairs(goods) do
710 775 if good.amount > 0 then
  776 + --插入rank
  777 + rankRole = rankRole + good.amount
  778 +
711 779 --插入记录
712 780 local tmpNotify = {roleId = roleId, name= name, good_id = good_id, typ = RewardType.GOODS, award = good.award, amount = good.amount, quality = good.quality, create_time = now}
713 781 for i = 1, good.amount do
... ... @@ -715,10 +783,10 @@ function Capsule:drawAll(roleId)
715 783 end
716 784  
717 785 --作为奖励记录+通知
718   - if not notify[roleId][good_id] then
719   - notify[roleId][good_id] = tmpNotify
  786 + if not goodsByUsual[good_id] then
  787 + goodsByUsual[good_id] = tmpNotify
720 788 else
721   - notify[roleId][good_id].amount = notify[roleId][good_id].amount + good.award
  789 + goodsByUsual[good_id].amount = goodsByUsual[good_id].amount + good.award
722 790 end
723 791  
724 792 --记录角色的抽奖记录
... ... @@ -732,34 +800,26 @@ function Capsule:drawAll(roleId)
732 800 end
733 801  
734 802 end
  803 + rank[roleId] = rankRole
735 804 recordByRole[roleId] = roleRecord
736   - self:setProperties({recordByRole = recordByRole, record = record, goods = goods})
  805 + self:setProperties({recordByRole = recordByRole, record = record, goods = goods, rank = rank})
737 806  
738   - local tmpNotify = self:checkIncentive(roleId, name, now)
739   - for k, v in pairs(tmpNotify) do
740   - if not notify[roleId][k] then
741   - notify[roleId][k] = v
742   - else
743   - notify[roleId][k].amount = notify[roleId][k].amount + v.amount
744   - end
745   - end
746   -
747   - local speciNotify = self:checkSpecialReward(now)
748   - rewardToNtyFunc(notify, speciNotify)
  807 + --奖励收集
  808 + local reward = {}
  809 + rewardCollect(reward, goodsByUsual)
749 810  
750   - local reward, rewardByGoods = {}, {}
751   - for key, val in pairs(notify) do
752   - if key == roleId then
753   - for k, v in pairs(val) do
754   - for id, count in pairs(v.award:toNumMap()) do
755   - reward[id] = (reward[id] or 0) + count
756   - end
757   - rewardByGoods[k] = v
758   - end
759   - end
  811 + local goodsByIncentive = self:checkIncentive(roleId, name, now)
  812 + rewardCollect(reward, goodsByIncentive)
760 813  
  814 + local goodsAmount = self:getGoodsAmount()
  815 + if goodsAmount == 0 then
  816 + self:setProperty("drawEndTime", now)
761 817 end
762   - return reward, rewardByGoods, notify
  818 +
  819 + local goodsBySpecial = self:checkSpecialReward(now, goodsAmount)
  820 + local specialByRole = rewardCollectByRoleId(roleId, reward, goodsBySpecial)
  821 +
  822 + return {reward = reward, usual = goodsByUsual, incentive = goodsByIncentive, specials = goodsBySpecial, special = specialByRole}
763 823 end
764 824  
765 825 --@param
... ... @@ -790,6 +850,65 @@ function Capsule:draw(roleId, full, cares)
790 850 end
791 851 end
792 852  
  853 +function Capsule:pageRecord(up, idx)
  854 + local record = self:getProperty("record") or {}
  855 + if not next(record) then return nil end
  856 +
  857 + --默认取20条
  858 + idx = idx or #record
  859 + up = up or 0
  860 +
  861 + local count = 0
  862 + local tmpRecord = {}
  863 + if up == 1 then
  864 + --向上获取索引更大的 从上往下拉
  865 + count = math.min(#record - idx, 20)
  866 + for i = idx, count do
  867 + tmpRecord[i] = record[i]
  868 + end
  869 + else
  870 + --向下获取索引更小的 从下往上拉
  871 + count = math.max(idx - 20, 0)
  872 + for i = count, idx do
  873 + tmpRecord[i] = record[i]
  874 + end
  875 + end
  876 +
  877 + return tmpRecord
  878 +end
  879 +
  880 +--检查是否有未领取奖励的通知
  881 +function Capsule:getSpecialNotify(roleId)
  882 + local specialsRecord = self:getProperty("specialsRecord") or {}
  883 + local tmp = {}
  884 + for _, goods in pairs(specialsRecord) do
  885 + for _, good in ipairs(goods) do
  886 + if good.roleId == roleId then
  887 + if not good.nty or good.nty == 0 then
  888 + tmp[good.good_id] = good
  889 + end
  890 + end
  891 + end
  892 + end
  893 + self:setProperty("specialsRecord", specialsRecord)
  894 +
  895 + return tmp
  896 +end
  897 +
  898 +function Capsule:clearSpecialNty(roleId, good_ids)
  899 + local specialsRecord = self:getProperty("specialsRecord") or {}
  900 + for _, goods in pairs(specialsRecord) do
  901 + for _, good in ipairs(goods) do
  902 + for _, good_id in ipairs(good_ids) do
  903 + if good_id == good.good_id and good.roleId == roleId then
  904 + good.nty = 1
  905 + end
  906 + end
  907 + end
  908 + end
  909 + self:setProperty("specialsRecord", specialsRecord)
  910 +end
  911 +
793 912  
794 913 function Capsule:data(roleId)
795 914 return {
... ... @@ -800,7 +919,7 @@ function Capsule:data(roleId)
800 919 coin = self:getProperty("coin"),
801 920 onlineCount = self:getOnlineCount(),
802 921 playerStatus = self:getRegisterByRoleId(roleId),
803   - record = self:getProperty("record"),
  922 + record = self:pageRecord() or {},
804 923 rank = self:getProperty("rank"),
805 924 goods = self:getProperty("goods"),
806 925 specials = self:getProperty("specials"),
... ...
src/models/RoleCross.lua
... ... @@ -211,7 +211,6 @@ RoleCross.bind = function (Role)
211 211 end
212 212  
213 213 function Role:paySpecialReward(roleId, notify)
214   - dump(notify)
215 214 if notify and next(notify) then
216 215 local reward = {}
217 216 for key, val in pairs(notify) do
... ... @@ -221,6 +220,7 @@ RoleCross.bind = function (Role)
221 220  
222 221 end
223 222 self:award(reward, {log = {desc = "CapsuleReward", int1=roleId}})
  223 + SendPacket(actionCodes.Capsule_notifyChange, MsgPack.pack({special = notify}))
224 224 end
225 225 end
226 226  
... ...
src/models/RolePlugin.lua
... ... @@ -2090,7 +2090,7 @@ function RolePlugin.bind(Role)
2090 2090 local emailSync = math.max(emailSync + 1, globalEmail - EMAIL_LIMIT + 1)
2091 2091 local redret = redisproxy:pipelining(function (red)
2092 2092 for id = emailSync, globalEmail do
2093   - red:hgetall(string.format("globalEmail:%s", id))
  2093 + red:hgetall(string.format("globalEmail:%s", id))
2094 2094 end
2095 2095 end)
2096 2096 for _, data in ipairs(redret) do
... ... @@ -3165,17 +3165,20 @@ function RolePlugin.bind(Role)
3165 3165 end
3166 3166  
3167 3167 function Role:drawCapsule(capsuleId, full, cares)
3168   - local capsule = self.capsules[capsuleId] or {}
3169   - if next(capsule) then
3170   - local roleId = self:getProperty("id")
3171   - return capsule:draw(roleId, full, cares)
3172   - end
3173   - return 3
  3168 + local capsule = self.capsules[capsuleId]
  3169 + if not capsule then return nil end
  3170 +
  3171 + local roleId = self:getProperty("id")
  3172 + local ret, drawReward = capsule:draw(roleId, full, cares)
  3173 + drawReward["specials"] = nil
  3174 + return ret, drawReward, capsule:data(roleId)
3174 3175 end
3175 3176  
3176   - function Role:joinCapsule(capsuleId)
3177   - local capsule = self.capsules[capsuleId] or {}
3178   - return capsule:data()
  3177 + function Role:joinCapsule(roleId, capsuleId)
  3178 + local capsule = self.capsules[capsuleId]
  3179 + if not capsule then return nil end
  3180 +
  3181 + return capsule:data(roleId)
3179 3182 end
3180 3183  
3181 3184 function Role:checkCapsule(now)
... ... @@ -3188,13 +3191,17 @@ function RolePlugin.bind(Role)
3188 3191 end
3189 3192  
3190 3193 function Role:goodStock(capsuleId)
3191   - local capsule = self.capsules[capsuleId] or {}
  3194 + local capsule = self.capsules[capsuleId]
  3195 + if not capsule then return 0 end
  3196 +
3192 3197 return capsule:getGoodsAmount(), capsule:getProperty("token")
3193 3198 end
3194 3199  
3195   - function Role:getCapsuleData(capsuleId)
3196   - local capsule = self.capsules[capsuleId] or {}
3197   - return capsule:data()
  3200 + function Role:getCapsuleData(roleId, capsuleId)
  3201 + local capsule = self.capsules[capsuleId]
  3202 + if not capsule then return nil end
  3203 +
  3204 + return capsule:data(roleId)
3198 3205 end
3199 3206  
3200 3207 function Role:resetCapsule()
... ... @@ -3220,6 +3227,20 @@ function RolePlugin.bind(Role)
3220 3227 end
3221 3228 end
3222 3229 end
  3230 +
  3231 + function Role:pageRecord(capsuleId, up, idx)
  3232 + local capsule = self.capsules[capsuleId]
  3233 + if not capsule then return nil end
  3234 +
  3235 + return capsule:pageRecord(up, idx)
  3236 + end
  3237 +
  3238 + function Role:getSpecialNotify(roleId, capsuleId)
  3239 + local capsule = self.capsules[capsuleId]
  3240 + if not capsule then return nil end
  3241 +
  3242 + return capsule:getSpecialNotify(roleId)
  3243 + end
3223 3244 end
3224 3245  
3225 3246 return RolePlugin
3226 3247 \ No newline at end of file
... ...
src/services/agent_ctrl.lua
... ... @@ -141,10 +141,11 @@ function _M:check_agent_status()
141 141 end
142 142 end
143 143  
  144 + datacenter.set("onlineCount", count)
144 145 if now >= next_log_time and now % 60 == 0 then
145 146 next_log_time = now + 60
146 147 local count = table_nums(self.u2f)
147   - datacenter.set("onlineCount", count)
  148 + --datacenter.set("onlineCount", count)
148 149 logproxy:log({["@type"] = "online", count = count}, "log")
149 150 end
150 151 end
... ...
src/services/capsuled.lua
... ... @@ -51,7 +51,9 @@ function getNameByRoleId(roleId)
51 51 end
52 52  
53 53 function broadCastCapsule(roleId, capsuleId, broadInfo)
54   - local capsule = capsules[capsuleId] or {}
  54 + local capsule = capsules[capsuleId]
  55 + if not capsule then print("not capsule :" .. capsuleId) return end
  56 +
55 57 local register = capsule:getProperty("register") or {}
56 58 if next(capsule) then
57 59 for id, _ in pairs(register) do
... ... @@ -63,21 +65,23 @@ function broadCastCapsule(roleId, capsuleId, broadInfo)
63 65 end
64 66  
65 67 function broadCastSpecial(roleId, capsuleId, broadInfo)
66   - local capsule = capsules[capsuleId] or {}
  68 + if not broadInfo or not next(broadInfo) then return end
  69 + local capsule = capsules[capsuleId]
  70 + if not capsule then skynet.error("not capsule: " .. capsuleId) return end
  71 +
67 72 local register = capsule:getProperty("register") or {}
68   - if next(capsule) then
69   - for id, _ in pairs(register) do
70   - if id ~= roleId then
71   - if broadInfo[id] then
72   - rpcRole(id, "paySpecialReward", id, broadInfo[id])
73   - end
  73 + for id, _ in pairs(register) do
  74 + if id ~= roleId then
  75 + if broadInfo[id] then
  76 + rpcRole(id, "paySpecialReward", id, broadInfo[id])
74 77 end
75 78 end
76 79 end
77 80 end
78 81  
79 82 local function add(roleId, capsuleId)
80   - local capsule = capsules[capsuleId] or {}
  83 + local capsule = capsules[capsuleId]
  84 + if not capsule then skynet.error("not capsule: " .. capsuleId) return end
81 85 if next(capsule) then
82 86 capsule:join(roleId)
83 87 broadCastCapsule(roleId, capsuleId, {notifyType= NotifyChangeType.JOIN, roleId = roleId})
... ... @@ -88,8 +92,9 @@ local function add(roleId, capsuleId)
88 92 end
89 93  
90 94 local function capsuleRefreshing()
  95 + local now = skynet.timex()
91 96 for _, v in pairs(capsules) do
92   - if v:refreshing() then
  97 + if v:refreshing(now) then
93 98 v:init()
94 99 v:create()
95 100 end
... ... @@ -114,13 +119,11 @@ function CMD.reset()
114 119 for _, val in ipairs(data) do
115 120 if val.type == 1 then
116 121 local key = val.id..val.room
117   - if not capsules[key] then
118   - local capsule = require("models.Capsule").new({ key = CAPSULE_PUBLIC:format(key), id= val.id, room = val.room, typ = 1, name=val.name})
119   - capsule:init()
120   - capsule:create()
121   - capsules[key] = capsule
122   - redisproxy:sadd(CAPSULE_INFO, key)
123   - end
  122 + local capsule = require("models.Capsule").new({ key = CAPSULE_PUBLIC:format(key), id= val.id, room = val.room, typ = 1, name=val.name})
  123 + capsule:init()
  124 + capsule:create()
  125 + capsules[key] = capsule
  126 + redisproxy:sadd(CAPSULE_INFO, key)
124 127 end
125 128 end
126 129 end
... ... @@ -149,11 +152,14 @@ function CMD.start()
149 152 if val.type == 1 then
150 153 local key = val.id..val.room
151 154 if not capsules[key] then
152   - local capsule = require("models.Capsule").new({ key = CAPSULE_PUBLIC:format(key), id= val.id, room = val.room, typ = 1, name=val.name})
153   - capsule:init()
154   - capsule:create()
155   - capsules[key] = capsule
156   - redisproxy:sadd(CAPSULE_INFO, key)
  155 + if now < val.hide_time then
  156 + local capsule = require("models.Capsule").new({ key = CAPSULE_PUBLIC:format(key), id= val.id, room = val.room, typ = 1, name=val.name})
  157 + capsule:init()
  158 + capsule:create()
  159 +
  160 + capsules[key] = capsule
  161 + redisproxy:sadd(CAPSULE_INFO, key)
  162 + end
157 163 end
158 164 end
159 165 end
... ... @@ -183,49 +189,76 @@ end
183 189  
184 190 function CMD.exit(roleId, capsuleId)
185 191 if capsuleId then
186   - local capsule = capsules[capsuleId] or {}
187   - if next(capsule) then
188   - capsule:exit(roleId)
189   - broadCastCapsule(roleId, capsuleId, {notifyType = NotifyChangeType.EXIT, roleId = roleId})
190   - end
  192 + local capsule = capsules[capsuleId]
  193 + if not capsule then skynet.error("not capsule: " .. capsuleId) return end
  194 +
  195 + capsule:exit(roleId)
  196 + broadCastCapsule(roleId, capsuleId, {notifyType = NotifyChangeType.EXIT, roleId = roleId})
191 197 else
192   - for _, capsule in pairs(capsules) do
  198 + for id, capsule in pairs(capsules) do
193 199 if next(capsule) then
194 200 capsule:exit(roleId)
195   - broadCastCapsule(roleId, capsuleId, {notifyType = NotifyChangeType.EXIT, roleId = roleId})
  201 + broadCastCapsule(roleId, id, {notifyType = NotifyChangeType.EXIT, roleId = roleId})
196 202 end
197 203 end
198 204 end
199 205 end
200 206  
201 207 function CMD.draw_capsule(roleId, capsuleId, full, drawsNum, cares)
202   - local capsule = capsules[capsuleId] or {}
203   - if next(capsule) then
204   - local ret, reward, rewardByGoods, notify = capsule:draw(roleId, full, drawsNum, cares)
205   - if ret > 5 then
206   - --broadCastCapsule(roleId, capsuleId, {notifyType = NotifyChangeType.DRAW, notify = notify})
207   - broadCastSpecial(roleId, capsuleId, notify)
208   - end
209   - return ret, reward, rewardByGoods, capsule:data(roleId)
  208 + local capsule = capsules[capsuleId]
  209 + if not capsule then skynet.error("not capsule: " .. capsuleId) return 2 end
  210 +
  211 + local ret, drawReward = capsule:draw(roleId, full, drawsNum, cares)
  212 + if ret > 5 then
  213 + --broadCastCapsule(roleId, capsuleId, {notifyType = NotifyChangeType.DRAW, notify = notify})
  214 + broadCastSpecial(roleId, capsuleId, drawReward["specials"])
210 215 end
211   - return 2
  216 + drawReward["specials"] = nil
  217 + return ret, drawReward, capsule:data(roleId)
212 218 end
213 219  
214 220 function CMD.register(roleId, capsuleId)
215   - local capsule = capsules[capsuleId] or {}
  221 + local capsule = capsules[capsuleId]
  222 + if not capsule then skynet.error("not capsule: " .. capsuleId) return nil end
  223 +
216 224 return capsule:register(roleId)
217 225 end
218 226  
219 227 function CMD.goods_stock(capsuleId)
220   - local capsule = capsules[capsuleId] or {}
  228 + local capsule = capsules[capsuleId]
  229 + if not capsule then skynet.error("not capsule: " .. capsuleId) return 0 end
  230 +
221 231 return capsule:getGoodsAmount(), capsule:getProperty("token")
222 232 end
223 233  
224 234 function CMD.capsule_data(roleId, capsuleId)
225   - local capsule = capsules[capsuleId] or {}
  235 + local capsule = capsules[capsuleId]
  236 + if not capsule then skynet.error("not capsule: " .. capsuleId) return nil end
  237 +
226 238 return capsule:data(roleId)
227 239 end
228 240  
  241 +function CMD.page_record(capsuleId, up, idx)
  242 + local capsule = capsules[capsuleId]
  243 + if not capsule then skynet.error("not capsule: " .. capsuleId) return nil end
  244 +
  245 + return capsule:pageRecord(up, idx)
  246 +end
  247 +
  248 +function CMD.get_special_nty(roleId, capsuleId)
  249 + local capsule = capsules[capsuleId]
  250 + if not capsule then skynet.error("not capsule: " .. capsuleId) return nil end
  251 +
  252 + return capsule:getSpecialNotify(roleId)
  253 +end
  254 +
  255 +function CMD.clear_special_nty(roleId, capsuleId, good_ids)
  256 + local capsule = capsules[capsuleId]
  257 + if not capsule then skynet.error("not capsule: " .. capsuleId) return nil end
  258 +
  259 + return capsule:clearSpecialNty(roleId, good_ids)
  260 +end
  261 +
229 262 skynet.start(function()
230 263 skynet.dispatch("lua", function(session, address, cmd, ...)
231 264 local f = CMD[string.lower(cmd)]
... ...
src/services/watchdog.lua
... ... @@ -56,7 +56,7 @@ end
56 56  
57 57 -- 创建world以及union channel 用于广播
58 58 function create_mutilcast()
59   - for i = 1, 10 do
  59 + for i = 1, 50 do
60 60 local chan_w = mc:new()
61 61 datacenter.set("MC_W_CHANNEL" .. i, chan_w.channel)
62 62 end
... ...