Skip to content

Commit

Permalink
Merge pull request #4886 from IllianiCBT/personnel_birthdays
Browse files Browse the repository at this point in the history
Fixed Birthday Anniversary Events, Added Employment Anniversary Events
  • Loading branch information
IllianiCBT authored Sep 26, 2024
2 parents 42c6bd4 + bc787b4 commit 0bcab47
Show file tree
Hide file tree
Showing 17 changed files with 215 additions and 175 deletions.
3 changes: 2 additions & 1 deletion MekHQ/resources/mekhq/resources/Campaign.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ LayeredForceIconLayer.LOGO.text=Logos
LayeredForceIconLayer.LOGO.toolTipText=This tab contains canon faction logos that can be added to the center of a force icon.

#### Anniversaries
anniversaryBirthday.text=%s is %s today!
anniversaryBirthday.text=%s is %s%s%s today!
anniversaryRecruitment.text=%s celebrates %s%s%s years with %s!

#### Personnel Removal
personnelRemoval.text=Old personnel records have been tidied away.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,10 @@ chkUseRemovalExemptRetirees.toolTipText=Data from retired personnel is exempt fr
anniversaryPanel.title=Anniversaries
chkAnnounceBirthdays.text=Announce Birthdays
chkAnnounceBirthdays.toolTipText=A daily report notification will occur whenever someone celebrates their birthday.
chkAnnounceRecruitmentAnniversaries.text=Announce Recruitment Anniversaries
chkAnnounceRecruitmentAnniversaries.toolTipText=A daily report notification will occur whenever someone celebrates a recruitment anniversary.
chkAnnounceOfficersOnly.text=Officers Only
chkAnnounceOfficersOnly.toolTipText=Only report officer birthdays.
chkAnnounceOfficersOnly.toolTipText=Only report officer anniversaries.
chkAnnounceChildBirthdays.text=Coming of Age Override
chkAnnounceChildBirthdays.toolTipText=If enabled, 18th birthdays will always be announced. Enabling this option will override any other settings.

Expand Down
71 changes: 61 additions & 10 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@
import mekhq.campaign.log.HistoricalLogEntry;
import mekhq.campaign.log.LogEntry;
import mekhq.campaign.log.ServiceLogger;
import mekhq.campaign.market.*;
import mekhq.campaign.market.PartsStore;
import mekhq.campaign.market.PersonnelMarket;
import mekhq.campaign.market.ShoppingList;
import mekhq.campaign.market.contractMarket.AbstractContractMarket;
import mekhq.campaign.market.contractMarket.AtbMonthlyContractMarket;
import mekhq.campaign.market.unitMarket.AbstractUnitMarket;
Expand Down Expand Up @@ -125,6 +127,7 @@
import mekhq.service.IAutosaveService;
import mekhq.service.mrms.MRMSService;
import mekhq.utilities.MHQXMLUtility;
import mekhq.utilities.ReportingUtilities;

import javax.swing.*;
import java.io.PrintWriter;
Expand All @@ -141,6 +144,7 @@
import static mekhq.campaign.personnel.education.EducationController.getAcademy;
import static mekhq.campaign.personnel.turnoverAndRetention.RetirementDefectionTracker.Payout.isBreakingContract;
import static mekhq.campaign.unit.Unit.SITE_FACILITY_MAINTENANCE;
import static mekhq.utilities.ReportingUtilities.CLOSING_SPAN_TAG;

