job.py (27541B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\jobboard\client\features\campaigns\job.py 2 import caching 3 import eveformat 4 import eveicon 5 import gametime 6 import mathext 7 import uthread2 8 from brennivin.itertoolsext import Bundle 9 from campaigns.client.v1.data_model.contribution_method import MissingParameterConfiguration 10 from campaigns.client.v1.data_model.objective import FutureObjective, ObjectiveState 11 from campaigns.client.errors import ObjectiveStateError, ParticipantStateError, CampaignForbiddenError, CampaignRequestError 12 from campaigns.client.parameter_types.const import ParameterType 13 from campaigns.client.parameter_types.parameter_controller import get_parameter_class 14 from campaigns.client.v1.signals import on_objective_contributed_notice, on_campaigns_objective_stats_updated, on_commited_state_changed 15 from campaigns.client.ui_controllers.campaign_controller import CampaignController 16 from campaigns.client.validation import check_can_commit, check_can_resign 17 from carbon.common.script.util.format import FmtDate 18 from carbonui import ButtonVariant 19 from carbonui.control.contextMenu.menuData import MenuData 20 from datetimeutils import datetime_to_filetime 21 from eve.client.script.ui import eveColor 22 from eve.client.script.ui.const.eveIconConst import CORP_ICONS 23 from eve.client.script.ui.control.eveIcon import Icon 24 from jobboard.client.features.campaigns.card import CampaignJobCard, FutureCampaignJobCard 25 from jobboard.client.features.campaigns.icons_by_corp_id import FLAT_ICONS_BY_CORP_ID 26 from jobboard.client.features.campaigns.info_panel_entry import CampaignInfoPanelEntry 27 from jobboard.client.features.campaigns.job_dynamic_data import DynamicCampaignJobData 28 from jobboard.client.features.campaigns.job_restrictions import get_restricted_message_id 29 from jobboard.client.features.campaigns.list_entry import CampaignListEntry, CampaignsRewardListEntry 30 from jobboard.client.features.campaigns.page import CampaignObjectivePage 31 from jobboard.client.features.campaigns.qa_tools import get_qa_menu_for_job 32 from jobboard.client.job import BaseJob 33 from jobboard.client.job_board_signals import on_job_state_changed 34 from jobboard.client.util import check_content_tags, get_closest_solarsystem_in_locations_from 35 from localization import GetByLabel, GetByMessageID 36 from metadata.common.content_tags.const import CAREER_PATH_TO_CONTENT_TAG_ID 37 from player_messaging.client.ui_message import message_player 38 from utillib import KeyVal 39 CAMPAIGN_OBJECTIVE_CHAIN_ID = 145 40 41 class BaseCampaignJob(BaseJob): 42 CARD_CLASS = CampaignJobCard 43 PAGE_CLASS = CampaignObjectivePage 44 INFO_PANEL_ENTRY_CLASS = CampaignInfoPanelEntry 45 LIST_ENTRY_CLASS = CampaignListEntry 46 REWARD_LIST_ENTRY_CLASS = CampaignsRewardListEntry 47 48 def __init__(self, job_id, provider, project): 49 self._repository = None 50 self._campaign_controller = None 51 self._objective = project 52 self._objectives_context = None 53 content_id = self.content_id 54 super(BaseCampaignJob, self).__init__(job_id, content_id, provider) 55 56 @property 57 def campaign_id(self): 58 return self._objective.campaign_id 59 60 @property 61 def objective(self): 62 return self._objective 63 64 @property 65 def repository(self): 66 if self._repository is None: 67 from campaigns.client.api import get_campaigns_repository_v1 68 self._repository = get_campaigns_repository_v1() 69 return self._repository 70 71 @property 72 def campaign_controller(self): 73 if self._campaign_controller is None: 74 campaign = self.repository.get_campaign(self.campaign_id) 75 controller = CampaignController(campaign, self.repository) 76 from campaigns.client.api import get_campaigns_repository_v1 77 self._campaign_controller = controller 78 return self._campaign_controller 79 80 @property 81 def content_id(self): 82 return None 83 84 @property 85 def is_active(self): 86 return False 87 88 @property 89 def icon_path(self): 90 return None 91 92 @property 93 def is_future_objective(self): 94 return False 95 96 def _get_contribution_definition_for_contribution_method(self, config_method_identifier): 97 campaign_data = self.campaign_controller.campaign 98 version = campaign_data.version 99 definitions = self.repository.get_contribution_method_definitions(version.definition_semantic_verison) 100 for definition in definitions: 101 if definition.contribution_method == config_method_identifier: 102 return definition 103 104 @property 105 def contribution_method_name(self): 106 return GetByMessageID(self.contribution_method_definition.title) 107 108 @property 109 def contribution_method_progress_description_text(self): 110 return GetByMessageID(self.contribution_method_definition.progress_description) 111 112 @property 113 def contribution_method_icon(self): 114 icon_data = eveicon.get(self.contribution_method_definition.icon or '', None) 115 return icon_data 116 117 @property 118 def restrictions_text(self): 119 return '' 120 121 def on_system_change(self): 122 pass 123 124 @property 125 def objective_background(self): 126 campaign_controller = self.campaign_controller 127 return campaign_controller.textures.objective_background 128 129 @property 130 def campaign_icon_path(self): 131 return self.campaign_controller.textures.icon_path 132 133 @property 134 def card_icon_path(self): 135 return self.campaign_icon_path 136 137 @property 138 def is_committed(self): 139 return False 140 141 @property 142 def total_progress_percentage(self): 143 return 0 144 145 @property 146 def personal_progress_percentage(self): 147 return 0 148 149 @property 150 def has_remaining_personal_progress(self): 151 return True 152 153 def update(self, objective = None): 154 if objective is not None: 155 self._objective = objective 156 return super(BaseCampaignJob, self).update(objective) 157 158 @property 159 def total_remaining_progress(self): 160 return None 161 162 163 class CampaignJob(BaseCampaignJob): 164 CARD_CLASS = CampaignJobCard 165 PAGE_CLASS = CampaignObjectivePage 166 167 def __init__(self, job_id, provider, project): 168 self._closest_solar_system_id = None 169 self._dynamic_data = None 170 super(CampaignJob, self).__init__(job_id, provider, project) 171 172 @property 173 def dynamic_data(self): 174 if self._dynamic_data is None: 175 self._dynamic_data = DynamicCampaignJobData(self.repository, self.campaign_id, self.objective_id, self._isk_reward, self._lp_reward) 176 return self._dynamic_data 177 178 @property 179 def content_id(self): 180 return self._objective.id 181 182 @property 183 def objective_id(self): 184 return self._objective.id 185 186 @property 187 def title(self): 188 return GetByMessageID(self.title_message_id) 189 190 @property 191 def title_message_id(self): 192 return self._objective.title 193 194 @property 195 def description(self): 196 return GetByMessageID(self._objective.subtitle) 197 198 @property 199 def contribution_method_definition(self): 200 config = self.contribution_method_configuration 201 config_method_identifier = config.contribution_method 202 return self._get_contribution_definition_for_contribution_method(config_method_identifier) 203 204 def get_contribution_method_info(self): 205 definition = self.contribution_method_definition 206 configuration = self.contribution_method_configuration 207 job_def = definition.to_job_format() 208 param_def = job_def.parameter_def_by_key 209 job_config = configuration.to_job_format() 210 param_config = job_config.parameter_configs_by_key 211 param_def_and_config = {} 212 for k, param_d in param_def.iteritems(): 213 config = param_config.get(k, None) 214 if not config: 215 config = MissingParameterConfiguration(k, []) 216 param_def_and_config[k] = (param_d, config) 217 218 return Bundle(job_contribution_definition=job_def, param_def_and_config=param_def_and_config) 219 220 @property 221 def contribution_method_configuration(self): 222 return self._objective.contribution_method_configuration 223 224 @property 225 def career_path(self): 226 return self._objective.career_path 227 228 @property 229 def theme_pack(self): 230 return self.campaign_controller.theme_pack 231 232 @property 233 def target_progress(self): 234 return self._objective.target_progress 235 236 @property 237 def current_total_progress(self): 238 return self.dynamic_data.current_total_progress 239 240 @property 241 def total_progress_percentage(self): 242 if self.current_total_progress is 0: 243 return 0.0 244 return self.current_total_progress / float(self.target_progress) 245 246 @property 247 def total_progress_percentage_with_contribution_text(self): 248 total_progress = self.total_progress_percentage 249 return self._get_progress_with_contribution_text(total_progress) 250 251 @property 252 def total_remaining_progress(self): 253 remaining = max(0, self.target_progress - self.current_total_progress) 254 return remaining 255 256 @property 257 def committed_participants(self): 258 return self.dynamic_data.committed_participants 259 260 @property 261 def personal_progress(self): 262 return self.dynamic_data.personal_progress 263 264 @property 265 def personal_progress_percentage(self): 266 if self.personal_progress is 0: 267 return 0.0 268 if self.contribution_limit: 269 return self.personal_progress / float(self.contribution_limit) 270 return self.personal_progress / float(self.target_progress) 271 272 def _get_progress_with_contribution_text(self, progress): 273 ratio = eveformat.percent(mathext.clamp(progress, 0, 1.0), decimal_places=1) 274 return '%s %s' % (ratio, self.contribution_method_progress_description_text) 275 276 @property 277 def personal_progress_percentage_with_contribution_text(self): 278 progress = self.personal_progress_percentage 279 return self._get_progress_with_contribution_text(progress) 280 281 @property 282 def remaining_personal_progress(self): 283 return min(self.total_remaining_progress, max(0, self.contribution_limit - self.personal_progress)) 284 285 @property 286 def has_remaining_personal_progress(self): 287 return self.remaining_personal_progress > 0 288 289 @property 290 def personal_progress_limit(self): 291 if self.contribution_limit: 292 return self.contribution_limit 293 return self.target_progress 294 295 def claim_rewards(self): 296 self.repository.redeem_rewards(self.objective_id) 297 298 @property 299 def has_claimable_rewards(self): 300 return self.dynamic_data.has_claimable_rewards 301 302 @property 303 def unclaimed_isk_info(self): 304 return self.dynamic_data.unclaimed_isk_info 305 306 @property 307 def unclaimed_lp_info(self): 308 return self.dynamic_data.unclaimed_lp_info 309 310 @property 311 def _isk_reward(self): 312 rewards = self._objective.rewards 313 if not rewards: 314 return None 315 isk_reward = rewards.isk_reward 316 if isk_reward: 317 return isk_reward 318 319 @property 320 def total_available_amount_isk(self): 321 isk_reward = self._isk_reward 322 if not isk_reward: 323 return 0 324 num_intervals = self.max_progress_per_participant / isk_reward.interval_size 325 total_isk = isk_reward.amount_per_interval * num_intervals 326 return total_isk 327 328 @property 329 def isk_amount_per_interval(self): 330 isk_reward = self._isk_reward 331 if not isk_reward: 332 return None 333 return isk_reward.amount_per_interval 334 335 @property 336 def isk_interval_size(self): 337 isk_reward = self._isk_reward 338 if not isk_reward: 339 return None 340 return isk_reward.interval_size 341 342 @property 343 def _lp_reward(self): 344 rewards = self._objective.rewards 345 if not rewards: 346 return None 347 lp_reward = rewards.lp_reward 348 if lp_reward: 349 return lp_reward 350 351 @property 352 def total_available_amount_lp(self): 353 lp_reward = self._lp_reward 354 if not lp_reward: 355 return 0 356 num_intervals = self.max_progress_per_participant / lp_reward.interval_size 357 total_lp = lp_reward.amount_per_interval * num_intervals 358 return total_lp 359 360 @property 361 def lp_amount_per_interval(self): 362 lp_reward = self._lp_reward 363 if not lp_reward: 364 return None 365 return lp_reward.amount_per_interval 366 367 @property 368 def lp_interval_size(self): 369 lp_reward = self._lp_reward 370 if not lp_reward: 371 return None 372 return lp_reward.interval_size 373 374 @property 375 def lp_issuer_id(self): 376 lp_reward = self._lp_reward 377 if not lp_reward: 378 return '' 379 issuing_corporation = lp_reward.issuing_corporation 380 return issuing_corporation 381 382 @property 383 def lp_issuer_text(self): 384 issuing_corporation = self.lp_issuer_id 385 if issuing_corporation: 386 return cfg.eveowners.Get(issuing_corporation).name 387 return '' 388 389 @property 390 def card_icon_path(self): 391 issuer_id = self.lp_issuer_id 392 if issuer_id in FLAT_ICONS_BY_CORP_ID: 393 return FLAT_ICONS_BY_CORP_ID[issuer_id] 394 if issuer_id in CORP_ICONS: 395 path = CORP_ICONS[issuer_id] 396 res_path, _ = Icon.ConvertIconNoToResPath(path) 397 return res_path 398 return super(CampaignJob, self).card_icon_path 399 400 @property 401 def _standings(self): 402 rewards = self._objective.rewards 403 if not rewards: 404 return None 405 standings_reward = rewards.standings_reward 406 if standings_reward: 407 return standings_reward 408 409 @property 410 def has_standings_boost(self): 411 standings_rewards = self._standings 412 if standings_rewards: 413 return True 414 return False 415 416 @property 417 def standing_booster_issuer_name(self): 418 standings_rewards = self._standings 419 if not standings_rewards: 420 return None 421 issuer_id = standings_rewards.issuer 422 if not issuer_id: 423 return None 424 return cfg.eveowners.Get(issuer_id).name 425 426 @property 427 def issuer_id(self): 428 return self._objective._issuer 429 430 @property 431 def issuer_name(self): 432 try: 433 return cfg.eveowners.Get(self.issuer_id).name 434 except Exception: 435 pass 436 437 return '' 438 439 @property 440 def state(self): 441 return self._objective.objective_state 442 443 @property 444 def finished_timestamp(self): 445 if self._objective.is_finished: 446 return datetime_to_filetime(self._objective.finished_datetime) 447 448 @property 449 def is_finished(self): 450 return self._objective.is_finished 451 452 @property 453 def is_active(self): 454 return self.state == ObjectiveState.ACTIVE 455 456 @property 457 def is_expired(self): 458 return self.state == ObjectiveState.EXPIRED 459 460 @property 461 def is_completed(self): 462 return self.state == ObjectiveState.COMPLETED 463 464 @property 465 def is_participant_state_unknown(self): 466 return self.dynamic_data.is_participant_state_unknown 467 468 @property 469 def is_committed(self): 470 return self.dynamic_data.is_committed 471 472 @property 473 def is_resigned(self): 474 return self.dynamic_data.is_resigned 475 476 @property 477 def contribution_limit(self): 478 return self._objective.max_progress_per_participant 479 480 @property 481 def is_available_in_browse(self): 482 if not super(CampaignJob, self).is_available_in_browse: 483 return False 484 if self.is_expired: 485 return False 486 if not self._can_contribute_for_browse(): 487 return False 488 if self.campaign_controller.is_expired: 489 return False 490 return True 491 492 def check_filters(self, content_tag_ids = None, keywords = None, **kwargs): 493 if not content_tag_ids: 494 return True 495 if self.campaign_id in content_tag_ids: 496 return True 497 if not check_content_tags(content_tag_ids, self.content_tag_ids): 498 return False 499 if not self._check_keywords(keywords): 500 return False 501 return True 502 503 @property 504 def is_available_in_active(self): 505 if not self.is_active: 506 return False 507 if self.is_tracked: 508 return True 509 return self.is_committed 510 511 @property 512 def is_trackable(self): 513 return self.is_active and self.is_committed 514 515 @property 516 def is_linkable(self): 517 return not self.is_removed 518 519 @property 520 def max_progress_per_participant(self): 521 return self._objective.max_progress_per_participant 522 523 def _register(self): 524 on_objective_contributed_notice.connect(self._on_objective_contributed) 525 on_campaigns_objective_stats_updated.connect(self._on_objective_stats_updated) 526 on_commited_state_changed.connect(self._on_participation_state_changed) 527 528 def _unregister(self): 529 on_objective_contributed_notice.disconnect(self._on_objective_contributed) 530 on_campaigns_objective_stats_updated.disconnect(self._on_objective_stats_updated) 531 on_commited_state_changed.disconnect(self._on_participation_state_changed) 532 533 def _update_job(self, state_changed = False): 534 self.on_job_updated() 535 if state_changed: 536 on_job_state_changed(self) 537 538 def get_cta_buttons(self): 539 buttons = [] 540 if self.is_active: 541 if self.is_committed: 542 buttons.append({'label': GetByLabel('UI/Campaigns/ResignFromJob'), 543 'hint': GetByLabel('UI/Campaigns/ResignFromJobHint'), 544 'on_click': self.on_resign, 545 'variant': ButtonVariant.GHOST, 546 'is_enabled': self.can_resign()}) 547 else: 548 buttons.append({'label': GetByLabel('UI/Campaigns/ParticipateNow'), 549 'hint': self._get_commit_tooltip(), 550 'on_click': self.on_commit, 551 'is_enabled': self.can_commit()}) 552 if self.is_committed or self.has_claimable_rewards: 553 pass 554 return buttons 555 556 def _get_commit_tooltip(self): 557 label_path = 'UI/Campaigns/ParticipateNowHint' 558 try: 559 check_can_commit(self) 560 except ObjectiveStateError as e: 561 label_path = 'UI/Campaigns/ParticipateNowHintError' 562 except ParticipantStateError as e: 563 message_id = get_restricted_message_id(self) 564 if message_id: 565 return GetByMessageID(message_id) 566 label_path = 'UI/Campaigns/ParticipateNowHintError' 567 568 return GetByLabel(label_path) 569 570 def _can_contribute_for_browse(self): 571 if not self.is_active: 572 return False 573 if not self.dynamic_data.has_valid_stats_caches: 574 self.repository.prime_all_stats_for_campaign(self.campaign_id) 575 return False 576 return self.remaining_personal_progress > 0 577 578 def can_commit(self): 579 try: 580 check_can_commit(self) 581 return True 582 except Exception as e: 583 return False 584 585 def can_resign(self): 586 try: 587 check_can_resign(self) 588 return True 589 except Exception as e: 590 return False 591 592 def on_commit(self, button = None): 593 if button is None: 594 uthread2.start_tasklet(self._do_commit) 595 return 596 if button.busy: 597 return 598 button.busy = True 599 button.disabled = True 600 uthread2.start_tasklet(self._commit_sequence, button) 601 602 def _commit_sequence(self, button): 603 self._do_commit() 604 button.busy = False 605 button.hint = None 606 607 def _do_commit(self): 608 try: 609 self.repository.commit(self.objective_id) 610 except CampaignForbiddenError: 611 message_player(GetByLabel('UI/Campaigns/UnableToCommitCampaignForbiddenError', numObjectives=10)) 612 return 613 except CampaignRequestError: 614 message_player(GetByLabel('UI/Campaigns/CannotCommitCampaignRequestError')) 615 return 616 617 def on_resign(self, button = None): 618 if button is None: 619 uthread2.start_tasklet(self._do_resign) 620 return 621 if button.busy: 622 return 623 button.busy = True 624 button.disabled = True 625 uthread2.start_tasklet(self._resign_sequence, button) 626 627 def _resign_sequence(self, button): 628 self._do_resign() 629 button.busy = False 630 button.disabled = False 631 632 def _do_resign(self): 633 self.repository.resign(self.objective_id) 634 635 def _on_participation_state_changed(self, objective_id): 636 if objective_id != self.objective_id: 637 return 638 if self.is_committed and not self.is_tracked: 639 self.add_tracked() 640 elif self.is_tracked and not self.is_trackable: 641 self.remove_tracked() 642 self._closest_solar_system_id = None 643 self._update_job(state_changed=True) 644 645 def _get_content_tag_ids(self): 646 return self.objective.content_tags 647 648 @property 649 def campaign_name(self): 650 return self.campaign_controller.title_text 651 652 @property 653 def campaign_issuer_name(self): 654 return self.campaign_controller.issuer_name 655 656 @property 657 def campaign_description(self): 658 return self.campaign_controller.subtitle_text 659 660 @property 661 def time_left_text(self): 662 return self.campaign_controller.time_left_text 663 664 @property 665 def expiration_time(self): 666 return datetime_to_filetime(self.campaign_controller.expiry_datetime) 667 668 @property 669 def presenting_character_id(self): 670 return self._objective.presenting_character 671 672 @property 673 def icon_path(self): 674 return self.campaign_controller.textures.icon_path 675 676 def get_menu(self): 677 data = super(BaseCampaignJob, self).get_menu() 678 data.extend(get_qa_menu_for_job(self)) 679 return data 680 681 def on_system_change(self): 682 self._closest_solar_system_id = None 683 684 @property 685 def solar_system_id(self): 686 if self._closest_solar_system_id is None: 687 self._update_closest_solar_system() 688 return self._closest_solar_system_id 689 690 def _update_closest_solar_system(self): 691 if not session.solarsystemid2: 692 return 693 location_ids = self.get_location_ids() 694 closest_solar_system_id = get_closest_solarsystem_in_locations_from(session.solarsystemid2, set(location_ids), sm.GetService('map'), sm.GetService('clientPathfinderService'))[0] 695 if closest_solar_system_id is not None: 696 self._closest_solar_system_id = closest_solar_system_id 697 698 def get_location_ids(self): 699 contribution_method_info = self.get_contribution_method_info() 700 return self.get_contribution_method_locations(contribution_method_info.param_def_and_config) 701 702 def get_contribution_method_locations(self, param_def_and_config): 703 locations = set() 704 for param_def, param_config in param_def_and_config.itervalues(): 705 if param_def.parameter_type in (ParameterType.LOCATION, ParameterType.DOCKABLE_LOCATION): 706 values = param_config.get_values() 707 parm_class = get_parameter_class(param_def.parameter_type) 708 if parm_class: 709 locations.update(parm_class.get_solarsystem_id_from_locations(values)) 710 711 return locations 712 713 @property 714 def annotations(self): 715 return self._objective.annotations 716 717 @property 718 def restrictions_text(self): 719 return self._GetTextFromAnnotations('restriction_tooltip_message_id') 720 721 def get_warning_texts(self): 722 warning_texts = [] 723 for x in xrange(1, 10): 724 name = 'warning_%s_message_id' % x 725 text = self._GetTextFromAnnotations(name) 726 if text: 727 warning_texts.append(text) 728 else: 729 break 730 731 return warning_texts 732 733 def _GetTextFromAnnotations(self, field_name, default_value = ''): 734 message_id = self.annotations.get(field_name, None) 735 if message_id is None: 736 return default_value 737 return GetByMessageID(int(message_id)) 738 739 def _on_objective_contributed(self, objective_id, total_participant_progress): 740 if objective_id != self.objective_id: 741 return 742 self._update_project() 743 744 def _on_objective_stats_updated(self, objective_ids): 745 if self.objective_id not in objective_ids: 746 return 747 self._update_project() 748 749 def _update_project(self, state_changed = False): 750 self._update_context() 751 self.on_job_updated() 752 if state_changed: 753 on_job_state_changed(self) 754 755 @caching.lazy_property 756 def objective_chain(self): 757 from objectives.client.objective_chain import ObjectiveChain 758 from objectives.common.objective_context import ObjectivesContext 759 self._objectives_context = ObjectivesContext() 760 self._update_context() 761 objective_chain = ObjectiveChain(content_id=CAMPAIGN_OBJECTIVE_CHAIN_ID, context=self._objectives_context, overrides={'progress': KeyVal(title=self.contribution_method_definition.title)}) 762 objective_chain.start() 763 return objective_chain 764 765 def _update_context(self): 766 if not self._objectives_context: 767 return 768 self._objectives_context.update_value(key='global_target_progress', value=self.target_progress) 769 self._objectives_context.update_value(key='global_current_progress', value=self.current_total_progress) 770 self._objectives_context.update_value(key='display_global_as_percentage', value=True) 771 self._objectives_context.update_value(key='personal_progress', value=self.personal_progress) 772 self._objectives_context.update_value(key='personal_target_progress', value=self.contribution_limit) 773 self._objectives_context.update_value(key='progress_bar_hex_color', value=eveColor.SUCCESS_GREEN_HEX) 774 775 776 class FutureCampaignJob(BaseCampaignJob): 777 CARD_CLASS = FutureCampaignJobCard 778 PAGE_CLASS = CampaignObjectivePage 779 780 @property 781 def content_id(self): 782 return (self.start_datetime, self._objective.career_path, self._objective.contribution_method_name) 783 784 @property 785 def start_datetime(self): 786 return self._objective.start_datetime 787 788 @property 789 def title(self): 790 return self.contribution_method_name 791 792 @property 793 def is_future_objective(self): 794 return True 795 796 def _get_content_tag_ids(self): 797 career_content_path = CAREER_PATH_TO_CONTENT_TAG_ID.get(self.objective.career_path) 798 if career_content_path: 799 return [career_content_path] 800 return [] 801 802 def get_menu(self): 803 data = MenuData() 804 return data 805 806 @property 807 def contribution_method_definition(self): 808 config_method_identifier = self._objective.contribution_method_name 809 return self._get_contribution_definition_for_contribution_method(config_method_identifier) 810 811 @property 812 def time_until_start_text(self): 813 start_date = datetime_to_filetime(self.start_datetime) 814 diff = max(0, start_date - gametime.GetWallclockTime()) 815 time_left = FmtDate(diff, 'ss') 816 return time_left 817 818 def check_filters(self, content_tag_ids = None, keywords = None, **kwargs): 819 return False