Skip to content

Commit

Permalink
Leader traits
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasdoehne committed Nov 8, 2023
1 parent f55f3ac commit cd7a845
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

function toggle_visibility(className) {
var elements = document.getElementsByClassName(className);
console.log("lalalal");
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = (elements[i].style.display == 'list-item' || elements[i].style.display == "") ? 'none' : 'list-item';
}
Expand Down
22 changes: 7 additions & 15 deletions stellarisdashboard/dashboard_app/history_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,14 +477,16 @@ def leader_details(self, leader_model: datamodel.Leader) -> Dict[str, str]:
"Gender": game_info.convert_id_to_name(leader_model.gender),
"Species": leader_model.species.rendered_name,
"Class": f"{game_info.convert_id_to_name(leader_model.leader_class)} in the {country_url}",
"Subclass": f"{game_info.lookup_key(leader_model.subclass)}" or "None",
"Traits": ", ".join(leader_model.rendered_traits),
"Born": datamodel.days_to_date(leader_model.date_born),
"Hired": datamodel.days_to_date(leader_model.date_hired),
"Last active": datamodel.days_to_date(
utils.get_most_recent_date(self._session)
if leader_model.is_active
else leader_model.last_date
),
"Status": "Active" if leader_model.is_active else "Dead or Dismissed",
"Status": "Active" if leader_model.is_active else "Dead or retired",
}
return details

Expand All @@ -497,23 +499,13 @@ def country_details(self, country_model: datamodel.Country) -> Dict[str, str]:
details.update(
{
"Personality": game_info.convert_id_to_name(gov.personality),
"Government Type": game_info.convert_id_to_name(
gov.gov_type, remove_prefix="gov"
),
"Authority": game_info.convert_id_to_name(
gov.authority, remove_prefix="auth"
),
"Government Type": game_info.lookup_key(gov.gov_type),
"Authority": game_info.lookup_key(gov.authority),
"Ethics": ", ".join(
[
game_info.convert_id_to_name(e, remove_prefix="ethic")
for e in sorted(gov.ethics)
]
[game_info.lookup_key(e) for e in sorted(gov.ethics)]
),
"Civics": ", ".join(
[
game_info.convert_id_to_name(c, remove_prefix="civic")
for c in sorted(gov.civics)
]
[game_info.lookup_key(c) for c in sorted(gov.civics)]
),
}
)
Expand Down
11 changes: 10 additions & 1 deletion stellarisdashboard/dashboard_app/templates/history_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,15 @@ <h2 class="eventlist_header">{{title[object] | safe}}</h2>
</span>
</div>
</li>
{% elif event["event_type"] == "gained_trait" %}
<li class="eventitem gained_trait">
<div class="eventdescription">
<span class="dateblock">{{event["start_date"]}}:</span>
<span class="eventtext">
{{ event["leader"].leader_class.capitalize() }} {{ links[event["leader"]] | safe }} gained the "{{ event["description"] }}" trait.
</span>
</div>
</li>
{% elif event["event_type"] == "first_contact" %}
<li class="eventitem first_contact">
<div class="eventdescription">
Expand Down Expand Up @@ -620,7 +629,7 @@ <h2 class="eventlist_header">{{title[object] | safe}}</h2>
<div class="eventdescription">
<span class="dateblock">{{event["start_date"]}}:</span>
<span class="eventtext">
{{ event["leader"].leader_class.capitalize() }} {{ links[event["leader"]] | safe }} died or was fired.
{{ event["leader"].leader_class.capitalize() }} {{ links[event["leader"]] | safe }} died or retired.
</span>
</div>
</li>
Expand Down
30 changes: 27 additions & 3 deletions stellarisdashboard/datamodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ class HistoricalEventType(enum.Enum):
leader_died = enum.auto() # TODO
level_up = enum.auto()
fleet_command = enum.auto()
gained_trait = enum.auto()
lost_trait = enum.auto()

# empire progress:
researched_technology = enum.auto()
Expand Down Expand Up @@ -887,7 +889,9 @@ class CouncilAgenda(Base):

name_id = Column(ForeignKey(SharedDescription.description_id), index=True)

country = relationship(Country, foreign_keys=[country_id], back_populates="council_agendas")
country = relationship(
Country, foreign_keys=[country_id], back_populates="council_agendas"
)
db_name = relationship(SharedDescription, foreign_keys=[name_id])

@property
Expand Down Expand Up @@ -1417,6 +1421,9 @@ class Leader(Base):
gender = Column(String(20))
last_level = Column(Integer)

subclass = Column(String()) # optional
leader_traits = Column(String()) # comma-separated

date_hired = Column(Integer) # The date when this leader was first encountered
date_born = Column(Integer) # estimated birthday
last_date = Column(Integer) # estimated death / dismissal
Expand Down Expand Up @@ -1445,6 +1452,13 @@ def rendered_name(self):
rendered = f"{rendered_first}{rendered_second}"
return rendered

@property
def rendered_traits(self) -> List[str]:
# todo: add level to this?
# todo: Imperial heir and ruler traits map to "[triggered_imperial_name]" which is
# then resolved in common/scripted_loc/08_scripted_loc_paragon.txt
return [game_info.lookup_key(t.rstrip("_0123456789")) for t in sorted(self.leader_traits.split(","))]