/**
* The main campaign class, keeps track of teams and units
Expand Down Expand Up @@ -1663,7 +1667,7 @@ public boolean recruitPerson(Person p, PrisonerStatus prisonerStatus, boolean gm
private void simulateRelationshipHistory(Person person) {
// how many weeks should the simulation run?
LocalDate localDate = getLocalDate();
long weeksBetween = ChronoUnit.WEEKS.between(person.getBirthday().plusYears(18), localDate);
long weeksBetween = ChronoUnit.WEEKS.between(person.getDateOfBirth().plusYears(18), localDate);

// this means there is nothing to simulate
if (weeksBetween == 0) {
Expand Down Expand Up @@ -3787,6 +3791,34 @@ && getCampaignOptions().getRandomDependentMethod().isAgainstTheBot()
processNewDayATBScenarios();
}

/**
* Processes the new day for all active personnel.
* <p>
* This method loops through all active personnel and performs the necessary actions
* for each person for a new day.
* <p>
* The following tasks are performed for each person:
* <ul>
* <li>Death - If the person has died, skip processing further for the dead person.</li>
* <li>Marriage - Process any marriage-related actions.</li>
* <li>Reset minutes left for the person.</li>
* <li>Reset acquisitions made to 0.</li>
* <li>Healing - If the person needs healing and advanced medical is not used,
* decrement the days to wait for healing and heal naturally or with a doctor.</li>
* <li>Advanced Medical - If advanced medical is used, resolve the daily healing for the person.</li>
* <li>Reset current edge points for support personnel on Mondays.</li>
* <li>Idle XP - If idle XP is enabled and it's the first day of the month,
* check if the person qualifies for idle XP and award them if they do.</li>
* <li>Divorce - Process any divorce-related actions.</li>
* <li>Procreation - Process any procreation-related actions.</li>
* <li>Anniversaries - Check if it's the person's birthday or 18th birthday
* and announce it if needed.</li>
* <li>Auto Awards - If it's the first day of the month, calculate the auto award
* support points based on the person's roles and experience level.</li>
* </ul>
* <p>
* Note: This method uses several other methods to perform the specific actions for each task.
*/
public void processNewDayPersonnel() {
// This MUST use getActivePersonnel as we only want to process active personnel, and
// furthermore, this allows us to add and remove personnel without issue
Expand Down Expand Up @@ -3865,9 +3897,9 @@ public void processNewDayPersonnel() {

if ((person.getStatus().isOnMaternityLeave()) && (!children.isEmpty())) {

children.sort(Comparator.comparing(Person::getBirthday).reversed());
children.sort(Comparator.comparing(Person::getDateOfBirth).reversed());

if (getLocalDate().isAfter(children.get(0).getBirthday().plusDays(41))) {
if (getLocalDate().isAfter(children.get(0).getDateOfBirth().plusDays(41))) {
person.changeStatus(this, getLocalDate(), PersonnelStatus.ACTIVE);
}
}
Expand All @@ -3877,16 +3909,35 @@ public void processNewDayPersonnel() {

// Anniversaries
if ((person.getRank().isOfficer()) || (!getCampaignOptions().isAnnounceOfficersOnly())) {
if ((person.getBirthday().isEqual(getLocalDate())) && (campaignOptions.isAnnounceBirthdays())) {
if ((person.getBirthday(getGameYear()).isEqual(getLocalDate()))
&& (campaignOptions.isAnnounceBirthdays())) {
addReport(String.format(resources.getString("anniversaryBirthday.text"),
person.getHyperlinkedFullTitle(),
ReportingUtilities.spanOpeningWithCustomColor(MekHQ.getMHQOptions().getFontColorPositiveHexColor()),
person.getAge(getLocalDate()),
CLOSING_SPAN_TAG));
}

LocalDate recruitmentDate = person.getRecruitment();
if (recruitmentDate != null) {
LocalDate recruitmentAnniversary = recruitmentDate.withYear(getGameYear());
int yearsOfEmployment = (int) ChronoUnit.YEARS.between(recruitmentDate, currentDay);

if ((recruitmentAnniversary.isEqual(getLocalDate()))
&& (campaignOptions.isAnnounceRecruitmentAnniversaries())) {
addReport(String.format(resources.getString("anniversaryRecruitment.text"),
person.getHyperlinkedFullTitle(),
person.getAge(getLocalDate())));
ReportingUtilities.spanOpeningWithCustomColor(MekHQ.getMHQOptions().getFontColorPositiveHexColor()),
yearsOfEmployment, CLOSING_SPAN_TAG, name));
}
}
} else if ((person.getAge(getLocalDate()) == 18) && (campaignOptions.isAnnounceChildBirthdays()) ){
if (person.getBirthday().isEqual(getLocalDate())) {
} else if ((person.getAge(getLocalDate()) == 18) && (campaignOptions.isAnnounceChildBirthdays())) {
if (person.getBirthday(getGameYear()).isEqual(getLocalDate())) {
addReport(String.format(resources.getString("anniversaryBirthday.text"),
person.getHyperlinkedFullTitle(),
18));
person.getHyperlinkedFullTitle(),
ReportingUtilities.spanOpeningWithCustomColor(MekHQ.getMHQOptions().getFontColorPositiveHexColor()),
person.getAge(getLocalDate()),
CLOSING_SPAN_TAG));
}
}

Expand Down
24 changes: 24 additions & 0 deletions MekHQ/src/mekhq/campaign/CampaignOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ public static String getTransitUnitName(final int unit) {

// Anniversaries
private boolean announceBirthdays;
private boolean announceRecruitmentAnniversaries;
private boolean announceOfficersOnly;
private boolean announceChildBirthdays;

Expand Down Expand Up @@ -858,6 +859,7 @@ public CampaignOptions() {

// Anniversaries
setAnnounceBirthdays(true);
setAnnounceRecruitmentAnniversaries(true);
setAnnounceOfficersOnly(true);
setAnnounceChildBirthdays(true);

Expand Down Expand Up @@ -2221,6 +2223,25 @@ public void setAnnounceBirthdays(final boolean announceBirthdays) {
this.announceBirthdays = announceBirthdays;
}

/**
* Checks if recruitment anniversaries should be announced.
*
* @return {@code true} if recruitment anniversaries should be announced, {@code false} otherwise.
*/
public boolean isAnnounceRecruitmentAnniversaries() {
return announceRecruitmentAnniversaries;
}

/**
* Set whether to announce recruitment anniversaries.
*
* @param announceRecruitmentAnniversaries {@code true} to announce recruitment anniversaries,
* {@code false} otherwise
*/
public void setAnnounceRecruitmentAnniversaries(final boolean announceRecruitmentAnniversaries) {
this.announceRecruitmentAnniversaries = announceRecruitmentAnniversaries;
}

public boolean isAnnounceOfficersOnly() {
return announceOfficersOnly;
}
Expand Down Expand Up @@ -4923,6 +4944,7 @@ public void writeToXml(final PrintWriter pw, int indent) {

// region Announcements
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "announceBirthdays", isAnnounceBirthdays());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "announceRecruitmentAnniversaries", isAnnounceRecruitmentAnniversaries());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "announceOfficersOnly", isAnnounceOfficersOnly());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "announceChildBirthdays", isAnnounceChildBirthdays());
// endregion Announcements
Expand Down Expand Up @@ -5631,6 +5653,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve
// region anniversaries
} else if (wn2.getNodeName().equalsIgnoreCase("announceBirthdays")) {
retVal.setAnnounceBirthdays(Boolean.parseBoolean(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("announceRecruitmentAnniversaries")) {
retVal.setAnnounceRecruitmentAnniversaries(Boolean.parseBoolean(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("announceOfficersOnly")) {
retVal.setAnnounceOfficersOnly(Boolean.parseBoolean(wn2.getTextContent().trim()));
} else if (wn2.getNodeName().equalsIgnoreCase("announceChildBirthdays")) {
Expand Down
32 changes: 12 additions & 20 deletions MekHQ/src/mekhq/campaign/MercRosterAccess.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,6 @@
*/
package mekhq.campaign;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

import javax.swing.SwingWorker;

import megamek.common.UnitType;
import megamek.logging.MMLogger;
import mekhq.campaign.force.Force;
Expand All @@ -44,6 +29,13 @@
import mekhq.campaign.personnel.ranks.Rank;
import mekhq.campaign.unit.Unit;

import javax.swing.*;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

public class MercRosterAccess extends SwingWorker<Void, Void> {
private static final MMLogger logger = MMLogger.create(MercRosterAccess.class);

Expand Down Expand Up @@ -91,7 +83,7 @@ public void connect() throws SQLException {
conProperties.put("password", passwd);
try {
Class.forName("com.mysql.jdbc.Driver");
connect = DriverManager.getConnection("jdbc:mysql://" + hostname + ":" + port + "/" + table, conProperties);
connect = DriverManager.getConnection("jdbc:mysql://" + hostname + ':' + port + '/' + table, conProperties);
} catch (SQLException e) {
throw e;
} catch (ClassNotFoundException e) {
Expand Down Expand Up @@ -562,10 +554,10 @@ private void writePersonnelData() {
preparedStatement.setInt(6, forceId);
preparedStatement.setInt(7, 1);
// TODO: get joining date right
preparedStatement.setDate(8, Date.valueOf(p.getBirthday()));
preparedStatement.setDate(8, Date.valueOf(p.getDateOfBirth()));
// TODO: combine personnel log with biography
preparedStatement.setString(9, p.getBiography());
preparedStatement.setDate(10, Date.valueOf(p.getBirthday()));
preparedStatement.setDate(10, Date.valueOf(p.getDateOfBirth()));
preparedStatement.setString(11, p.getId().toString());
if (preparedStatement.executeUpdate() < 1) {
// no prior record so insert
Expand All @@ -578,9 +570,9 @@ private void writePersonnelData() {
preparedStatement.setString(5, p.getStatus().toString());
preparedStatement.setInt(6, forceId);
preparedStatement.setInt(7, 1);
preparedStatement.setDate(8, Date.valueOf(p.getBirthday()));
preparedStatement.setDate(8, Date.valueOf(p.getDateOfBirth()));
preparedStatement.setString(9, p.getBiography());
preparedStatement.setDate(10, Date.valueOf(p.getBirthday()));
preparedStatement.setDate(10, Date.valueOf(p.getDateOfBirth()));
preparedStatement.setString(11, p.getId().toString());
preparedStatement.executeUpdate();
}
Expand Down
25 changes: 20 additions & 5 deletions MekHQ/src/mekhq/campaign/personnel/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public Person(final String preNominal, final String givenName, final String surn
secondaryRole = PersonnelRole.NONE;
primaryDesignator = ROMDesignation.NONE;
secondaryDesignator = ROMDesignation.NONE;
setBirthday(LocalDate.now());
setDateOfBirth(LocalDate.now());

originFaction = Factions.getInstance().getFaction(factionCode);
originPlanet = null;
Expand Down Expand Up @@ -1337,7 +1337,12 @@ public Gender getGender() {
return gender;
}

public void setBirthday(final LocalDate birthday) {
/**
* Sets the date of birth (the date they are born) for the person.
*
* @param birthday the person's new date of birth
*/
public void setDateOfBirth(final LocalDate birthday) {
this.birthday = birthday;
}

Expand All @@ -1346,10 +1351,20 @@ public void setBirthday(final LocalDate birthday) {
*
* @return a LocalDate representing the person's date of birth
*/
public LocalDate getBirthday() {
public LocalDate getDateOfBirth() {
return birthday;
}

/**
* Retrieves the birthday for a person, with the year set to the same as the provided year.
*
* @param currentYear the current in-game year
* @return the birthday with the year updated to match the provided year
*/
public LocalDate getBirthday(int currentYear) {
return birthday.withYear(currentYear);
}

public @Nullable LocalDate getDateOfDeath() {
return dateOfDeath;
}
Expand All @@ -1365,7 +1380,7 @@ public int getAge(LocalDate today) {
today = getDateOfDeath();
}

return Math.toIntExact(ChronoUnit.YEARS.between(getBirthday(), today));
return Math.toIntExact(ChronoUnit.YEARS.between(getDateOfBirth(), today));
}

public @Nullable LocalDate getJoinedCampaign() {
Expand Down Expand Up @@ -2048,7 +2063,7 @@ public void writeToXML(final PrintWriter pw, int indent, final Campaign campaign
if (overtimeLeft > 0) {
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "overtimeLeft", overtimeLeft);
}
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "birthday", getBirthday());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "birthday", getDateOfBirth());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "deathday", getDateOfDeath());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "recruitment", getRecruitment());
MHQXMLUtility.writeSimpleXMLTag(pw, indent, "joinedCampaign", getJoinedCampaign());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,6 @@ protected void generateBirthday(Campaign campaign, Person person, int expLvl, bo
int nDays = birthday.isLeapYear() ? 366 : 365;

int randomDay = Compute.randomInt(nDays) + 1;
person.setBirthday(birthday.withDayOfYear(randomDay));
person.setDateOfBirth(birthday.withDayOfYear(randomDay));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -389,11 +389,11 @@ Person createExternalSpouse(final Campaign campaign, final LocalDate today, fina
if (externalSpouseAge < externalSpouseMinAge) {
int difference = externalSpouseMinAge - externalSpouseAge;

externalSpouse.setBirthday(externalSpouse.getBirthday().minusYears(difference));
externalSpouse.setDateOfBirth(externalSpouse.getDateOfBirth().minusYears(difference));
} else if (externalSpouseAge > externalSpouseMaxAge) {
int difference = externalSpouseMaxAge - externalSpouseAge;

externalSpouse.setBirthday(externalSpouse.getBirthday().plusYears(difference));
externalSpouse.setDateOfBirth(externalSpouse.getDateOfBirth().plusYears(difference));
}

return externalSpouse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m
final Person baby = campaign.newDependent(true, Gender.RANDOMIZE);
baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle()
.generateBabySurname(mother, father, baby.getGender()));
baby.setBirthday(today);
baby.setDateOfBirth(today);

// Create reports and log the birth
campaign.addReport(String.format(resources.getString("babyBorn.report"),
Expand Down Expand Up @@ -441,7 +441,7 @@ public List<Person> birthHistoric(final Campaign campaign, final LocalDate today
baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle()
.generateBabySurname(mother, father, baby.getGender()));

baby.setBirthday(today);// Limit skills by age for children and adolescents
baby.setDateOfBirth(today);// Limit skills by age for children and adolescents

baby.removeAllSkills();

Expand Down
Loading

0 comments on commit 0bcab47

Please sign in to comment.