diff --git a/MekHQ/resources/mekhq/resources/Campaign.properties b/MekHQ/resources/mekhq/resources/Campaign.properties index e48ef36fce..fc11a9cd6d 100644 --- a/MekHQ/resources/mekhq/resources/Campaign.properties +++ b/MekHQ/resources/mekhq/resources/Campaign.properties @@ -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. diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 953d2055bd..98b73033b1 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -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. diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index a72aea8008..ff1a843a06 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -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; @@ -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; @@ -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 @@ -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) { @@ -3787,6 +3791,34 @@ && getCampaignOptions().getRandomDependentMethod().isAgainstTheBot() processNewDayATBScenarios(); } + /** + * Processes the new day for all active personnel. + *

+ * This method loops through all active personnel and performs the necessary actions + * for each person for a new day. + *

+ * The following tasks are performed for each person: + *

+ *

+ * 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 @@ -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); } } @@ -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)); } } diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index ba53e682e9..18439cff29 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -291,6 +291,7 @@ public static String getTransitUnitName(final int unit) { // Anniversaries private boolean announceBirthdays; + private boolean announceRecruitmentAnniversaries; private boolean announceOfficersOnly; private boolean announceChildBirthdays; @@ -858,6 +859,7 @@ public CampaignOptions() { // Anniversaries setAnnounceBirthdays(true); + setAnnounceRecruitmentAnniversaries(true); setAnnounceOfficersOnly(true); setAnnounceChildBirthdays(true); @@ -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; } @@ -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 @@ -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")) { diff --git a/MekHQ/src/mekhq/campaign/MercRosterAccess.java b/MekHQ/src/mekhq/campaign/MercRosterAccess.java index ed403a0837..0f87ba64ab 100644 --- a/MekHQ/src/mekhq/campaign/MercRosterAccess.java +++ b/MekHQ/src/mekhq/campaign/MercRosterAccess.java @@ -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; @@ -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 { private static final MMLogger logger = MMLogger.create(MercRosterAccess.class); @@ -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) { @@ -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 @@ -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(); } diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java index 22e53a1ec3..acf05c9aa1 100644 --- a/MekHQ/src/mekhq/campaign/personnel/Person.java +++ b/MekHQ/src/mekhq/campaign/personnel/Person.java @@ -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; @@ -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; } @@ -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; } @@ -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() { @@ -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()); diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java index 4312bebd85..7ee60f39dc 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java @@ -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)); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 536434303c..3f5ef99913 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -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; diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 7bcf080005..7d2794d92e 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -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"), @@ -441,7 +441,7 @@ public List 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(); diff --git a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java index bf98e5bcc3..599bfe6201 100644 --- a/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java +++ b/MekHQ/src/mekhq/campaign/storyarc/storypoint/CreateCharacterStoryPoint.java @@ -20,14 +20,6 @@ */ package mekhq.campaign.storyarc.storypoint; -import java.io.PrintWriter; -import java.text.ParseException; -import java.util.Enumeration; -import java.util.UUID; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.common.options.IOption; import megamek.common.options.IOptionGroup; @@ -54,6 +46,13 @@ import mekhq.gui.dialog.CreateCharacterDialog; import mekhq.gui.dialog.CreateCharacterDialog.NameRestrictions; import mekhq.utilities.MHQXMLUtility; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintWriter; +import java.text.ParseException; +import java.util.Enumeration; +import java.util.UUID; /** * This StoryPoint opens a {@link CreateCharacterDialog CreateCharacterDialog} @@ -180,7 +179,7 @@ public Person createPerson() { AbstractSkillGenerator skillGenerator = new DefaultSkillGenerator(skillPrefs); skillGenerator.generateSkills(getCampaign(), p, SkillType.EXP_ULTRA_GREEN); - p.setBirthday(getCampaign().getLocalDate().minusYears(age)); + p.setDateOfBirth(getCampaign().getLocalDate().minusYears(age)); // set education EducationController.setInitialEducation(campaign, p); diff --git a/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java b/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java index 44a9af261b..b966ec467e 100644 --- a/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java @@ -157,7 +157,7 @@ public CreateCharacterDialog(JFrame parent, boolean modal, Person person, Campai } private void initializePilotAndOptions () { - birthdate = person.getBirthday(); + birthdate = person.getDateOfBirth(); selectedPhenotype = person.getPhenotype(); options = person.getOptions(); portrait = person.getPortrait(); @@ -932,7 +932,7 @@ private DefaultComboBoxModel getFactionsComboBoxModel() { int endYear = person.getRecruitment() != null ? Math.min(person.getRecruitment().getYear(), year) : year; - if (faction.validBetween(person.getBirthday().getYear(), endYear)) { + if (faction.validBetween(person.getDateOfBirth().getYear(), endYear)) { factionsModel.addElement(faction); } } @@ -959,8 +959,8 @@ private DefaultComboBoxModel getPlanetarySystemsComboBoxModel(F DefaultComboBoxModel model = new DefaultComboBoxModel<>(); List orderedSystems = campaign.getSystems().stream() - .filter(a -> a.getFactionSet(person.getBirthday()).contains(faction)) - .sorted(Comparator.comparing(a -> a.getName(person.getBirthday()))) + .filter(a -> a.getFactionSet(person.getDateOfBirth()).contains(faction)) + .sorted(Comparator.comparing(a -> a.getName(person.getDateOfBirth()))) .toList(); for (PlanetarySystem system : orderedSystems) { model.addElement(system); @@ -1451,7 +1451,7 @@ private void done() { if (choiceGender.getSelectedItem() != null) { person.setGender((Gender) choiceGender.getSelectedItem()); } - person.setBirthday(birthdate); + person.setDateOfBirth(birthdate); person.setOriginFaction((Faction) choiceFaction.getSelectedItem()); if (choiceSystem.getSelectedItem() != null && choicePlanet.getSelectedItem() != null) { person.setOriginPlanet((Planet)choicePlanet.getSelectedItem()); diff --git a/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java b/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java index 80ecefb149..413261071a 100644 --- a/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java @@ -18,25 +18,6 @@ */ package mekhq.gui.dialog; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.time.LocalDate; -import java.time.Period; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.ResourceBundle; - -import javax.swing.*; - import megamek.client.generator.RandomCallsignGenerator; import megamek.client.generator.RandomNameGenerator; import megamek.client.ui.baseComponents.MMComboBox; @@ -55,20 +36,11 @@ import megamek.logging.MMLogger; import mekhq.MekHQ; import mekhq.campaign.Campaign; -import mekhq.campaign.personnel.Bloodname; -import mekhq.campaign.personnel.Person; -import mekhq.campaign.personnel.PersonnelOptions; -import mekhq.campaign.personnel.SkillType; -import mekhq.campaign.personnel.SpecialAbility; +import mekhq.campaign.personnel.*; import mekhq.campaign.personnel.enums.Phenotype; import mekhq.campaign.personnel.enums.education.EducationLevel; import mekhq.campaign.personnel.randomEvents.PersonalityController; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Aggression; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Ambition; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Greed; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Intelligence; -import mekhq.campaign.personnel.randomEvents.enums.personalities.PersonalityQuirk; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Social; +import mekhq.campaign.personnel.randomEvents.enums.personalities.*; import mekhq.campaign.unit.Unit; import mekhq.campaign.universe.Faction; import mekhq.campaign.universe.Faction.Tag; @@ -82,6 +54,14 @@ import mekhq.gui.control.EditScenarioLogControl; import mekhq.gui.utilities.MarkdownEditorPanel; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.time.LocalDate; +import java.time.Period; +import java.util.List; +import java.util.*; + /** * This dialog is used to both hire new pilots and to edit existing ones * @@ -165,7 +145,7 @@ public CustomizePersonDialog(JFrame parent, boolean modal, Person person, Campai } private void initializePilotAndOptions() { - birthdate = person.getBirthday(); + birthdate = person.getDateOfBirth(); if (person.getRecruitment() != null) { recruitment = person.getRecruitment(); } @@ -1105,7 +1085,7 @@ private DefaultComboBoxModel getFactionsComboBoxModel() { int endYear = person.getRecruitment() != null ? Math.min(person.getRecruitment().getYear(), year) : year; - if (faction.validBetween(person.getBirthday().getYear(), endYear)) { + if (faction.validBetween(person.getDateOfBirth().getYear(), endYear)) { factionsModel.addElement(faction); } } @@ -1130,8 +1110,8 @@ private DefaultComboBoxModel getPlanetarySystemsComboBoxModel(F DefaultComboBoxModel model = new DefaultComboBoxModel<>(); List orderedSystems = campaign.getSystems().stream() - .filter(a -> a.getFactionSet(person.getBirthday()).contains(faction)) - .sorted(Comparator.comparing(a -> a.getName(person.getBirthday()))) + .filter(a -> a.getFactionSet(person.getDateOfBirth()).contains(faction)) + .sorted(Comparator.comparing(a -> a.getName(person.getDateOfBirth()))) .toList(); for (PlanetarySystem system : orderedSystems) { model.addElement(system); @@ -1194,7 +1174,7 @@ private void btnOkActionPerformed(ActionEvent evt) { person.setGender((Gender) choiceGender.getSelectedItem()); } - person.setBirthday(birthdate); + person.setDateOfBirth(birthdate); person.setRecruitment(recruitment); person.setLastRankChangeDate(lastRankChangeDate); person.setRetirement(retirement); diff --git a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java index 083d5309d1..5a3730a9aa 100644 --- a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java @@ -20,43 +20,14 @@ */ package mekhq.gui.dialog; -import static mekhq.campaign.personnel.backgrounds.BackgroundsController.randomMercenaryCompanyNameGenerator; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.List; -import java.util.Objects; -import java.util.StringJoiner; -import java.util.function.Predicate; - -import javax.swing.*; -import javax.swing.GroupLayout.Alignment; - import megamek.client.generator.RandomCallsignGenerator; import megamek.client.generator.RandomNameGenerator; import megamek.client.ui.baseComponents.MMButton; import megamek.client.ui.baseComponents.MMComboBox; import megamek.client.ui.dialogs.EntityReadoutDialog; -import megamek.client.ui.preferences.JComboBoxPreference; -import megamek.client.ui.preferences.JIntNumberSpinnerPreference; -import megamek.client.ui.preferences.JTabbedPanePreference; -import megamek.client.ui.preferences.JTextFieldPreference; -import megamek.client.ui.preferences.PreferencesNode; +import megamek.client.ui.preferences.*; import megamek.codeUtilities.StringUtility; -import megamek.common.Compute; -import megamek.common.Entity; -import megamek.common.EntityWeightClass; -import megamek.common.MekFileParser; -import megamek.common.MekSummary; -import megamek.common.Messages; -import megamek.common.UnitType; +import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; import megamek.logging.MMLogger; @@ -78,6 +49,19 @@ import mekhq.gui.displayWrappers.FactionDisplay; import mekhq.gui.panels.LayeredForceIconCreationPanel; +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.function.Predicate; + +import static mekhq.campaign.personnel.backgrounds.BackgroundsController.randomMercenaryCompanyNameGenerator; + public class GMToolsDialog extends AbstractMHQDialog { private static final MMLogger logger = MMLogger.create(GMToolsDialog.class); @@ -708,7 +692,7 @@ private JPanel createRATPanel() { final DefaultComboBoxModel factionModel = new DefaultComboBoxModel<>(); factionModel.addAll(FactionDisplay.getSortedValidFactionDisplays(Factions.getInstance().getFactions(), - (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getBirthday())); + (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getDateOfBirth())); setComboRATFaction(new MMComboBox<>("comboRATFaction", factionModel)); getComboRATFaction().setSelectedIndex(0); gbc.gridx++; @@ -854,7 +838,7 @@ private JPanel createNamePanel() { final DefaultComboBoxModel factionModel = new DefaultComboBoxModel<>(); factionModel.addAll(FactionDisplay.getSortedValidFactionDisplays(Factions.getInstance().getFactions(), - (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getBirthday())); + (getPerson() == null) ? getGUI().getCampaign().getLocalDate() : getPerson().getDateOfBirth())); setComboNameGeneratorFaction(new MMComboBox<>("comboRATFaction", factionModel)); getComboNameGeneratorFaction().setSelectedIndex(0); gbc.gridx++; @@ -1396,7 +1380,7 @@ private void setValuesFromPerson() { getChkClanPersonnel().setSelected(getPerson().isClanPersonnel()); // Now we figure out the person's origin faction - final FactionDisplay faction = new FactionDisplay(getPerson().getOriginFaction(), getPerson().getBirthday()); + final FactionDisplay faction = new FactionDisplay(getPerson().getOriginFaction(), getPerson().getDateOfBirth()); getComboRATFaction().setSelectedItem(faction); getComboNameGeneratorFaction().setSelectedItem(faction); diff --git a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java index 25254f2bc7..9dcfc9fcbd 100644 --- a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java @@ -369,7 +369,7 @@ private void hire(boolean isGmHire) { if (useAge) { if ((age > maxAgeVal) || (age < minAgeVal)) { LocalDate birthDay = earliestBirthDate.plusDays(Compute.randomInt(days)); - person.setBirthday(birthDay); + person.setDateOfBirth(birthDay); age = person.getAge(today); } diff --git a/MekHQ/src/mekhq/gui/dialog/MedicalViewDialog.java b/MekHQ/src/mekhq/gui/dialog/MedicalViewDialog.java index ae220ea98e..75e916c7ef 100644 --- a/MekHQ/src/mekhq/gui/dialog/MedicalViewDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/MedicalViewDialog.java @@ -18,34 +18,14 @@ */ package mekhq.gui.dialog; -import java.awt.*; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.time.Period; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.ResourceBundle; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import javax.swing.*; - import megamek.client.ui.preferences.JWindowPreference; import megamek.client.ui.preferences.PreferencesNode; import megamek.logging.MMLogger; import mekhq.MekHQ; import mekhq.Utilities; import mekhq.campaign.Campaign; -import mekhq.campaign.ExtraData; +import mekhq.campaign.ExtraData.Key; +import mekhq.campaign.ExtraData.StringKey; import mekhq.campaign.force.Force; import mekhq.campaign.log.LogEntry; import mekhq.campaign.log.LogEntryType; @@ -56,15 +36,31 @@ import mekhq.campaign.personnel.enums.InjuryLevel; import mekhq.gui.view.Paperdoll; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.time.Period; +import java.util.List; +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + public class MedicalViewDialog extends JDialog { private static final MMLogger logger = MMLogger.create(MedicalViewDialog.class); private static final String MENU_CMD_SEPARATOR = ","; - private static final ExtraData.Key DOCTOR_NOTES = new ExtraData.StringKey("doctor_notes"); + private static final Key DOCTOR_NOTES = new StringKey("doctor_notes"); // TODO: Custom paper dolls @SuppressWarnings("unused") - private static final ExtraData.Key PAPERDOLL = new ExtraData.StringKey("paperdoll_xml_file"); + private static final Key PAPERDOLL = new StringKey("paperdoll_xml_file"); private final Campaign campaign; private final Person person; @@ -324,7 +320,7 @@ private JPanel genBaseData(Campaign c, Person p) { surname = p.getBloodname(); } - Period age = Period.between(p.getBirthday(), c.getLocalDate()); + Period age = Period.between(p.getDateOfBirth(), c.getLocalDate()); String phenotype = p.getPhenotype().isNone() ? resourceMap.getString("baselinePhenotype.text") : p.getPhenotype().toString(); @@ -343,7 +339,7 @@ private JPanel genBaseData(Campaign c, Person p) { panel.add(genWrittenPanel(givenName)); panel.add(genLabel(resourceMap.getString("birthDate.text"))); panel.add(genLabel(resourceMap.getString("age.text"))); - panel.add(genWrittenPanel(MekHQ.getMHQOptions().getDisplayFormattedDate(p.getBirthday()))); + panel.add(genWrittenPanel(MekHQ.getMHQOptions().getDisplayFormattedDate(p.getDateOfBirth()))); panel.add(genWrittenPanel(String.format(resourceMap.getString("age.format"), age.getYears(), age.getMonths()))); panel.add(genLabel(resourceMap.getString("gender.text"))); panel.add(genLabel(resourceMap.getString("phenotype.text"))); @@ -373,7 +369,7 @@ private JPanel genMedicalHistory(Campaign c, Person p) { Collectors.groupingBy(entry -> MekHQ.getMHQOptions().getDisplayFormattedDate(entry.getDate()))); groupedEntries.entrySet().stream() .filter(e -> !e.getValue().isEmpty()) - .sorted(Map.Entry.comparingByKey()) + .sorted(Entry.comparingByKey()) .forEachOrdered(e -> { if (e.getValue().size() > 1) { panel.add(genWrittenText(e.getKey())); @@ -433,7 +429,7 @@ private Stream maxInjuryLevelLocationStream(Person p) { .forEach(bl -> levelMap.put(bl, getMaxInjuryLevel(p, bl))); return levelMap.entrySet().stream() .sorted((entry1, entry2) -> Integer.compare(entry2.getValue().ordinal(), entry1.getValue().ordinal())) - .map(Map.Entry::getKey); + .map(Entry::getKey); } private JPanel fillInjuries(JPanel panel, Campaign c, Person p) { diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java index 3d7a673fb9..8b42f7fd2c 100644 --- a/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java +++ b/MekHQ/src/mekhq/gui/enums/PersonnelTableModelColumn.java @@ -18,14 +18,6 @@ */ package mekhq.gui.enums; -import java.util.Comparator; -import java.util.ResourceBundle; -import java.util.stream.Collectors; - -import javax.swing.JTable; -import javax.swing.SortOrder; -import javax.swing.SwingConstants; - import megamek.codeUtilities.StringUtility; import megamek.common.Entity; import megamek.common.Jumpship; @@ -41,19 +33,15 @@ import mekhq.campaign.personnel.PersonnelOptions; import mekhq.campaign.personnel.SkillType; import mekhq.campaign.personnel.enums.GenderDescriptors; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Aggression; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Ambition; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Greed; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Intelligence; -import mekhq.campaign.personnel.randomEvents.enums.personalities.Social; +import mekhq.campaign.personnel.randomEvents.enums.personalities.*; import mekhq.campaign.unit.Unit; import mekhq.campaign.universe.Planet; -import mekhq.gui.sorter.BonusSorter; -import mekhq.gui.sorter.DateStringComparator; -import mekhq.gui.sorter.FormattedNumberSorter; -import mekhq.gui.sorter.IntegerStringSorter; -import mekhq.gui.sorter.LevelSorter; -import mekhq.gui.sorter.PersonRankStringSorter; +import mekhq.gui.sorter.*; + +import javax.swing.*; +import java.util.Comparator; +import java.util.ResourceBundle; +import java.util.stream.Collectors; public enum PersonnelTableModelColumn { // region Enum Declarations @@ -495,7 +483,7 @@ public String getCellValue(final Campaign campaign, final PersonnelMarket person return person.getCallsign(); case AGE: case BIRTHDAY: - return MekHQ.getMHQOptions().getDisplayFormattedDate(person.getBirthday()); + return MekHQ.getMHQOptions().getDisplayFormattedDate(person.getDateOfBirth()); case PERSONNEL_STATUS: return person.getStatus().toString(); case GENDER: diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index d3a2330a14..a25e74b287 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -450,6 +450,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { // Anniversaries private final JPanel anniversaryPanel = new JPanel(); private JCheckBox chkAnnounceBirthdays; + private JCheckBox chkAnnounceRecruitmentAnniversaries; private JCheckBox chkAnnounceOfficersOnly; private JCheckBox chkAnnounceChildBirthdays; @@ -5316,10 +5317,13 @@ private JPanel createAnniversaryPanel() { chkAnnounceBirthdays.addActionListener(evt -> { final boolean isEnabled = chkAnnounceBirthdays.isSelected(); - chkAnnounceOfficersOnly.setEnabled(isEnabled); chkAnnounceChildBirthdays.setEnabled(isEnabled); }); + chkAnnounceRecruitmentAnniversaries = new JCheckBox(resources.getString("chkAnnounceRecruitmentAnniversaries.text")); + chkAnnounceRecruitmentAnniversaries.setToolTipText(resources.getString("chkAnnounceRecruitmentAnniversaries.toolTipText")); + chkAnnounceRecruitmentAnniversaries.setName("chkAnnounceRecruitmentAnniversaries"); + chkAnnounceOfficersOnly = new JCheckBox(resources.getString("chkAnnounceOfficersOnly.text")); chkAnnounceOfficersOnly.setToolTipText(resources.getString("chkAnnounceOfficersOnly.toolTipText")); chkAnnounceOfficersOnly.setName("chkAnnounceOfficersOnly"); @@ -5342,12 +5346,14 @@ private JPanel createAnniversaryPanel() { layout.setVerticalGroup( layout.createSequentialGroup() .addComponent(chkAnnounceBirthdays) + .addComponent(chkAnnounceRecruitmentAnniversaries) .addComponent(chkAnnounceOfficersOnly) .addComponent(chkAnnounceChildBirthdays)); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addComponent(chkAnnounceBirthdays) + .addComponent(chkAnnounceRecruitmentAnniversaries) .addComponent(chkAnnounceOfficersOnly) .addComponent(chkAnnounceChildBirthdays)); @@ -8643,6 +8649,7 @@ public void setOptions(@Nullable CampaignOptions options, // Anniversaries chkAnnounceBirthdays.setSelected(options.isAnnounceBirthdays()); + chkAnnounceRecruitmentAnniversaries.setSelected(options.isAnnounceRecruitmentAnniversaries()); chkAnnounceOfficersOnly.setSelected(options.isAnnounceOfficersOnly()); chkAnnounceChildBirthdays.setSelected(options.isAnnounceChildBirthdays()); @@ -9387,6 +9394,7 @@ public void updateOptions() { // Anniversaries options.setAnnounceBirthdays(chkAnnounceBirthdays.isSelected()); + options.setAnnounceRecruitmentAnniversaries(chkAnnounceRecruitmentAnniversaries.isSelected()); options.setAnnounceOfficersOnly(chkAnnounceOfficersOnly.isSelected()); options.setAnnounceChildBirthdays(chkAnnounceChildBirthdays.isSelected());