goalsController.py (26654B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\corporation\client\goals\goalsController.py 2 import corporation.client.goals.goalMessengerSignals as messenger_signals 3 import gametime 4 import logging 5 import threadutils 6 import uthread2 7 from assetholding.client import assetholdingSignals 8 from assetholding.client.assetholdingController import AssetHoldingController 9 from carbonui import uiconst 10 from collections import defaultdict 11 from corporation.client.goals import goalSignals 12 from corporation.client.goals.errors import AtGoalCapacity, BadRequestToReserveAsset, WalletAccessForbidden, InsufficientFunds, InvalidExpirationTime 13 from corporation.client.goals.featureFlag import are_corporation_goals_enabled 14 from corporation.client.goals.goal import CorporationGoal 15 from corporation.client.goals.goalMessenger import GoalMessenger 16 from corporation.client.goals.goalsSettings import qa_allow_short_corp_projects 17 from corporation.client.goals.goalsUtil import get_timespan_by_option 18 from eve.common.script.sys.idCheckers import IsNPCCorporation 19 from goals.common.goalConst import ContributionMethodTypes, GoalState 20 from localization import GetByLabel 21 from player_messaging.client.ui_message import message_player, prompt_player_fsd_dialog 22 logger = logging.getLogger('corporation_goals') 23 24 class CorpGoalsController(object): 25 __notifyevents__ = ['OnCharacterSelected', 'OnSessionChanged'] 26 _instance = None 27 28 def __init__(self): 29 self._capacity = None 30 self._messenger = None 31 self._goals = {} 32 self._fetching_data_for_goal_ids = set() 33 self._active_goal_ids = set() 34 self._is_active_dirty = True 35 self._fetching_active = False 36 self._unclaimed_goal_ids = set() 37 self._is_unclaimed_dirty = True 38 self._fetching_unclaimed = False 39 self._has_tried_fetching_any_unclaimed_ids = False 40 self._inactive_goal_ids = defaultdict(set) 41 self._is_inactive_dirty = defaultdict(lambda : True) 42 self._fetching_inactive = defaultdict(lambda : False) 43 sm.RegisterNotify(self) 44 self._connect_to_messenger_signals() 45 AssetHoldingController.get_instance() 46 47 def __del__(self): 48 sm.UnregisterNotify(self) 49 self._disconnect_from_messenger_signals() 50 51 def _connect_to_messenger_signals(self): 52 messenger_signals.on_goal_created_internal.connect(self._on_goal_created) 53 messenger_signals.on_goal_deleted_internal.connect(self._on_goal_deleted) 54 messenger_signals.on_goal_closed_internal.connect(self._on_goal_closed) 55 messenger_signals.on_goal_completed_internal.connect(self._on_goal_completed) 56 messenger_signals.on_goal_contribution_internal.connect(self._on_goal_contribution) 57 messenger_signals.on_goal_progress_set_internal.connect(self._on_goal_progress_set) 58 messenger_signals.on_goal_redeemed_internal.connect(self._on_goal_redeemed) 59 messenger_signals.on_goal_name_changed_internal.connect(self._on_goal_name_changed) 60 messenger_signals.on_goal_description_changed_internal.connect(self._on_goal_description_changed) 61 messenger_signals.on_goal_expired_internal.connect(self._on_goal_expired) 62 assetholdingSignals.on_entitlement_redeemed.connect(self._on_goal_redeemed) 63 64 def _disconnect_from_messenger_signals(self): 65 messenger_signals.on_goal_created_internal.disconnect(self._on_goal_created) 66 messenger_signals.on_goal_deleted_internal.disconnect(self._on_goal_deleted) 67 messenger_signals.on_goal_closed_internal.disconnect(self._on_goal_closed) 68 messenger_signals.on_goal_completed_internal.disconnect(self._on_goal_completed) 69 messenger_signals.on_goal_contribution_internal.disconnect(self._on_goal_contribution) 70 messenger_signals.on_goal_progress_set_internal.disconnect(self._on_goal_progress_set) 71 messenger_signals.on_goal_redeemed_internal.disconnect(self._on_goal_redeemed) 72 messenger_signals.on_goal_name_changed_internal.disconnect(self._on_goal_name_changed) 73 messenger_signals.on_goal_description_changed_internal.disconnect(self._on_goal_description_changed) 74 messenger_signals.on_goal_expired_internal.disconnect(self._on_goal_expired) 75 assetholdingSignals.on_entitlement_redeemed.disconnect(self._on_goal_redeemed) 76 77 @classmethod 78 def get_instance(cls): 79 if not cls._instance: 80 cls._instance = CorpGoalsController() 81 return cls._instance 82 83 @property 84 def messenger(self): 85 if self._messenger is None: 86 self._messenger = GoalMessenger.get_instance(sm.GetService('publicGatewaySvc')) 87 return self._messenger 88 89 def redeem_reward(self, goal_id): 90 try: 91 self.messenger.redeem_reward(goal_id) 92 except Exception as e: 93 logger.warning('Failed to redeem goal with id %s - %s', goal_id, str(e)) 94 goalSignals.on_goal_redeem_failed(goal_id) 95 96 def get_active_goals(self, fetch_contribution = True, wait = True): 97 self.fetch_active_goals(fetch_contribution=fetch_contribution) 98 if wait: 99 self.wait_for_active() 100 return self.get_cached_active_goals() 101 102 def get_cached_active_goals(self): 103 return [ self._goals[goal_id] for goal_id in self._active_goal_ids if self._goals[goal_id].has_data() ] 104 105 def fetch_active_goals(self, fetch_contribution = True): 106 if not self._should_fetch_goals(): 107 return 108 if self._fetching_active: 109 return 110 if self._is_active_dirty: 111 self._fetching_active = True 112 uthread2.start_tasklet(self._fetch_active_goal_ids) 113 uthread2.start_tasklet(self._fetch_missing_active_goals_data, fetch_contribution) 114 115 def wait_for_active(self): 116 while self._fetching_active: 117 uthread2.Yield() 118 119 def get_unclaimed_goals(self, wait = True): 120 self.fetch_unclaimed_goals() 121 if wait: 122 self.wait_for_unclaimed() 123 return self.get_cached_unclaimed_goals() 124 125 def get_cached_unclaimed_goals(self): 126 return [ self._goals[goal_id] for goal_id in self._unclaimed_goal_ids if self._goals[goal_id].has_data() ] 127 128 def fetch_unclaimed_goals(self): 129 if not self._should_fetch_goals(): 130 return 131 if self._fetching_unclaimed: 132 return 133 if self._is_unclaimed_dirty: 134 self._fetching_unclaimed = True 135 uthread2.start_tasklet(self._fetch_unclaimed_goal_ids) 136 uthread2.start_tasklet(self._fetch_missing_unclaimed_goals_data) 137 138 def wait_for_unclaimed(self): 139 while self._fetching_unclaimed: 140 uthread2.Yield() 141 142 def get_inactive_goals(self, months_since = None, fetch_contribution = True, wait = True): 143 self.fetch_inactive_goals(months_since, fetch_contribution) 144 if wait: 145 self.wait_for_inactive(months_since) 146 return self.get_cached_inactive_goals(months_since) 147 148 def get_cached_inactive_goals(self, months_since = None): 149 return [ self._goals[goal_id] for goal_id in self._inactive_goal_ids[months_since] if self._goals[goal_id].has_data() ] 150 151 def fetch_inactive_goals(self, months_since = None, fetch_contribution = True): 152 if not self._should_fetch_goals(): 153 return 154 if self._fetching_inactive[months_since]: 155 return 156 if self._is_inactive_dirty[months_since]: 157 self._fetching_inactive[months_since] = True 158 uthread2.start_tasklet(self._fetch_inactive_goal_ids, months_since) 159 uthread2.start_tasklet(self._fetch_missing_inactive_goals_data, months_since, fetch_contribution) 160 161 def wait_for_inactive(self, months_since = None): 162 while self._fetching_inactive[months_since]: 163 uthread2.Yield() 164 165 def is_inactive_goal(self, goal_id, months_since = None): 166 return goal_id in self._inactive_goal_ids[months_since] and self._goals[goal_id].has_data() 167 168 def get_goal(self, goal_id): 169 goal = self._goals.get(goal_id, None) 170 if goal and goal.has_data(): 171 return goal 172 if not self._should_fetch_goals(): 173 return 174 if not goal: 175 logger.info('Creating goal from get_goal %s', goal_id) 176 goal = CorporationGoal(goal_id) 177 self._goals[goal_id] = goal 178 self._fetch_missing_goal_data(goal, wait_while_fetching=True) 179 if not goal.has_data(): 180 return 181 return goal 182 183 def has_unclaimed_rewards(self): 184 if not bool(self._unclaimed_goal_ids) and not self._has_tried_fetching_any_unclaimed_ids and self._is_unclaimed_dirty and not self._fetching_unclaimed and are_corporation_goals_enabled(): 185 self._has_tried_fetching_any_unclaimed_ids = True 186 uthread2.start_tasklet(self._fetch_unclaimed_page, None) 187 return bool(self._unclaimed_goal_ids) 188 189 def _should_fetch_goals(self): 190 return session.corpid and not IsNPCCorporation(session.corpid) and are_corporation_goals_enabled() 191 192 def _fetch_active_goal_ids(self): 193 self._fetching_active = True 194 next_token = None 195 has_exception = False 196 while next_token != '': 197 try: 198 next_token = self._fetch_active_page(token=next_token) 199 except Exception as e: 200 logger.warning('Unable to fetch active goal ids with token %s - %s', next_token, str(e)) 201 has_exception = True 202 break 203 204 self._fetching_active = False 205 self._is_active_dirty = has_exception 206 207 def _fetch_active_page(self, token): 208 if token is None: 209 token = '' 210 next_token, goal_ids = self.messenger.get_active_goal_ids(token=token) 211 for goal_id in goal_ids: 212 if goal_id not in self._goals: 213 self._goals[goal_id] = CorporationGoal(goal_id) 214 self._active_goal_ids.add(goal_id) 215 216 return next_token 217 218 def _fetch_missing_active_goals_data(self, fetch_contribution = True): 219 self.wait_for_active() 220 for goal_id in self._active_goal_ids: 221 self._fetch_missing_goal_data(self._goals.get(goal_id, None), fetch_contribution) 222 223 def _fetch_unclaimed_goal_ids(self): 224 self._fetching_unclaimed = True 225 next_token = None 226 has_exception = False 227 while next_token != '': 228 try: 229 next_token = self._fetch_unclaimed_page(token=next_token) 230 except Exception as e: 231 logger.warning('Unable to fetch unclaimed goal ids with token %s - %s', next_token, str(e)) 232 has_exception = True 233 break 234 235 self._fetching_unclaimed = False 236 self._is_unclaimed_dirty = has_exception 237 238 def _fetch_unclaimed_page(self, token): 239 if token is None: 240 token = '' 241 next_token, goal_ids = self.messenger.get_unclaimed_goal_ids(token=token) 242 self._has_tried_fetching_any_unclaimed_ids = True 243 for goal_id in goal_ids: 244 if goal_id not in self._goals: 245 self._goals[goal_id] = CorporationGoal(goal_id) 246 self._unclaimed_goal_ids.add(goal_id) 247 248 if bool(goal_ids): 249 goalSignals.on_unclaimed_goal_ids_changed() 250 return next_token 251 252 def _fetch_missing_unclaimed_goals_data(self): 253 self.wait_for_unclaimed() 254 for goal_id in self._unclaimed_goal_ids: 255 self._fetch_missing_goal_data(self._goals.get(goal_id, None)) 256 257 def _fetch_inactive_goal_ids(self, months_since): 258 self._fetching_inactive[months_since] = True 259 next_token = None 260 has_exception = False 261 while next_token != '': 262 try: 263 next_token = self._fetch_inactive_page(months_since, token=next_token) 264 except Exception as e: 265 logger.warning('Unable to fetch inactive goal ids with token %s - %s', next_token, str(e)) 266 has_exception = True 267 break 268 269 self._fetching_inactive[months_since] = False 270 self._is_inactive_dirty[months_since] = has_exception 271 272 def _fetch_inactive_page(self, months_since, token): 273 if token is None: 274 token = '' 275 start_time, duration = get_timespan_by_option(months_since) 276 next_token, goal_ids = self.messenger.get_inactive_goal_ids(start_time, duration, token=token) 277 for goal_id in goal_ids: 278 if goal_id not in self._goals: 279 self._goals[goal_id] = CorporationGoal(goal_id) 280 self._inactive_goal_ids[months_since].add(goal_id) 281 282 return next_token 283 284 def _fetch_missing_inactive_goals_data(self, months_since, fetch_contribution = True): 285 self.wait_for_inactive(months_since) 286 for goal_id in self._inactive_goal_ids[months_since]: 287 self._fetch_missing_goal_data(self._goals.get(goal_id, None), fetch_contribution) 288 289 def _fetch_missing_goal_data(self, goal, fetch_contribution = True, wait_while_fetching = False): 290 if not goal: 291 return 292 if goal.has_data() and (not fetch_contribution or goal.has_fetched_contribution()): 293 return 294 goal_id = goal.goal_id 295 if goal_id not in self._fetching_data_for_goal_ids: 296 self._fetching_data_for_goal_ids.add(goal_id) 297 self.__fetch_missing_goal_data(goal, fetch_contribution) 298 if wait_while_fetching: 299 while goal_id in self._fetching_data_for_goal_ids: 300 uthread2.Yield() 301 302 @threadutils.threaded 303 def __fetch_missing_goal_data(self, goal, fetch_contribution): 304 goal_id = goal.get_id() 305 updated = False 306 if not goal.has_data(): 307 try: 308 data = self.messenger.get_goal(goal_id) 309 except Exception as e: 310 logger.warning('Unable to fetch goal %s - %s', goal_id, str(e)) 311 data = None 312 313 if data: 314 goal.set_data(data) 315 updated = True 316 else: 317 fetch_contribution = False 318 if fetch_contribution and not goal.has_fetched_contribution(): 319 if goal.get_current_progress() == 0: 320 summary = {'progress': 0, 321 'rewards_unclaimed': 0} 322 else: 323 try: 324 summary = self.messenger.get_my_contributor_summary(goal_id) 325 except Exception as e: 326 logger.warning('Unable to fetch character contribution summary for goal %s - %s', goal_id, str(e)) 327 summary = None 328 329 if summary: 330 goal.set_contribution(summary['progress'], summary['rewards_unclaimed']) 331 if goal_id not in self._unclaimed_goal_ids and goal.has_unclaimed_reward(): 332 self._unclaimed_goal_ids.add(goal_id) 333 goalSignals.on_unclaimed_goal_ids_changed() 334 updated = True 335 self._fetching_data_for_goal_ids.discard(goal_id) 336 if updated: 337 goalSignals.on_goal_data_fetched(goal) 338 339 def _is_fetching_data_for_goal(self, goal): 340 return goal.goal_id in self._fetching_data_for_goal_ids 341 342 def _is_fetching_any_active_goal_data(self): 343 return not self._active_goal_ids.isdisjoint(self._fetching_data_for_goal_ids) 344 345 def _is_fetching_any_unclaimed_goal_data(self): 346 return not self._unclaimed_goal_ids.isdisjoint(self._fetching_data_for_goal_ids) 347 348 def _is_fetching_any_inactive_goal_data(self, months_since = None): 349 return not self._inactive_goal_ids[months_since].isdisjoint(self._fetching_data_for_goal_ids) 350 351 def flush_cache(self): 352 self._capacity = None 353 self._goals.clear() 354 self._active_goal_ids.clear() 355 self._is_active_dirty = True 356 self._unclaimed_goal_ids.clear() 357 self._is_unclaimed_dirty = True 358 self._has_tried_fetching_any_unclaimed_ids = False 359 self._inactive_goal_ids.clear() 360 self._is_inactive_dirty.clear() 361 goalSignals.on_cache_invalidated() 362 logger.info('GoalsController::flush_cache') 363 364 def get_all_goal_contributor_summaries(self, goal_id): 365 goal = self._goals.get(goal_id, None) 366 if not goal: 367 return [] 368 cached = goal.all_contributor_summaries 369 if cached is not None and gametime.GetSecondsSinceWallclockTime(goal.all_contributor_summaries_fetch_time) < 60: 370 return cached 371 goal.all_contributor_summaries_fetch_time = gametime.GetWallclockTime() 372 result = [] 373 next_token = None 374 has_exception = False 375 while next_token != '': 376 try: 377 if next_token is None: 378 next_token = '' 379 next_token, summaries = self.messenger.get_all_contributor_summaries_for_goal(goal_id=goal_id, token=next_token) 380 result.extend(summaries) 381 except Exception as e: 382 logger.warning('Unable to fetch contributor summaries for goal %s with token %s - %s', goal_id, next_token, str(e)) 383 has_exception = True 384 break 385 386 if not has_exception: 387 goal.all_contributor_summaries = result 388 return result 389 390 def _has_funds(self, amount): 391 wallet = sm.GetService('wallet') 392 wealth = wallet.GetCorpWealth(accountKey=session.corpAccountKey) 393 return wealth >= amount 394 395 def create_goal(self, name, description, desired_progress, method_type, contribution_fields = None, career_path = None, payment_per_contribution = None, end_time = None, participation_limit = None, coverage_limit = None, multiplier = None): 396 if payment_per_contribution and not self._has_funds(payment_per_contribution * desired_progress): 397 message_player(GetByLabel('UI/Corporations/Goals/InsufficientFunds')) 398 raise InsufficientFunds('Funds in the selected wallet division do not suffice to create project') 399 try: 400 self.messenger.create_goal(name=name, description=description, desired_progress=desired_progress, method_id=method_type, contribution_fields=contribution_fields or {}, career_path=career_path, payment=payment_per_contribution, expiration=end_time, validate_end_date=not qa_allow_short_corp_projects.get(), participation_limit=participation_limit, coverage_limit=coverage_limit, multiplier=multiplier) 401 except AtGoalCapacity: 402 max_active = self.get_active_capacity() 403 message_player(GetByLabel('UI/Corporations/Goals/AtGoalsCapacity', numMax=max_active)) 404 raise 405 except BadRequestToReserveAsset: 406 message_player(GetByLabel('UI/Corporations/Goals/InsufficientFunds')) 407 raise 408 except WalletAccessForbidden: 409 message_player(GetByLabel('UI/Corporations/Wallet/WalletDivisionAccessDenied')) 410 raise 411 except InvalidExpirationTime: 412 message_player(GetByLabel('UI/Corporations/Goals/InvalidDuration')) 413 raise 414 except Exception: 415 message_player(GetByLabel('UI/Corporations/Goals/FailedToConnect')) 416 self.flush_cache() 417 raise 418 419 def delete_goal(self, goal_id, show_prompt = True): 420 try: 421 if show_prompt and prompt_player_fsd_dialog('DeleteCorpProject', buttons=uiconst.YESNO) != uiconst.ID_YES: 422 return 423 self.messenger.delete_goal(goal_id) 424 except Exception: 425 message_player(GetByLabel('UI/Corporations/Goals/FailedToConnect')) 426 self.flush_cache() 427 raise 428 429 def complete_goal(self, goal_id): 430 try: 431 if prompt_player_fsd_dialog('CompleteCorpProject', buttons=uiconst.YESNO) != uiconst.ID_YES: 432 return 433 goal = self.get_goal(goal_id) 434 current_progress = goal.get_current_progress() 435 desired_progress = goal.get_desired_progress() 436 updated_progress = desired_progress 437 self._set_goal_progress(goal_id, current_progress, updated_progress, desired_progress) 438 except Exception: 439 message_player(GetByLabel('UI/Corporations/Goals/FailedToConnect')) 440 self.flush_cache() 441 raise 442 443 def close_goal(self, goal_id): 444 try: 445 if prompt_player_fsd_dialog('CloseCorpProject', buttons=uiconst.YESNO) != uiconst.ID_YES: 446 return 447 self.messenger.close_goal(goal_id) 448 except Exception: 449 message_player(GetByLabel('UI/Corporations/Goals/FailedToConnect')) 450 self.flush_cache() 451 raise 452 453 def set_current_progress(self, goal_id, updated_progress): 454 goal = self._goals.get(goal_id, None) 455 if not goal: 456 return 457 current_progress = goal.get_current_progress() 458 desired_progress = goal.get_desired_progress() 459 self._set_goal_progress(goal_id, current_progress, updated_progress, desired_progress) 460 461 def get_items_pending_delivery(self, office_id): 462 if not are_corporation_goals_enabled(): 463 return {} 464 try: 465 goals = self.get_active_goals(wait=False, fetch_contribution=False) 466 except (NotImplementedError, RuntimeError): 467 return {} 468 469 quantity_by_type = defaultdict(int) 470 for goal in goals: 471 if goal.has_reached_participation_limit(): 472 continue 473 contribution_method = goal.get_contribution_method() 474 if contribution_method.method_id == ContributionMethodTypes.DELIVER_ITEM and contribution_method.office in (None, office_id): 475 quantity_by_type[contribution_method.item_type] += goal.get_my_remaining_progress() 476 477 return quantity_by_type 478 479 def get_active_capacity(self): 480 if self._capacity is None: 481 try: 482 self._capacity = self.messenger.get_capacity() 483 except Exception: 484 return 0 485 486 return self._capacity 487 488 def qa_delete_all_goals(self): 489 for goal in self.get_cached_active_goals(): 490 if not goal.get_current_progress(): 491 self.delete_goal(goal.get_id(), show_prompt=False) 492 493 def _set_goal_progress(self, goal_id, current_progress, updated_progress, desired_progress): 494 updated_progress = min(updated_progress, desired_progress) 495 try: 496 self.messenger.set_manual_goal_progress(goal_id=goal_id, current_progress=current_progress, updated_progress=updated_progress) 497 except Exception: 498 message_player(GetByLabel('UI/Corporations/Goals/FailedToConnect')) 499 self.flush_cache() 500 raise 501 502 def OnSessionChanged(self, _isRemote, _session, change): 503 if 'corpid' in change: 504 self.flush_cache() 505 506 def OnCharacterSelected(self, *args, **kwargs): 507 self.flush_cache() 508 509 def _on_goal_created(self, goal_id, goal_data): 510 goal = CorporationGoal(goal_id) 511 goal.set_data(goal_data) 512 self._goals[goal_id] = goal 513 self._active_goal_ids.add(goal.goal_id) 514 goalSignals.on_created(goal_id) 515 516 def _on_goal_deleted(self, goal_id): 517 goal = self._goals.pop(goal_id, None) 518 self._active_goal_ids.discard(goal_id) 519 for months_since in self._inactive_goal_ids: 520 self._inactive_goal_ids[months_since].discard(goal_id) 521 522 if goal: 523 goalSignals.on_deleted(goal_id) 524 525 def _on_goal_closed(self, goal_id): 526 goal = self._goals.get(goal_id, None) 527 self._active_goal_ids.discard(goal_id) 528 self._inactive_goal_ids[None].add(goal_id) 529 if goal: 530 goal.close() 531 goalSignals.on_closed(goal_id) 532 goalSignals.on_state_changed(goal_id, state=GoalState.CLOSED) 533 534 def _on_goal_completed(self, goal_id): 535 goal = self._goals.get(goal_id, None) 536 self._active_goal_ids.discard(goal_id) 537 self._inactive_goal_ids[None].add(goal_id) 538 if goal: 539 desired_progress = goal.get_desired_progress() 540 goal.set_current_progress(desired_progress) 541 goal.complete() 542 goalSignals.on_completed(goal_id) 543 goalSignals.on_state_changed(goal_id, state=GoalState.COMPLETED) 544 545 def _on_goal_expired(self, goal_id): 546 goal = self._goals.get(goal_id, None) 547 self._active_goal_ids.discard(goal_id) 548 self._inactive_goal_ids[None].add(goal_id) 549 if goal: 550 goal.expire() 551 goalSignals.on_expired(goal_id) 552 goalSignals.on_state_changed(goal_id, state=GoalState.EXPIRED) 553 554 def _on_goal_progress_set(self, goal_id, progress): 555 logger.info('GoalsController::_on_goal_progress_set: goal_id=%s, progress=%s', goal_id, progress) 556 goal = self._goals.get(goal_id, None) 557 if not goal: 558 logger.info('Goal not found, not setting progress: goal_id=%s, progress=%s', goal_id, progress) 559 return 560 goal.set_current_progress(progress) 561 goalSignals.on_progress_changed(goal_id, progress, state_changed=False) 562 563 def _on_goal_contribution(self, goal_id, progress_added, current_progress): 564 goal = self._goals.get(goal_id, None) 565 if not goal: 566 return 567 state_changed = goal.update_my_progress(progress_added) 568 goal.set_current_progress(current_progress) 569 if goal_id not in self._unclaimed_goal_ids and goal.has_unclaimed_reward(): 570 self._unclaimed_goal_ids.add(goal_id) 571 goalSignals.on_unclaimed_goal_ids_changed() 572 goalSignals.on_progress_changed(goal_id, current_progress, state_changed=state_changed) 573 574 def _on_goal_redeemed(self, goal_id, quantity): 575 goal = self._goals.get(goal_id, None) 576 if goal: 577 goal.update_redeemed_capacity(quantity) 578 if not goal.has_unclaimed_reward() and goal_id in self._unclaimed_goal_ids: 579 self._unclaimed_goal_ids.discard(goal_id) 580 goalSignals.on_unclaimed_goal_ids_changed() 581 582 def _on_goal_name_changed(self, goal_id, new_name): 583 goal = self._goals.get(goal_id, None) 584 if goal: 585 goal.set_name(new_name) 586 goalSignals.on_goal_name_changed(goal_id) 587 588 def _on_goal_description_changed(self, goal_id, new_description): 589 goal = self._goals.get(goal_id, None) 590 if goal: 591 goal.set_description(new_description) 592 goalSignals.on_goal_description_changed(goal_id) 593 594 595 def __SakeReloadHook(): 596 try: 597 CorpGoalsController.get_instance().flush_cache() 598 except Exception: 599 import log 600 log.LogException()