NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

purchase.py (4923B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\characterskills\purchase.py
      2 import abc
      3 
      4 def purchase_skills(context, skill_type_ids):
      5     skill_type_ids = list(skill_type_ids)
      6     context.validate(skill_type_ids)
      7     skills_to_inject = []
      8     try:
      9         for skill_type_id in skill_type_ids:
     10             context.pay_for_skill(skill_type_id)
     11             skills_to_inject.append(skill_type_id)
     12 
     13     finally:
     14         if skills_to_inject:
     15             context.inject_skills(skills_to_inject)
     16 
     17     return skills_to_inject
     18 
     19 
     20 class SkillPurchaseContext(object):
     21     __metaclass__ = abc.ABCMeta
     22 
     23     @abc.abstractmethod
     24     def get_validator(self):
     25         pass
     26 
     27     @abc.abstractmethod
     28     def inject_skills(self, skill_type_ids):
     29         pass
     30 
     31     @abc.abstractmethod
     32     def pay_for_skill(self, skill_type_id):
     33         pass
     34 
     35     def validate(self, skill_type_ids):
     36         validator = self.get_validator()
     37         validator.validate(skill_type_ids)
     38 
     39 
     40 class SkillPurchaseValidator(object):
     41     __metaclass__ = abc.ABCMeta
     42 
     43     @abc.abstractmethod
     44     def get_account_balance(self):
     45         pass
     46 
     47     @abc.abstractmethod
     48     def get_skill_price(self, skill_type_id):
     49         pass
     50 
     51     @abc.abstractmethod
     52     def is_skill(self, type_id):
     53         pass
     54 
     55     @abc.abstractmethod
     56     def is_skill_available_for_purchase(self, skill_type_id):
     57         pass
     58 
     59     @abc.abstractmethod
     60     def is_skill_injected(self, skill_type_id):
     61         pass
     62 
     63     def validate(self, skill_type_ids):
     64         self._check_no_duplicate_skills(skill_type_ids)
     65         self._check_all_type_ids_are_skills(skill_type_ids)
     66         self._check_all_skills_available_for_purchase(skill_type_ids)
     67         self._check_no_skills_already_injected(skill_type_ids)
     68         self._check_balance_can_cover_purchase_cost(skill_type_ids)
     69 
     70     def _check_no_duplicate_skills(self, skill_type_ids):
     71         duplicates = find_duplicates(skill_type_ids)
     72         if duplicates:
     73             raise DuplicateSkillValueError(duplicates)
     74 
     75     def _check_all_type_ids_are_skills(self, type_ids):
     76         for type_id in type_ids:
     77             if not self.is_skill(type_id):
     78                 raise TypeIsNotSkillError(type_id)
     79 
     80     def _check_no_skills_already_injected(self, skill_type_ids):
     81         for skill_type_id in skill_type_ids:
     82             if self.is_skill_injected(skill_type_id):
     83                 raise SkillAlreadyInjectedError(skill_type_id)
     84 
     85     def _check_all_skills_available_for_purchase(self, skill_type_ids):
     86         for skill_type_id in skill_type_ids:
     87             if not self.is_skill_available_for_purchase(skill_type_id):
     88                 raise SkillUnavailableForPurchaseError(skill_type_id)
     89 
     90     def _check_balance_can_cover_purchase_cost(self, skill_type_ids):
     91         total_cost = sum(map(self.get_skill_price, skill_type_ids))
     92         balance = self.get_account_balance()
     93         if total_cost > balance:
     94             raise NotEnoughMoneyError(total_cost, balance)
     95 
     96 
     97 def find_duplicates(seq):
     98     seen = set()
     99     duplicates = set()
    100     for item in seq:
    101         if item in seen:
    102             duplicates.add(item)
    103         else:
    104             seen.add(item)
    105 
    106     return duplicates
    107 
    108 
    109 class SkillPurchaseError(Exception):
    110     pass
    111 
    112 
    113 class SkillAlreadyInjectedError(SkillPurchaseError):
    114     MESSAGE_TEMPLATE = 'The skill (type ID {}) is already injected'
    115 
    116     def __init__(self, type_id):
    117         message = self.MESSAGE_TEMPLATE.format(type_id)
    118         super(SkillAlreadyInjectedError, self).__init__(message)
    119         self.type_id = type_id
    120 
    121 
    122 class SkillUnavailableForPurchaseError(SkillPurchaseError):
    123     MESSAGE_TEMPLATE = 'The skill (type ID {}) is not available for purchase'
    124 
    125     def __init__(self, type_id):
    126         message = self.MESSAGE_TEMPLATE.format(type_id)
    127         super(SkillUnavailableForPurchaseError, self).__init__(message)
    128         self.type_id = type_id
    129 
    130 
    131 class TypeIsNotSkillError(SkillPurchaseError):
    132     MESSAGE_TEMPLATE = 'Type ID {} is not a skill'
    133 
    134     def __init__(self, type_id):
    135         message = self.MESSAGE_TEMPLATE.format(type_id)
    136         super(TypeIsNotSkillError, self).__init__(message)
    137         self.type_id = type_id
    138 
    139 
    140 class NotEnoughMoneyError(SkillPurchaseError):
    141     MESSAGE_TEMPLATE = 'You need {} to complete this purchase but only have {}'
    142 
    143     def __init__(self, required_amount, current_balance):
    144         message = self.MESSAGE_TEMPLATE.format(required_amount, current_balance)
    145         super(NotEnoughMoneyError, self).__init__(message)
    146         self.required_amount = required_amount
    147         self.current_balance = current_balance
    148 
    149 
    150 class DuplicateSkillValueError(SkillPurchaseError):
    151     MESSAGE_TEMPLATE = 'The following skill type IDs occurr more than once in the input: {}'
    152 
    153     def __init__(self, type_ids):
    154         message = self.MESSAGE_TEMPLATE.format(', '.join(map(str, type_ids)))
    155         super(DuplicateSkillValueError, self).__init__(message)
    156         self.type_ids = type_ids