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

achievement_entry.py (17618B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\achievement_system\client\ui\controller\achievement_entry.py
      2 from __future__ import division
      3 import datetime
      4 import eveicon
      5 import logging
      6 from achievement_system.client.api.error import AchievementAlreadyTrackedError, TrackedAchievementLimitReachedError, TrackedAchievementNotFoundError, AlreadyPinnedError, PinLimitReachedError, PinNotFoundError, DefinitionNotFoundError
      7 from achievement_system.client.api.repository import get_repository
      8 from achievement_system.client.ui.window.const import get_content_tag_icon, EXCLUDED_CONTRIB_METHOD_PARAM_KEYS, HISTORIC_COMPLETE_COLOR, HISTORIC_INCOMPLETE_COLOR
      9 from achievement_system.client.ui.util import get_controller_for_configured_parameter
     10 from achievement_system.common.const import LOGGER_NAME
     11 from carbon.common.script.util.format import FmtAmt
     12 from achievement_system.client.model.definition.achievement.entry import AchievementDefinitionEntry
     13 from achievement_system.client.model.definition.contribution_method.progress_config import ProgressType
     14 from eve.client.script.ui import eveColor, eveThemeColor
     15 from localization import GetByMessageID, GetByLabel
     16 from mathext import clamp
     17 from player_messaging.client.ui_message import message_player
     18 from signals import Signal
     19 logger = logging.getLogger(LOGGER_NAME)
     20 
     21 class AchievementEntryController(object):
     22 
     23     def __init__(self, achievement_entry):
     24         self.achievement_entry = achievement_entry
     25         self._selected_milestone_index = min(self.completed_milestones, self.total_milestones - 1)
     26         self.on_selected_milestone_changed = Signal('on_selected_milestone_changed')
     27 
     28     @property
     29     def state(self):
     30         return get_repository().get_achievement_state(achievement_identifier=self.achievement_entry.identifier)
     31 
     32     @property
     33     def id(self):
     34         return self.achievement_entry.identifier.uuid
     35 
     36     @property
     37     def icon(self):
     38         if self.achievement_entry.attributes.icon_id:
     39             return eveicon.get(self.achievement_entry.attributes.icon_id)
     40         else:
     41             return eveicon.get(self.contribution_attributes.icon_id)
     42 
     43     @property
     44     def content_tag_icon(self):
     45         return get_content_tag_icon(self.achievement_entry.attributes.tags)
     46 
     47     @property
     48     def name(self):
     49         return self.achievement_entry.attributes.name_message.get_localized_text()
     50 
     51     @property
     52     def description(self):
     53         amount = self.target_for_milestone_index(self.current_milestone_index)
     54         return GetByMessageID(self.achievement_entry.attributes.description_message.identifier, amount=amount)
     55 
     56     @property
     57     def description_for_selected_milestone(self):
     58         amount = self.target_for_milestone_index(self.selected_milestone_index)
     59         return GetByMessageID(self.achievement_entry.attributes.description_message.identifier, amount=amount)
     60 
     61     @property
     62     def flavor_text(self):
     63         message = self.achievement_entry.attributes.flavor_text_message
     64         if message is None:
     65             return
     66         localized_text = message.get_localized_text()
     67         if len(localized_text) == 0:
     68             return
     69         return localized_text
     70 
     71     @property
     72     def total_milestones(self):
     73         return len(self.achievement_entry.attributes.milestones)
     74 
     75     @property
     76     def completed_milestones(self):
     77         if self.state is None:
     78             return 0
     79         return len(self.state.reached_milestones)
     80 
     81     @property
     82     def selected_milestone_index(self):
     83         return self._selected_milestone_index
     84 
     85     @property
     86     def current_milestone_index(self):
     87         return min(self.completed_milestones, self.total_milestones - 1)
     88 
     89     @property
     90     def progress(self):
     91         max_progress = self.achievement_entry.attributes.milestones[-1].attributes.cumulated_target
     92         if self.state is None:
     93             return 0
     94         if self.progress_type is ProgressType.CUMULATIVE:
     95             progress = self.state.progress if self.state.progress else 0
     96         elif self.progress_type in [ProgressType.CHECKLIST, ProgressType.SET]:
     97             progress = self.state.checklist.get_progress_value() if self.state.checklist else 0
     98         else:
     99             progress = 0
    100         return min(progress, max_progress)
    101 
    102     @property
    103     def is_checklist(self):
    104         return self.progress_type == ProgressType.CHECKLIST
    105 
    106     @property
    107     def is_historic(self):
    108         return self.achievement_entry.attributes.is_historic
    109 
    110     def is_checklist_item_done(self, item_value):
    111         if self.progress_type != ProgressType.CHECKLIST:
    112             logger.error("trying to evaluate a checklist item %s for an non-checklist achievement, this isn't normal", item_value)
    113             return False
    114         if self.state.checklist is None:
    115             return False
    116         for value_type, values in self.state.checklist.values.items():
    117             if str(item_value) in values:
    118                 return True
    119 
    120         return False
    121 
    122     def target_for_milestone_index(self, index):
    123         return self.achievement_entry.attributes.milestones[clamp(index, 0, len(self.achievement_entry.attributes.milestones) - 1)].attributes.cumulated_target
    124 
    125     @property
    126     def progress_score_text_for_current_milestone(self):
    127         return self.progress_score_text_for_milestone(self.current_milestone_index)
    128 
    129     @property
    130     def progress_score_text_for_selected_milestone(self):
    131         return self.progress_score_text_for_milestone(self.selected_milestone_index)
    132 
    133     def progress_score_text_for_milestone(self, milestone_index):
    134         current_value = self.progress
    135         target_value = self.target_for_milestone_index(milestone_index)
    136         if current_value > target_value:
    137             current_value = target_value
    138         if target_value <= 100000:
    139             current_text = FmtAmt(current_value)
    140             target_text = FmtAmt(target_value)
    141         else:
    142             current_text = FmtAmt(current_value, fmt='sn')
    143             target_text = FmtAmt(target_value, fmt='sn')
    144         return '%s/%s' % (current_text, target_text)
    145 
    146     @property
    147     def progress_score_hint_for_current_milestone(self):
    148         return self.progress_score_hint_for_milestone(self.current_milestone_index)
    149 
    150     @property
    151     def progress_score_hint_for_selected_milestone(self):
    152         return self.progress_score_hint_for_milestone(self.selected_milestone_index)
    153 
    154     def progress_score_hint_for_milestone(self, milestone_index):
    155         current_value = self.progress
    156         target_value = self.target_for_milestone_index(milestone_index)
    157         if current_value > target_value:
    158             current_value = target_value
    159         return '%s/%s' % (FmtAmt(current_value), FmtAmt(target_value))
    160 
    161     @property
    162     def selected_milestone_target(self):
    163         return self.target_for_milestone_index(self.selected_milestone_index)
    164 
    165     @property
    166     def percent_progress_towards_selected_milestone(self):
    167         return self.progress_ratio_towards_milestone(self.selected_milestone_index)
    168 
    169     @property
    170     def percent_progress_towards_current_milestone(self):
    171         return self.progress_ratio_towards_milestone(self.current_milestone_index)
    172 
    173     def progress_ratio_towards_milestone(self, milestone_index):
    174         progress = self._get_percent_progress_towards_milestone(milestone_index)
    175         if 0 < progress < 0.01:
    176             return 0.01
    177         if 0.99 < progress < 1.0:
    178             return 0.99
    179         return progress
    180 
    181     def rewards_for_milestone_index(self, index):
    182         return self.achievement_entry.attributes.milestones[clamp(index, 0, len(self.achievement_entry.attributes.milestones) - 1)].attributes.rewards
    183 
    184     def achievement_score_for_milestone_index(self, index):
    185         return self.achievement_entry.attributes.milestones[index].attributes.category_points
    186 
    187     def set_selected_milestone_index(self, index):
    188         self._selected_milestone_index = clamp(index, 0, self.total_milestones - 1)
    189         self.on_selected_milestone_changed()
    190 
    191     @property
    192     def selected_milestone_id(self):
    193         return self.achievement_entry.attributes.milestones[self.selected_milestone_index].identifier
    194 
    195     @property
    196     def selected_milestone_rewards(self):
    197         return self.rewards_for_milestone_index(self.selected_milestone_index)
    198 
    199     @property
    200     def current_milestone_rewards(self):
    201         return self.rewards_for_milestone_index(self.current_milestone_index)
    202 
    203     @property
    204     def selected_milestone_score(self):
    205         return self.achievement_score_for_milestone_index(self.selected_milestone_index)
    206 
    207     @property
    208     def current_milestone_score(self):
    209         return self.achievement_score_for_milestone_index(self.current_milestone_index)
    210 
    211     @property
    212     def is_selected_milestone_completed(self):
    213         return self.completed_milestones > 0 and self.selected_milestone_index < self.completed_milestones
    214 
    215     @property
    216     def is_current_milestone_completed(self):
    217         return self.completed_milestones > 0 and self.current_milestone_index < self.completed_milestones
    218 
    219     @property
    220     def has_multiple_milestones(self):
    221         return self.total_milestones > 1
    222 
    223     @property
    224     def has_flavor_text(self):
    225         return self.flavor_text is not None
    226 
    227     @property
    228     def progress_type(self):
    229         return self.contribution_attributes.progress_config.progress_type
    230 
    231     @property
    232     def contribution_config(self):
    233         return self.achievement_entry.attributes.contribution_method
    234 
    235     @property
    236     def contribution_attributes(self):
    237         contribution_identifier = self.contribution_config.identifier
    238         return get_repository().definitions.get_contribution_method(contribution_identifier)
    239 
    240     @property
    241     def contribution_name(self):
    242         return self.contribution_attributes.name_message.get_localized_text()
    243 
    244     @property
    245     def contribution_description(self):
    246         return self.contribution_attributes.description_message.get_localized_text()
    247 
    248     @property
    249     def contribution_progress_text(self):
    250         return self.contribution_attributes.progress_message.get_localized_text()
    251 
    252     @property
    253     def contribution_icon(self):
    254         contribution_attributes = self.contribution_attributes
    255         if contribution_attributes.icon_id:
    256             return eveicon.get(contribution_attributes.icon_id)
    257         else:
    258             logger.error('Icon not found for contribution method %s in achievement %s', self.contribution_config.identifier, self.achievement_entry.identifier)
    259             return None
    260 
    261     @property
    262     def icon_frame_textures(self):
    263         ach_outer, ach_mask, ach_inner = self.achievement_entry.attributes.get_icon_frame_keys(self.is_completed)
    264         cm_outer, cm_mask, cm_inner = self.contribution_attributes.get_icon_frame_keys(self.is_completed)
    265         outer = ach_outer if ach_outer else cm_outer
    266         mask = ach_mask if ach_mask else cm_mask
    267         inner = ach_inner if ach_inner else cm_inner
    268         if outer is None:
    269             logger.error('achievement %s has no icon outer frame defined', self.achievement_entry.attributes.name_message.get_localized_text())
    270         if mask is None:
    271             logger.error('achievement %s has no icon mask frame defined', self.achievement_entry.attributes.name_message.get_localized_text())
    272         if inner is None:
    273             logger.error('achievement %s has no icon inner frame defined', self.achievement_entry.attributes.name_message.get_localized_text())
    274         return (outer, mask, inner)
    275 
    276     @property
    277     def is_completed(self):
    278         return self.state is not None and not self.state.not_completed
    279 
    280     @property
    281     def progress_bar_color(self):
    282         if self.is_completed:
    283             if not self.is_historic:
    284                 return eveColor.SUCCESS_GREEN
    285             return HISTORIC_COMPLETE_COLOR
    286         elif not self.is_historic:
    287             return eveThemeColor.THEME_ACCENT.rgba
    288         else:
    289             return HISTORIC_INCOMPLETE_COLOR
    290 
    291     @property
    292     def milestone_progress_bar_color(self):
    293         if self.percent_progress_towards_selected_milestone == 1.0:
    294             if not self.is_historic:
    295                 return eveColor.SUCCESS_GREEN
    296             return HISTORIC_COMPLETE_COLOR
    297         return self.progress_bar_color
    298 
    299     @property
    300     def is_pinned(self):
    301         return get_repository().activity.is_pinned(self.achievement_entry.identifier)
    302 
    303     @property
    304     def is_tracked(self):
    305         return get_repository().activity.is_tracked(self.achievement_entry.identifier)
    306 
    307     @property
    308     def is_time_limited(self):
    309         return self.expiration_date is not None
    310 
    311     @property
    312     def is_expired(self):
    313         if not self.is_time_limited:
    314             return False
    315         time_remaining = self.expiration_date - datetime.datetime.now()
    316         return time_remaining < datetime.timedelta(0)
    317 
    318     @property
    319     def expiration_date(self):
    320         return self.achievement_entry.attributes.expiration_date
    321 
    322     @property
    323     def time_remaining(self):
    324         if self.is_expired:
    325             return datetime.timedelta(0)
    326         return self.expiration_date - datetime.datetime.now()
    327 
    328     @property
    329     def has_unclaimed_rewards(self):
    330         unclaimed_rewards = get_repository().get_unclaimed_rewards_for_achievement(achievement_id=self.achievement_entry.identifier)
    331         return unclaimed_rewards is not None
    332 
    333     def toggle_pinned(self):
    334         if self.is_pinned:
    335             try:
    336                 get_repository().activity.unpin_achievement(self.achievement_entry.identifier)
    337             except PinNotFoundError:
    338                 logger.warning('Pin not found for achievement: %s', self.achievement_entry.identifier)
    339 
    340         else:
    341             try:
    342                 get_repository().activity.pin_achievement(self.achievement_entry.identifier)
    343             except AlreadyPinnedError:
    344                 logger.warning('Achievement already pinned: %s', self.achievement_entry.identifier)
    345             except PinLimitReachedError:
    346                 message_player(GetByLabel('UI/Achievements/Error/PinLimitReached'))
    347 
    348     def toggle_tracked(self):
    349         if self.is_tracked:
    350             self.untrack()
    351         else:
    352             self.track()
    353 
    354     def track(self):
    355         try:
    356             get_repository().activity.track_achievement(self.achievement_entry.identifier)
    357         except AchievementAlreadyTrackedError:
    358             logger.warning('Achievement already tracked: %s', self.achievement_entry.identifier)
    359         except TrackedAchievementLimitReachedError:
    360             message_player(GetByLabel('UI/Achievements/Error/TrackedAchievementLimitReached'))
    361 
    362     def untrack(self):
    363         try:
    364             get_repository().activity.untrack_achievement(self.achievement_entry.identifier)
    365         except TrackedAchievementNotFoundError:
    366             logger.warning('Tracked achievement not found: %s', self.achievement_entry.identifier)
    367 
    368     def get_contribution_parameters_to_display(self):
    369         exclude_list = [ x for x in EXCLUDED_CONTRIB_METHOD_PARAM_KEYS ]
    370         progress_mode = self.contribution_attributes.progress_config.progress_type
    371         if progress_mode == ProgressType.CHECKLIST:
    372             exclude_list.append(self.contribution_attributes.progress_config.target_parameter)
    373             logger.info('get_contribution_parameters_to_display: skipping %s for achievement %s as it is the checklist target parameter', self.contribution_attributes.progress_config.target_parameter, self.achievement_entry.attributes.name_message.get_localized_text())
    374         parameters_to_display = []
    375         for parameter_entry in self.contribution_attributes.parameters:
    376             if parameter_entry.identifier.key not in exclude_list:
    377                 param_config = self.contribution_config.get_parameter_config_by_identifier(parameter_entry.identifier)
    378                 if param_config is not None:
    379                     parameters_to_display.append((parameter_entry, param_config))
    380 
    381         return parameters_to_display
    382 
    383     @property
    384     def parameters_to_display_as_list(self):
    385         result = []
    386         include_list = []
    387         if self.progress_type == ProgressType.CHECKLIST:
    388             include_list.append(self.contribution_attributes.progress_config.target_parameter)
    389         if len(include_list) == 0:
    390             return result
    391         for parameter_entry in self.contribution_attributes.parameters:
    392             if parameter_entry.identifier.key in include_list:
    393                 param_config = self.contribution_config.get_parameter_config_by_identifier(parameter_entry.identifier)
    394                 if param_config is not None:
    395                     result.append((parameter_entry, param_config))
    396 
    397         return result
    398 
    399     def get_contribution_param_ui_controllers(self):
    400         result = []
    401         for parameter_entry, param_config in self.get_contribution_parameters_to_display():
    402             component_controller = get_controller_for_configured_parameter(definition=parameter_entry.get_ui_controller(), configuration=param_config.get_ui_controller())
    403             if component_controller is None:
    404                 continue
    405             result.append(component_controller)
    406 
    407         return result
    408 
    409     def _get_percent_progress_towards_milestone(self, index):
    410         current_target = self.target_for_milestone_index(index)
    411         return min(self.progress / current_target, 1.0)
    412 
    413     @property
    414     def category_icon(self):
    415         try:
    416             category_id = self.achievement_entry.attributes.parent_category
    417             category_attributes = get_repository().definitions.get_category(category_id)
    418             return eveicon.get(category_attributes.icon_id)
    419         except DefinitionNotFoundError:
    420             return eveicon.cup