Esempio n. 1
0
    def __init__(self, char_id):
        self.char_id = char_id

        try:
            self.mc_limit = MongoStoreCharLimit.objects.get(id=self.char_id)
        except DoesNotExist:
            self.mc_limit = MongoStoreCharLimit(id=self.char_id)
Esempio n. 2
0
    def __init__(self, char_id):
        self.char_id = char_id

        try:
            self.mc_limit = MongoStoreCharLimit.objects.get(id=self.char_id)
        except DoesNotExist:
            self.mc_limit = MongoStoreCharLimit(id=self.char_id)
            self.mc_limit.limits = {}
            self.mc_limit.save()
Esempio n. 3
0
class Store(object):
    def __init__(self, char_id):
        self.char_id = char_id

        try:
            self.mc_limit = MongoStoreCharLimit.objects.get(id=self.char_id)
        except DoesNotExist:
            self.mc_limit = MongoStoreCharLimit(id=self.char_id)
            self.mc_limit.limits = {}
            self.mc_limit.save()

    def get_new_store(self):
        try:
            data = api_store_get({})
        except APIFailure:
            raise SanguoException(
                errormsg.SERVER_FAULT,
                self.char_id,
                "Store",
                "APIFailure. api_store_get"
            )

        store = data['data']['store']
        return {int(k): v for k, v in store.iteritems()}


    def buy(self, _id, amount):
        if amount < 1:
            raise SanguoException(
                errormsg.STORE_INVALID_BUY_AMOUNT,
                self.char_id,
                "Store Buy",
                "invalid amount {0}".format(amount)
            )

        store = self.get_new_store()

        try:
            this_goods = store[_id]
        except KeyError:
            raise SanguoException(
                errormsg.STORE_GOODS_NOT_EXIST,
                self.char_id,
                "Store Buy",
                "{0} not exist".format(_id)
            )

        char = Char(self.char_id)
        mc = char.mc

        # check vip
        if this_goods['vip_condition'] > mc.vip:
            raise SanguoException(
                errormsg.STORE_GOODS_VIP_CONDITION,
                self.char_id,
                "Store Buy",
                "{0} has vip condition {1}. greater than char vip {2}".format(_id, this_goods['vip_condition'], mc.vip)
            )

        # check level
        if this_goods['level_condition'] > mc.level:
            raise SanguoException(
                errormsg.STORE_GOODS_LEVEL_CONDITION,
                self.char_id,
                "Store Buy",
                "{0} has level condition {1}. greater than char level {2}".format(_id, this_goods['level_condition'], mc.level)
            )

        # check total amount
        if this_goods['has_total_amount']:
            if this_goods['total_amount_run_time'] < amount:
                raise SanguoException(
                    errormsg.STORE_GOODS_AMOUNT_NOT_ENOUGH,
                    self.char_id,
                    "Store Buy",
                    "{0} amount not enough. remained {1}, buy amount {2}".format(_id, this_goods['total_amount_run_time'], amount)
                )

        # check limit
        if this_goods['has_limit_amount']:
            remained_amount = self.get_limit_remained_amount(_id, this_goods['limit_amount'])
            if remained_amount < amount:
                raise SanguoException(
                    errormsg.STORE_GOODS_CHAR_LIMIT,
                    self.char_id,
                    "Store Buy",
                    "{0} reach limit {1}".format(_id, this_goods['limit_amount'])
                )

        # check gold or sycee
        wealth_needs = this_goods['sell_price'] * amount

        if this_goods['sell_type'] == 1:
            resource_need = {'gold': -wealth_needs}
        else:
            resource_need = {'sycee': -wealth_needs}

        resource = Resource(self.char_id, "Store Buy", 'buy {0}, amount: {1}'.format(_id, amount))
        with resource.check(**resource_need):
            # 本地server检查完毕,然后通过API通知HUB购买。
            # 对于有total amount限制的物品,HUB可能返回错误
            data = {
                'char_id': self.char_id,
                'goods_id': _id,
                'goods_amount': amount,
            }

            try:
                res = api_store_buy(data)
            except APIFailure:
                raise SanguoException(
                    errormsg.SERVER_FAULT,
                    self.char_id,
                    "Store",
                    "APIFailure. api_store_buy"
                )

            if res['ret'] != 0:
                raise SanguoException(
                    res['ret'],
                    self.char_id,
                    "Store Buy",
                    "api failure"
                )

            # ALL OK
            # 开始操作
            if this_goods['has_limit_amount']:
                # 有每人限量的记录到每人的购买记录中
                self.mc_limit.limits[str(_id)] = self.mc_limit.limits.get(str(_id), 0) + amount
                self.mc_limit.save()

            # 更新store
            if this_goods['has_total_amount']:
                store[_id]['total_amount_run_time'] = res['data']['total_amount_run_time']

            # 给东西
            resource_add = {}
            if this_goods['item_tp'] == 1:
                resource_add['heros'] = [(this_goods['item_id'], amount)]
            elif this_goods['item_tp'] == 2:
                resource_add['equipments'] = [(this_goods['item_id'], 1, amount)]
            elif this_goods['item_tp'] == 3:
                resource_add['gems'] = [(this_goods['item_id'], amount)]
            else:
                resource_add['stuffs'] = [(this_goods['item_id'], amount)]

            resource.add(**resource_add)

        self.send_notify(store=store)



    def get_limit_already_amount(self, gid):
        return self.mc_limit.limits.get(str(gid), 0)

    def get_limit_remained_amount(self, gid, limit_amount):
        already_amount = self.get_limit_already_amount(gid)
        remained = limit_amount - already_amount
        if remained < 0:
            remained = 0
        return remained


    def fill_up_notify_msg(self, store=None):
        c = Char(self.char_id)
        mc = c.mc

        if not store:
            store = self.get_new_store()

        msg = StoreNotify()
        msg.session = ""

        for k, v in store.items():
            if v['level_condition'] > mc.level:
                store.pop(k)
                continue

            g = msg.goods.add()
            g.id = v['id']
            g.tag = v['tag']
            g.item_tp = v['item_tp']
            g.item_id = v['item_id']
            g.sell_tp = v['sell_type']
            g.original_price = v['original_price']
            g.sell_price = v['sell_price']

            if v['has_total_amount']:
                g.conditions.append(1)
                g.total_condition.amount = v['total_amount_run_time']

            if v['has_limit_amount']:
                g.conditions.append(2)
                g.limit_condition.amount = self.get_limit_remained_amount(v['id'], v['limit_amount'])

            if v['vip_condition'] > 0:
                g.conditions.append(3)
                g.vip_condition.vip = v['vip_condition']
                g.vip_condition.can_buy = mc.vip >= v['vip_condition']

        return msg


    def send_notify(self, store=None):
        msg = self.fill_up_notify_msg(store=store)
        publish_to_char(self.char_id, pack_msg(msg))
