diff --git a/game-server/app/servers/role/handler/shopHandler.ts b/game-server/app/servers/role/handler/shopHandler.ts index 7e4017b18..10e8705a3 100644 --- a/game-server/app/servers/role/handler/shopHandler.ts +++ b/game-server/app/servers/role/handler/shopHandler.ts @@ -2,15 +2,13 @@ import { Application, BackendSession } from "pinus"; import { gameData, hasShopType } from "../../../pubUtils/data"; import { parseGoodStr, resResult } from "../../../pubUtils/util"; import { STATUS, GUILD_STRUCTURE, ITID, CONSUME_TYPE, HERO_QUALITY_TYPE, HERO_GROW_MAX, ITEM_CHANGE_REASON } from "../../../consts"; -import { DicShopListModel } from "../../../db/DicShopList"; import { UserShopModel } from "../../../db/UserShop"; import { handleCost, addItems } from "../../../services/role/rewardService"; -import { GuildModel } from "../../../db/Guild"; import { SHOP } from "../../../pubUtils/dicParam"; import { HeroModel } from "../../../db/Hero"; -import { getShopDicById, getShopListByType, getShopPrice } from "../../../services/shopService"; +import { checkShopInPurchase, getShopDicById, getShopListByType, getShopPrice } from "../../../services/shopService"; import { RewardInter } from "../../../pubUtils/interface"; -import { RoleModel } from "../../../db/Role"; +import { UserShopTypeModel } from "../../../db/UserShopType"; export default function(app: Application) { return new ShopHandler(app); @@ -34,43 +32,38 @@ export class ShopHandler { return resResult(STATUS.SUCCESS, result); } + // 读取红点 + async readShop(msg: { shop: number, type: number }, session: BackendSession) { + let roleId = session.get('roleId'); + let { shop, type } = msg; + + if(!hasShopType(shop, type)) { + return resResult(STATUS.WRONG_PARMS); + } + + await UserShopTypeModel.read(roleId, shop, type); + return resResult(STATUS.SUCCESS); + } + // 购买商品 async purchase(msg: { activityId: number, shopItemId: number, count: number }, session: BackendSession) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); - let guildCode = session.get('guildCode'); let serverId = session.get('serverId'); - let vipStartTime: number = session.get('vipStartTime'); let { activityId, shopItemId, count } = msg; if( count < 0) return resResult(STATUS.WRONG_PARMS); let dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId); - if(!dicShopItem) return resResult(STATUS.DIC_DATA_NOT_FOUND); - - if(dicShopItem.guildLvLimit) { - let myGuild = await GuildModel.findByCode(guildCode, serverId); - if(!myGuild || myGuild.lv < dicShopItem.guildLvLimit) return resResult(STATUS.GUILD_LV_LIMIT); - } - if(dicShopItem.lvLimit) { - let role = await RoleModel.findByRoleId(roleId, 'lv'); - if(role.lv < dicShopItem.lvLimit) { - return resResult(STATUS.LV_LIMIT); - } - } + if(!dicShopItem) return STATUS.DIC_DATA_NOT_FOUND; + if(dicShopItem['productID']) return resResult(STATUS.CAN_NOT_PURCHASE); let userShop = await UserShopModel.findByRoleAndItem(roleId, activityId, dicShopItem); - if(dicShopItem.purchaseLimit != -1) { - if(vipStartTime > 0 && dicShopItem.purchaseLimit != -1) { - if(userShop && userShop.count + count > dicShopItem.purchaseLimit + dicShopItem.vipPurchaseLimit) { - return resResult(STATUS.BUY_COUNT_OVER); - } - } else { - if(userShop && userShop.count + count > dicShopItem.purchaseLimit) { - return resResult(STATUS.BUY_COUNT_OVER); - } - } + + let checkResult = await checkShopInPurchase(session, activityId, count, userShop?.count||0, dicShopItem); + if(checkResult.code != STATUS.SUCCESS.code) { + return resResult(checkResult); } // 消耗 diff --git a/game-server/app/services/orderService.ts b/game-server/app/services/orderService.ts index 48cd24df2..f06793b23 100644 --- a/game-server/app/services/orderService.ts +++ b/game-server/app/services/orderService.ts @@ -33,15 +33,20 @@ import { addGuildPay } from './activity/guildPayService'; import { sendMessageToUserWithSuc } from './pushService'; import { gameData } from '../pubUtils/data'; import { checkParamPrice } from '../pubUtils/sdkUtil'; +import { checkShopCanBuyInOrder, makeShopOrder } from './shopService'; export async function checkOrderCanBuy(roleId: string, serverId: number, activityData: ActivityModelType, productID: string, paramStr: string) { let activityId = activityData.activityId; - console.log('*****', activityData.type) + switch(activityData.type) { case ACTIVITY_TYPE.POP_UP_SHOP: { return await checkPopUpShopCanBuy(roleId, serverId, activityId, productID, paramStr) } + case ACTIVITY_TYPE.SHOP: + { + return await checkShopCanBuyInOrder(roleId, serverId, activityData, productID) + } } return true } @@ -151,6 +156,12 @@ export async function makeOrder(orderInfo: UserOrderModelType, sid: string) { rewardResult = await makeTaskPass(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) break; + } + case ACTIVITY_TYPE.SHOP: // 商店 + { + rewardResult = await makeShopOrder(roleId, roleInfo.roleName, sid, orderInfo.serverId, orderInfo.activityId, orderInfo.productID) + break; + } default: rewardResult = STATUS.ERROR_TYPE; diff --git a/game-server/app/services/shopService.ts b/game-server/app/services/shopService.ts index b37ee843a..17c1a3d50 100644 --- a/game-server/app/services/shopService.ts +++ b/game-server/app/services/shopService.ts @@ -1,18 +1,28 @@ import { gameData, getShopType } from "../pubUtils/data"; -import { ShopData, ShopReturnData } from '../domain/roleField/shop'; +import { ShopData, ShopDicExtendData, ShopReturnData } from '../domain/roleField/shop'; import { UserShopModel, UserShopType } from "../db/UserShop"; import { getActivitiesByType, getActivityById } from "./activity/activityService"; -import { ACTIVITY_TYPE } from "../consts"; +import { ACTIVITY_TYPE, ITEM_CHANGE_REASON, STATUS } from "../consts"; import { getRoleCreateTime, getServerCreateTime } from "./redisService"; import { decodeArrayListStr } from "../pubUtils/util"; +import { UserShopTypeModel, UserShopTypeType } from "../db/UserShopType"; +import { GuildModel } from "../db/Guild"; +import { RoleModel } from "../db/Role"; +import { DicShop } from "../pubUtils/dictionary/DicShop"; +import { BackendSession } from "pinus"; +import { ActivityModelType } from "../db/Activity"; +import { addItems } from "./role/rewardService"; export async function getAllShopList(roleId: string, serverId: number) { let userShopRecs = await UserShopModel.findByRoleId(roleId); + let userShopTypeRecs = await UserShopTypeModel.findByRoleId(roleId); let activities = await getShopActivityDatas(roleId, serverId); let shops: ShopReturnData[] = []; for(let [_, { shop, type } ] of gameData.shopType) { - let shopData = await getShopListByData(shop, type, userShopRecs, activities); + let activity = activities.find(cur => cur.shop == shop && cur.type == type); + let readRecord = userShopTypeRecs.find(cur => cur.shop == shop && cur.type == type); + let shopData = await getShopListByData(shop, type, userShopRecs, activity, readRecord); shops.push(shopData); } return shops; @@ -21,20 +31,22 @@ export async function getAllShopList(roleId: string, serverId: number) { export async function getShopListByType(shop: number, type: number, roleId: string, serverId: number) { let userShopRecs = await UserShopModel.findByShopType(roleId, shop, type); let activities = await getShopActivityDatas(roleId, serverId); - return await getShopListByData(shop, type, userShopRecs, activities); + let activity = activities.find(cur => cur.shop == shop && cur.type == type); + let readRecord = await UserShopTypeModel.findByType(roleId, shop, type); + return await getShopListByData(shop, type, userShopRecs, activity, readRecord); } -async function getShopListByData(shop: number, type: number, userShopRecs: UserShopType[], activities: ShopData[]) { +async function getShopListByData(shop: number, type: number, userShopRecs: UserShopType[], activity: ShopData, readRecord: UserShopTypeType) { let result = new ShopReturnData(shop, type); let dicShopType = getShopType(shop, type); if(dicShopType && dicShopType.isLimit) { - for(let activity of activities) { - result.setDicByActivity(activity); - } + if(activity) result.setDicByActivity(activity); + if(readRecord) result.setReadRecord(readRecord); } + console.log('###### getShopListByData', userShopRecs) for(let userShop of userShopRecs) { - result.setUserRecords(userShop); + result.addUserRecords(userShop); } return result; @@ -101,4 +113,94 @@ function parseShopPrice(str: string) { result.push({ times: parseInt(times), price: parseInt(price) }); } return result +} + +export async function checkShopInPurchase(session: BackendSession, activityId: number, count: number, buyCount: number, dicShopItem: DicShop|ShopDicExtendData) { + let roleId = session.get('roleId'); + let guildCode = session.get('guildCode'); + let serverId = session.get('serverId'); + let vipStartTime: number = session.get('vipStartTime'); + + return await checkShopItemCanBuy(activityId, dicShopItem.id, roleId, serverId, guildCode, vipStartTime, count, buyCount, dicShopItem) +} + +export async function checkShopCanBuyInOrder(roleId: string, serverId: number, activity: ActivityModelType, productID: string) { + let role = await RoleModel.findByRoleId(roleId, 'guildCode createTime vipStartTime'); + let { createTime, guildCode, vipStartTime } = role; + let serverTime = await getServerCreateTime(serverId); + let shopData = new ShopData(activity, createTime, serverTime); + if(!shopData) return false; + let dicItem = shopData.findByProductID(productID); + if(!dicItem) return false; + + let userShop = await UserShopModel.findByRoleAndItem(roleId, activity.activityId, dicItem); + let result = await checkShopItemCanBuy(activity.activityId, dicItem.id, roleId, serverId, guildCode, vipStartTime, 1, userShop?.count||0, dicItem); + return result.code == STATUS.SUCCESS.code; +} + +export async function checkShopItemCanBuy(activityId: number, shopItemId: number, roleId: string, serverId: number, guildCode: string, vipStartTime: number, count: number, buyCount: number, dicShopItem?: DicShop|ShopDicExtendData) { + + if(!dicShopItem) { + dicShopItem = await getShopDicById(activityId, shopItemId, roleId, serverId); + } + if(!dicShopItem) return STATUS.DIC_DATA_NOT_FOUND; + + if(dicShopItem.guildLvLimit) { + let myGuild = await GuildModel.findByCode(guildCode, serverId); + if(!myGuild || myGuild.lv < dicShopItem.guildLvLimit) return STATUS.GUILD_LV_LIMIT; + } + if(dicShopItem.lvLimit) { + let role = await RoleModel.findByRoleId(roleId, 'lv'); + if(role.lv < dicShopItem.lvLimit) { + return STATUS.LV_LIMIT; + } + } + + if(dicShopItem.purchaseLimit != -1) { + if(vipStartTime > 0 && dicShopItem.vipPurchaseLimit != -1) { + if(buyCount + count > dicShopItem.purchaseLimit + dicShopItem.vipPurchaseLimit) { + return STATUS.BUY_COUNT_OVER; + } + } else { + if(buyCount + count > dicShopItem.purchaseLimit) { + return STATUS.BUY_COUNT_OVER; + } + } + } + return STATUS.SUCCESS +} + +/** + * rmb购买 + * + * @param {number} serverId 区Id + * @param {number} activityId 活动Id + * @param {string} roleId 角色Id + * @param {string} productID 商品ID + * + */ + export async function makeShopOrder(roleId: string, roleName: string, sid: string, serverId: number, activityId: number, productID: string) { + let activityData: ActivityModelType = await getActivityById(activityId); + if (!activityData) { + return STATUS.ACTIVITY_MISSING; + } + if (activityData.type !== ACTIVITY_TYPE.SHOP) { + return STATUS.ACTIVITY_TYPE_ERROR; + } + let createTime = await getRoleCreateTime(roleId); + let serverTime = await getServerCreateTime(serverId); + let shopData = new ShopData(activityData, createTime, serverTime); + let dicItem = shopData.findByProductID(productID); + if(!dicItem) return STATUS.DIC_DATA_NOT_FOUND; + let reward = [{ + id: dicItem.goodId, + count: 1 + }]; + await addItems(roleId, roleName, sid, reward, ITEM_CHANGE_REASON.SHOP_PURCHASE); + + await UserShopModel.purchase(roleId, roleName, activityId, dicItem, 1); + return { + code: 0, + data: Object.assign({}, { item: { shop: dicItem.shop, type: dicItem.type, shopItemId: dicItem.id }, activityId: activityId }) + } } \ No newline at end of file diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index d3be420cd..a07729666 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -414,6 +414,7 @@ export const STATUS = { SKIN_HAS_NOT_HERO: { code: 30903, simStr: '未拥有该武将不可获得皮肤' }, HERO_NOT_MAX: { code: 30904, simStr: '该武将未升满星' }, LV_LIMIT: { code: 30905, simStr: '玩家等级不足' }, + CAN_NOT_PURCHASE: { code: 30906, simStr: '该商品不可使用该购买方式' }, // 任务相关 31001-31100 TASK_NOT_REACH_CONDITION: { code: 31001, simStr: '任务不满足条件' }, diff --git a/shared/db/UserShop.ts b/shared/db/UserShop.ts index e22d72091..1ddf16ae4 100644 --- a/shared/db/UserShop.ts +++ b/shared/db/UserShop.ts @@ -32,6 +32,9 @@ export default class UserShop extends BaseModel { @prop({ required: true }) itemId: number; // 商品id + @prop({ required: true }) + createTime: number; // 商品上新时间 + @prop({ required: true }) goodId: number; // 商品包含的物品id @@ -55,9 +58,9 @@ export default class UserShop extends BaseModel { } - public static async findByShopType(roleId: string, shopId: number, typeId: number) { + public static async findByShopType(roleId: string, shop: number, type: number) { let timeCondition = this.getRefreshCondition(); - let rec: UserShopType[] = await UserShopModel.find({ shopId, typeId, roleId, $or: timeCondition }).lean(); + let rec: UserShopType[] = await UserShopModel.find({ shop, type, roleId, $or: timeCondition }).lean(); return rec; } @@ -67,21 +70,21 @@ export default class UserShop extends BaseModel { return rec; } - public static async findByRoleAndItem(roleId: string, activityId: number, dicShopItem: { id: number, shop: number, type: number }) { + public static async findByRoleAndItem(roleId: string, activityId: number, dicShopItem: { id: number, shop: number, type: number, createTime?: number }) { let timeCondition = this.getRefreshCondition(); - let { id, shop, type } = dicShopItem; + let { id, shop, type, createTime = 0 } = dicShopItem; - let rec: UserShopType = await UserShopModel.findOne({ roleId, itemId: id, shop, type, activityId, $or: timeCondition }).lean(); + let rec: UserShopType = await UserShopModel.findOne({ roleId, itemId: id, shop, type, activityId, createTime, $or: timeCondition }).lean(); return rec; } - public static async purchase(roleId: string, roleName: string, activityId: number, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number }, inc: number) { + public static async purchase(roleId: string, roleName: string, activityId: number, dicShopItem: { id: number, goodId: number, refreshType: number, shop: number, type: number, createTime?: number }, inc: number) { let code = genCode(8); let timeCondition = this.getRefreshCondition(); - let { id, goodId, refreshType, shop, type } = dicShopItem; + let { id, goodId, refreshType, shop, type, createTime = 0 } = dicShopItem; let rec: UserShopType = await UserShopModel.findOneAndUpdate( - { roleId, itemId: id, $or: timeCondition, activityId, shop, type }, + { roleId, itemId: id, $or: timeCondition, activityId, shop, type, createTime }, { $setOnInsert: { roleName, code, goodId, refreshType }, $inc: { count: inc } }, { new: true, upsert: true } ).lean(); diff --git a/shared/db/UserShopType.ts b/shared/db/UserShopType.ts new file mode 100644 index 000000000..a504c3cc8 --- /dev/null +++ b/shared/db/UserShopType.ts @@ -0,0 +1,43 @@ +import BaseModel from './BaseModel'; +import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose'; +import { nowSeconds } from '../pubUtils/timeUtil'; + +/** + * 玩家购买商店记录表,每个商品一条,每次刷新新建一条 +**/ +@modelOptions({ schemaOptions: { id: false } }) +@index({ roleId: 1, shop: 1, type: 1 }) + +export default class UserShopType extends BaseModel { + @prop({ required: true }) + roleId: string; // 玩家id + + @prop({ required: true }) + shop: number; // 商店id + + @prop({ required: true }) + type: number; // 商店页签id + + @prop({ required: true }) + readTime: number; + + public static async findByRoleId(roleId: string) { + let rec: UserShopTypeType[] = await UserShopTypeModel.find({ roleId }).lean(); + return rec; + } + + public static async findByType(roleId: string, shop: number, type: number) { + let rec: UserShopTypeType = await UserShopTypeModel.findOne({ roleId, shop, type }).lean(); + return rec; + } + + public static async read(roleId: string, shop: number, type: number) { + let rec: UserShopTypeType[] = await UserShopTypeModel.findOneAndUpdate({ roleId, shop, type }, { $set: {readTime: nowSeconds()} }, { new: true, upsert: true }).lean(); + return rec; + } +} + +export const UserShopTypeModel = getModelForClass(UserShopType); + +export interface UserShopTypeType extends Pick, keyof UserShopType> { } +export type UserShopTypeParam = Partial; diff --git a/shared/domain/roleField/shop.ts b/shared/domain/roleField/shop.ts index bfed5f0f7..2980598d6 100644 --- a/shared/domain/roleField/shop.ts +++ b/shared/domain/roleField/shop.ts @@ -1,6 +1,8 @@ import { SHOP_REFRESH_TYPE } from "../../consts"; import { ActivityModelType } from "../../db/Activity"; import { UserShopType } from "../../db/UserShop"; +import { UserShopTypeType } from "../../db/UserShopType"; +import { nowSeconds } from "../../pubUtils/timeUtil"; import { ActivityBase } from "../activityField/activityField"; interface ShopInDb { @@ -53,7 +55,13 @@ export class ShopData extends ActivityBase { public findByItemId(itemId: number) { let item = this.list.find(cur => cur.id == itemId); if(!item) return null; - return {...item, shop: this.shop, type: this.type}; + return {...item, shop: this.shop, type: this.type}; + } + + public findByProductID(productID: string) { + let item = this.list.find(cur => cur.productID == productID); + if(!item) return null; + return {...item, shop: this.shop, type: this.type}; } } @@ -94,8 +102,20 @@ export class ShopDicData { this.beginTime = obj.beginTime; this.endTime = obj.endTime; } + + public setReadRecord(record: UserShopTypeType) { + let now = nowSeconds(); + if(this.beginTime <= now && this.endTime >= now) { + let readTime = record?.readTime||0; + if(this.createTime > readTime) this.isNew = true; + } + } } +export interface ShopDicExtendData extends ShopDicData { + shop: number; + type: number; +} export class ShopReturnData { activityId: number = 0; @@ -112,14 +132,26 @@ export class ShopReturnData { public setDicByActivity(activityData: ShopData) { if(!activityData || activityData.shop != this.shop || activityData.type != this.type) return; this.activityId = activityData.activityId; - this.dic.push(...activityData.list) + for(let obj of activityData.list) { + let newDic = new ShopDicData(obj); + this.dic.push(newDic); + } } - public setUserRecords(record: UserShopType) { + public addUserRecords(record: UserShopType) { if(!record || record.shop != this.shop || record.type != this.type) return; + let dic = this.dic.find(cur => cur.id == record.itemId); + console.log('######### addUserRecords', dic?.createTime, record?.createTime) + if(!dic || (dic.createTime && dic.createTime != record.createTime)) return; let recordResult = new ShopReturnRecordData(record); if(recordResult && recordResult.shopItemId) this.records.push(recordResult) } + + public setReadRecord(record: UserShopTypeType) { + for(let obj of this.dic) { + obj.setReadRecord(record); + } + } } export class ShopReturnRecordData { diff --git a/shared/resource/jsons/dic_zyz_rmb.json b/shared/resource/jsons/dic_zyz_rmb.json index 507e4c9d2..687a33986 100644 --- a/shared/resource/jsons/dic_zyz_rmb.json +++ b/shared/resource/jsons/dic_zyz_rmb.json @@ -1041,5 +1041,12 @@ "price": 98, "message": "每周天外陨金礼包", "gameCoin": 1 + }, + { + "productID": "com.bantu.sgzzyz.yb61", + "type": 44, + "price": 98, + "message": "商店", + "gameCoin": 1 } ] \ No newline at end of file diff --git a/shared/resource/jsons/dic_zyz_shop.json b/shared/resource/jsons/dic_zyz_shop.json index 4b106d84f..9ea883e94 100644 --- a/shared/resource/jsons/dic_zyz_shop.json +++ b/shared/resource/jsons/dic_zyz_shop.json @@ -11,7 +11,7 @@ "purchaseLimit": 6, "refreshType": 1, "money": 31002, - "price": "1&0|3&50", + "price": "1&0|3&50|5&100", "chosen": 1, "indirectId": 0, "vipPurchaseLimit": 4 @@ -45,7 +45,7 @@ "purchaseLimit": 8, "refreshType": 2, "money": 31002, - "price": 1000, + "price": "1&1000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -62,7 +62,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 31002, - "price": 300, + "price": "1&300", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -79,7 +79,7 @@ "purchaseLimit": 50, "refreshType": 2, "money": 31002, - "price": 300, + "price": "1&300", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -96,7 +96,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 31002, - "price": 400, + "price": "1&400", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -113,7 +113,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 31002, - "price": 250, + "price": "1&250", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -130,7 +130,7 @@ "purchaseLimit": 1000, "refreshType": 1, "money": 31002, - "price": 200, + "price": "1&200", "chosen": 1, "indirectId": 1, "vipPurchaseLimit": 0 @@ -147,7 +147,7 @@ "purchaseLimit": 1000, "refreshType": 1, "money": 31002, - "price": 500, + "price": "1&500", "chosen": 1, "indirectId": 2, "vipPurchaseLimit": 0 @@ -164,7 +164,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 31002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -181,7 +181,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 31002, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -198,7 +198,7 @@ "purchaseLimit": 20, "refreshType": 1, "money": 40005, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -215,7 +215,7 @@ "purchaseLimit": 20, "refreshType": 1, "money": 40005, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -232,7 +232,7 @@ "purchaseLimit": 20, "refreshType": 1, "money": 40005, - "price": 1200, + "price": "1&1200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -249,7 +249,7 @@ "purchaseLimit": 20, "refreshType": 1, "money": 40005, - "price": 2400, + "price": "1&2400", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -266,7 +266,7 @@ "purchaseLimit": 20, "refreshType": 1, "money": 40005, - "price": 10000, + "price": "1&10000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -283,7 +283,7 @@ "purchaseLimit": 1000, "refreshType": 1, "money": 40005, - "price": 30, + "price": "1&30", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -300,7 +300,7 @@ "purchaseLimit": 100, "refreshType": 1, "money": 40005, - "price": 25, + "price": "1&25", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -317,7 +317,7 @@ "purchaseLimit": 140, "refreshType": 1, "money": 40005, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -334,7 +334,7 @@ "purchaseLimit": 16, "refreshType": 1, "money": 40005, - "price": 1500, + "price": "1&1500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -351,7 +351,7 @@ "purchaseLimit": 20, "refreshType": 2, "money": 40001, - "price": 100, + "price": "1&100", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -368,7 +368,7 @@ "purchaseLimit": 2, "refreshType": 2, "money": 40001, - "price": 400, + "price": "1&400", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -385,7 +385,7 @@ "purchaseLimit": 6, "refreshType": 1, "money": 40001, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -402,7 +402,7 @@ "purchaseLimit": 6, "refreshType": 1, "money": 40001, - "price": 20, + "price": "1&20", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -419,7 +419,7 @@ "purchaseLimit": 4, "refreshType": 1, "money": 40001, - "price": 30, + "price": "1&30", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -436,7 +436,7 @@ "purchaseLimit": 2, "refreshType": 1, "money": 40001, - "price": 50, + "price": "1&50", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -453,7 +453,7 @@ "purchaseLimit": 30, "refreshType": 3, "money": 40004, - "price": 150, + "price": "1&150", "chosen": 1, "indirectId": 0, "vipPurchaseLimit": 0 @@ -470,7 +470,7 @@ "purchaseLimit": 2, "refreshType": 2, "money": 40004, - "price": 400, + "price": "1&400", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -487,7 +487,7 @@ "purchaseLimit": 80, "refreshType": 2, "money": 40004, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -504,7 +504,7 @@ "purchaseLimit": 20, "refreshType": 2, "money": 40004, - "price": 45, + "price": "1&45", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -521,7 +521,7 @@ "purchaseLimit": 10, "refreshType": 2, "money": 40004, - "price": 60, + "price": "1&60", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -538,7 +538,7 @@ "purchaseLimit": 10, "refreshType": 2, "money": 40004, - "price": 75, + "price": "1&75", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -555,7 +555,7 @@ "purchaseLimit": 10, "refreshType": 2, "money": 40004, - "price": 90, + "price": "1&90", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -572,7 +572,7 @@ "purchaseLimit": 10, "refreshType": 2, "money": 40004, - "price": 120, + "price": "1&120", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -589,7 +589,7 @@ "purchaseLimit": 20, "refreshType": 2, "money": 40004, - "price": 100, + "price": "1&100", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -606,7 +606,7 @@ "purchaseLimit": 1, "refreshType": 4, "money": 40014, - "price": 30, + "price": "1&30", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -623,7 +623,7 @@ "purchaseLimit": 1, "refreshType": 4, "money": 40014, - "price": 30, + "price": "1&30", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -640,7 +640,7 @@ "purchaseLimit": 1, "refreshType": 4, "money": 40006, - "price": 30, + "price": "1&30", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -657,7 +657,7 @@ "purchaseLimit": 1, "refreshType": 4, "money": 40006, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -674,7 +674,7 @@ "purchaseLimit": 1, "refreshType": 2, "money": 40002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -691,7 +691,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 400, + "price": "1&400", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -708,7 +708,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 250, + "price": "1&250", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -725,7 +725,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -742,7 +742,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40002, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -759,7 +759,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -776,7 +776,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -793,7 +793,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -810,7 +810,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 200, + "price": "1&200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -827,7 +827,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -844,7 +844,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -861,7 +861,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -878,7 +878,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 500, + "price": "1&500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -895,7 +895,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 1000, + "price": "1&1000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -912,7 +912,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 1000, + "price": "1&1000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -929,7 +929,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 1000, + "price": "1&1000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -946,7 +946,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 1000, + "price": "1&1000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -963,7 +963,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 2500, + "price": "1&2500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -980,7 +980,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 2500, + "price": "1&2500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -997,7 +997,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 2500, + "price": "1&2500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1014,7 +1014,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 2500, + "price": "1&2500", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1031,7 +1031,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 5000, + "price": "1&5000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1048,7 +1048,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 5000, + "price": "1&5000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1065,7 +1065,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 5000, + "price": "1&5000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1082,7 +1082,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 5000, + "price": "1&5000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1099,7 +1099,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 8000, + "price": "1&8000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1116,7 +1116,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 8000, + "price": "1&8000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1133,7 +1133,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 8000, + "price": "1&8000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1150,7 +1150,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 8000, + "price": "1&8000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1167,7 +1167,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 15000, + "price": "1&15000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1184,7 +1184,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 15000, + "price": "1&15000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1201,7 +1201,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 15000, + "price": "1&15000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1218,7 +1218,7 @@ "purchaseLimit": 9999, "refreshType": 2, "money": 40002, - "price": 15000, + "price": "1&15000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1235,7 +1235,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40007, - "price": 100, + "price": "1&100", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1252,7 +1252,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40007, - "price": 250, + "price": "1&250", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1269,7 +1269,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40007, - "price": 600, + "price": "1&600", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1286,7 +1286,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40007, - "price": 1200, + "price": "1&1200", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1303,7 +1303,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40007, - "price": 5000, + "price": "1&5000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1320,7 +1320,7 @@ "purchaseLimit": 1200, "refreshType": 1, "money": 40007, - "price": 20, + "price": "1&20", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1337,7 +1337,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1354,7 +1354,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1371,7 +1371,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1388,7 +1388,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 10, + "price": "1&10", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1405,7 +1405,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 1000, + "price": "1&1000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1422,7 +1422,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 2000, + "price": "1&2000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1439,7 +1439,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 4000, + "price": "1&4000", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0 @@ -1456,7 +1456,7 @@ "purchaseLimit": 9999, "refreshType": 1, "money": 40011, - "price": 800, + "price": "1&800", "chosen": 0, "indirectId": 0, "vipPurchaseLimit": 0