class Planet(Base):
__tablename__ = "planet"
Expand Down Expand Up @@ -1800,8 +1814,18 @@ def description(self) -> str:
old_rendered = game_info.lookup_key(old)
new_rendered = game_info.lookup_key(new)
return f"{name_rendered!r} from {old_rendered!r} to {new_rendered!r}"
elif self.event_type in (HistoricalEventType.agenda_launch, HistoricalEventType.agenda_preparation):
return game_info.lookup_key(f"council_agenda_{self.db_description.text}_name")
elif self.event_type in (
HistoricalEventType.agenda_launch,
HistoricalEventType.agenda_preparation,
):
return game_info.lookup_key(
f"council_agenda_{self.db_description.text}_name"
)
elif self.event_type in (
HistoricalEventType.gained_trait,
HistoricalEventType.lost_trait,
):
return game_info.lookup_key(self.db_description.text)
elif self.db_description:
return game_info.lookup_key(self.db_description.text)
else:
Expand Down
76 changes: 71 additions & 5 deletions stellarisdashboard/parsing/timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,7 @@ def _add_new_leader(
- 360 * leader_dict.get("age", 0.0)
+ self._random_instance.randint(-15, 15)
)
subclass, leader_traits = self._get_leader_traits(leader_dict)
leader = datamodel.Leader(
country=country_model,
leader_id_in_game=leader_id,
Expand All @@ -1161,6 +1162,8 @@ def _add_new_leader(
date_hired=date_hired,
date_born=date_born,
is_active=True,
subclass=subclass,
leader_traits=leader_traits,
)
self._update_leader_attributes(
leader=leader, leader_dict=leader_dict
Expand Down Expand Up @@ -1197,6 +1200,7 @@ def _update_leader_attributes(self, leader: datamodel.Leader, leader_dict):
level = leader_dict.get("level", -1)
species_id = leader_dict.get("species", -1)
leader_species = self._species_dict.get(species_id)
subclass, leader_traits = self._get_leader_traits(leader_dict)
if leader_species is None:
logger.warning(
f"{self._basic_info.logger_str} Invalid species ID {species_id} for leader {leader_dict}"
Expand All @@ -1205,28 +1209,87 @@ def _update_leader_attributes(self, leader: datamodel.Leader, leader_dict):
leader.first_name != first_name
or leader.second_name != second_name
or leader.leader_class != leader_class
or leader.subclass != subclass
or leader.gender != leader_gender
or leader.species != leader_species
or leader.leader_traits != leader_traits
):
hist_event_kwargs = dict(
country=leader.country,
start_date_days=self._basic_info.date_in_days,
leader=leader,
event_is_known_to_player=leader.country.is_player,
)
if leader.last_level != level:
self._session.add(
datamodel.HistoricalEvent(
**hist_event_kwargs,
event_type=datamodel.HistoricalEventType.level_up,
country=leader.country,
start_date_days=self._basic_info.date_in_days,
leader=leader,
event_is_known_to_player=leader.country.is_player,
db_description=self._get_or_add_shared_description(str(level)),
)
)
if leader.leader_traits != leader_traits:
gained_traits, lost_traits = self._get_gained_lost_traits(
old_traits=leader.leader_traits, new_traits=leader_traits
)
for event_type, trait in itertools.chain(
zip(
itertools.repeat(datamodel.HistoricalEventType.lost_trait),
gained_traits,
),
zip(
itertools.repeat(datamodel.HistoricalEventType.gained_trait),
lost_traits,
),
):
self._session.add(
datamodel.HistoricalEvent(
**hist_event_kwargs,
event_type=event_type,
db_description=self._get_or_add_shared_description(trait),
)
)

leader.last_level = level
leader.first_name = first_name
leader.second_name = second_name
leader.leader_class = leader_class
leader.subclass = subclass
leader.gender = leader_gender
leader.species = leader_species
leader.leader_traits = leader_traits
self._session.add(leader)

def _get_leader_traits(self, leader_dict) -> (str, str):
leader_traits = leader_dict.get("traits", [])
if not isinstance(leader_traits, list):
leader_traits = [leader_traits]
subclass = ""
for trait in leader_traits:
if trait.startswith("subclass"):
subclass = trait
break

traits = ",".join(t for t in sorted(leader_traits) if not t.startswith("subclass"))
return subclass, traits


def _get_gained_lost_traits(self, old_traits: str, new_traits: str):
old_traits = set(old_traits.split(","))
new_traits = set(new_traits.split(","))
gained_traits = old_traits - new_traits
lost_traits = new_traits - old_traits

# Only consider a trait "lost" if it is not replaced by a direct upgrade, e.g.
# trait_ruler_charismatic -> trait_ruler_charismatic_2
lost_traits = {
lt
for lt in lost_traits
if not any(gt.startswith(lt.rstrip("_0123456789")) for gt in gained_traits)
}

return gained_traits, lost_traits


class PlanetProcessor(AbstractGamestateDataProcessor):
ID = "planet_models"
Expand Down Expand Up @@ -1472,7 +1535,10 @@ def extract_data_from_gamestate(self, dependencies):

for country_id, country_model in self._countries_dict.items():
country_dict = self._gamestate_dict["country"][country_id]
country_sectors = country_dict.get("sectors", {}).get("owned", [])
country_sector_dict = country_dict.get("sectors")
if not isinstance(country_sector_dict, dict):
continue
country_sectors = country_sector_dict.get("owned", [])
unprocessed_systems = set(
s.system_id_in_game for s in self._systems_by_owner.get(country_id, [])
)
Expand Down

0 comments on commit cd7a845

Please sign in to comment.