Esempio n. 4
0
class Store(object):
    def __init__(self, char_id):
        self.char_id = char_id

        try:
            self.mc_limit = MongoStoreCharLimit.objects.get(id=self.char_id)
        except DoesNotExist:
            self.mc_limit = MongoStoreCharLimit(id=self.char_id)

    def get_new_store(self):
        try:
            data = api_store_get({})
        except APIFailure:
            raise SanguoException(errormsg.SERVER_FAULT, self.char_id, "Store",
                                  "APIFailure. api_store_get")

        store = data['data']['store']
        return {int(k): v for k, v in store.iteritems()}

    def buy(self, _id, amount):
        store = self.get_new_store()

        try:
            this_goods = store[_id]
        except KeyError:
            raise SanguoException(errormsg.STORE_GOODS_NOT_EXIST, self.char_id,
                                  "Store Buy", "{0} not exist".format(_id))

        char = Char(self.char_id)
        mc = char.mc

        # TODO check vip
        # if this_goods['vip_condition'] > mc.vip:
        #     raise InvalidOperate("Store Buy. Char {0} Try to buy {1}. But vip test not passed. {2} < {3}".format(
        #         self.char_id, _id, mc.vip, this_goods['vip_condition']
        #     ))

        # check level
        if this_goods['level_condition'] > mc.level:
            raise SanguoException(
                errormsg.STORE_GOODS_LEVEL_CONDITION, self.char_id,
                "Store Buy",
                "{0} has level condition {1}. greater than char level {2}".
                format(_id, this_goods['level_condition'], mc.level))

        # check total amount
        if this_goods['has_total_amount']:
            if this_goods['total_amount_run_time'] < amount:
                raise SanguoException(
                    errormsg.STORE_GOODS_AMOUNT_NOT_ENOUGH, self.char_id,
                    "Store Buy",
                    "{0} amount not enough. remained {1}, buy amount {2}".
                    format(_id, this_goods['total_amount_run_time'], amount))

        # check limit
        if this_goods['has_limit_amount']:
            remained_amount = self.get_limit_remained_amount(
                _id, this_goods['limit_amount'])
            if remained_amount < amount:
                raise SanguoException(
                    errormsg.STORE_GOODS_CHAR_LIMIT, self.char_id, "Store Buy",
                    "{0} reach limit {1}".format(_id,
                                                 this_goods['limit_amount']))

        # check gold or sycee
        wealth_needs = this_goods['sell_price'] * amount

        resource = Resource(self.char_id, "Store Buy",
                            'buy {0}, amount: {1}'.format(_id, amount))
        if this_goods['sell_type'] == 1:
            resource_need = {'gold': -wealth_needs}
        else:
            resource_need = {'sycee': -wealth_needs}

        if this_goods['sell_type'] == 1:
            if mc.gold < wealth_needs:
                raise SanguoException(
                    errormsg.GOLD_NOT_ENOUGH,
                    self.char_id,
                    "Store Buy",
                    "gold not enough",
                )
        else:
            if mc.sycee < wealth_needs:
                raise SanguoException(errormsg.SYCEE_NOT_ENOUGH, self.char_id,
                                      "Store Buy", "sycee not enough")

        with resource.check(**resource_need):
            # 本地server检查完毕,然后通过API通知HUB购买。
            # 对于有total amount限制的物品,HUB可能返回错误
            data = {
                'char_id': self.char_id,
                'goods_id': _id,
                'goods_amount': amount,
            }

            try:
                res = api_store_buy(data)
            except APIFailure:
                raise SanguoException(errormsg.SERVER_FAULT, self.char_id,
                                      "Store", "APIFailure. api_store_buy")

            if res['ret'] != 0:
                raise SanguoException(res['ret'], self.char_id, "Store Buy",
                                      "api failure")

            # ALL OK
            # 开始操作
            if this_goods['has_limit_amount']:
                # 有每人限量的记录到每人的购买记录中
                self.mc_limit.limits[str(_id)] = self.mc_limit.limits.get(
                    str(_id), 0) + amount
                self.mc_limit.save()

            # 更新store
            if this_goods['has_total_amount']:
                store[_id]['total_amount_run_time'] = res['data'][
                    'total_amount_run_time']

            # 给东西
            resource_add = {}
            if this_goods['item_tp'] == 1:
                resource_add['heros'] = [(this_goods['item_id'], amount)]
            elif this_goods['item_tp'] == 2:
                resource_add['equipments'] = [this_goods['item_id']] * amount
            elif this_goods['item_tp'] == 3:
                resource_add['gems'] = [(this_goods['item_id'], amount)]
            else:
                resource_add['stuffs'] = [(this_goods['item_id'], amount)]

            resource.add(**resource_add)

        self.send_notify(store=store)

    def get_limit_already_amount(self, gid):
        return self.mc_limit.limits.get(str(gid), 0)

    def get_limit_remained_amount(self, gid, limit_amount):
        already_amount = self.get_limit_already_amount(gid)
        remained = limit_amount - already_amount
        if remained < 0:
            remained = 0
        return remained

    def fill_up_notify_msg(self, store=None):
        c = Char(self.char_id)
        mc = c.mc

        if not store:
            store = self.get_new_store()

        msg = StoreNotify()
        msg.session = ""

        for k, v in store.items():
            if v['level_condition'] > mc.level:
                store.pop(k)
                continue

            g = msg.goods.add()
            g.id = v['id']
            g.tag = v['tag']
            g.item_tp = v['item_tp']
            g.item_id = v['item_id']
            g.sell_tp = v['sell_type']
            g.original_price = v['original_price']
            g.sell_price = v['sell_price']

            if v['has_total_amount']:
                g.conditions.append(1)
                g.total_condition.amount = v['total_amount_run_time']

            if v['has_limit_amount']:
                g.conditions.append(2)
                g.limit_condition.amount = self.get_limit_remained_amount(
                    v['id'], v['limit_amount'])

            if v['vip_condition'] > 0:
                g.conditions.append(3)
                g.vip_condition.vip = v['vip_condition']
                # TODO
                # g.vip_condition.can_buy = mc.vip >= v['vip_condition']
                g.vip_condition.can_buy = False

        return msg

    def send_notify(self, store=None):
        msg = self.fill_up_notify_msg(store=store)
        publish_to_char(self.char_id, pack_msg(msg))