From 70724dbf03c998237fb676d9e11a55e61fd6185d Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sun, 28 Jul 2024 23:55:49 -0500 Subject: [PATCH 01/41] Add randomized relationship history for personnel Implemented a new feature to simulate relationship histories, including marriage, procreation, and divorce for new campaign personnel. Enhanced the settings panel to include options for this new feature. --- .../CampaignOptionsDialog.properties | 15 +- MekHQ/src/mekhq/campaign/Campaign.java | 322 +++++++++++++++--- MekHQ/src/mekhq/campaign/CampaignOptions.java | 133 +++++--- .../mekhq/campaign/mission/AtBContract.java | 9 +- .../personnel/divorce/AbstractDivorce.java | 27 ++ .../personnel/familyTree/Genealogy.java | 8 + .../personnel/marriage/AbstractMarriage.java | 26 ++ .../procreation/AbstractProcreation.java | 128 +++++-- .../adapter/PersonnelTableMouseAdapter.java | 2 +- .../mekhq/gui/panes/CampaignOptionsPane.java | 53 ++- .../procreation/AbstractProcreationTest.java | 16 +- 11 files changed, 595 insertions(+), 144 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 67d212d0d0..253a8b1c01 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -434,12 +434,25 @@ lifePathsPanel.title=Life Paths personnelRandomizationPanel.title=Personnel Randomization chkUseDylansRandomXP.text=Use Dylan's Random XP (Unofficial) chkUseDylansRandomXP.toolTipText=Use Dylan's optional random XP on creation of a new person (20% chance each of 0, 1, 2, 3, and randomized between 1 and 8 XP) + +# Random Histories +randomHistoriesPanel.title=Random Histories chkUseRandomPersonalities.text=Use Random Personalities chkUseRandomPersonalities.toolTipText=Personnel are generated with random personality traits, quirks and intelligence.\
\ -
Intelligence affects a characters ability to graduate from education module academies.\ +
Intelligence affects a character's ability to graduate from education module academies.\
\
While traits and quirks do not currently have a mechanical effect, they will be used by the upcoming Random Events module. +chkUseSimulatedRelationships.text=Simulate Relationship History +chkUseSimulatedRelationships.toolTipText=Personnel are generated with a random relationship history.\ +
\ +
If randomized marriages are enabled the various marriage settings (including chance) will be used to determine whether new personnel have been previously married.\ +
\ +
If randomized procreation is enabled the various procreation settings (including chance) will be used to determine whether new personnel have children traveling with them.\ +
\ +
If randomized divorce is enabled the various divorce settings (including chance) will be used to determine whether any marriages have ended in divorce.\ +
\ +
Any children and current spouses will travel alongside the unit. # Family familyPanel.title=Family (Unofficial) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 31bf6c2bd8..0139a557cf 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -26,7 +26,6 @@ import megamek.client.generator.RandomUnitGenerator; import megamek.client.ui.swing.util.PlayerColour; import megamek.codeUtilities.MathUtility; -import megamek.codeUtilities.ObjectUtility; import megamek.common.*; import megamek.common.AmmoType.Munitions; import megamek.common.annotations.Nullable; @@ -1353,18 +1352,24 @@ public Unit getUnit(UUID id) { //region Personnel //region Person Creation /** - * @return A new {@link Person}, who is a dependent. + * Creates a new {@link Person} instance who is a dependent. + * If {@code baby} is false and the random dependent origin option is enabled, + * the new person will have a random origin. + * + * @param baby a boolean indicating if the person is a baby or not + * @param gender the Gender enum for the person (should normally be Gender.RANDOM) + * @return a new {@link Person} instance who is a dependent */ - public Person newDependent(boolean baby) { + public Person newDependent(boolean baby, Gender gender) { Person person; - if (!baby && getCampaignOptions().getRandomOriginOptions().isRandomizeDependentOrigin()) { - person = newPerson(PersonnelRole.DEPENDENT); - } else { + if ((!baby) && (getCampaignOptions().getRandomOriginOptions().isRandomizeDependentOrigin())) { person = newPerson(PersonnelRole.DEPENDENT, PersonnelRole.NONE, new DefaultFactionSelector(getCampaignOptions().getRandomOriginOptions()), new DefaultPlanetSelector(getCampaignOptions().getRandomOriginOptions()), - Gender.RANDOMIZE); + gender); + } else { + person = newPerson(PersonnelRole.DEPENDENT); } if (person.getAge(getLocalDate()) < 16) { @@ -1554,9 +1559,161 @@ public boolean recruitPerson(Person p, PrisonerStatus prisonerStatus, boolean gm p.setPrisonerStatus(this, prisonerStatus, log); + if (getCampaignOptions().isUseSimulatedRelationships()) { + if ((prisonerStatus.isFree()) && (!p.getPrimaryRole().isDependent())) { + simulateRelationshipHistory(p); + } + } + MekHQ.triggerEvent(new PersonNewEvent(p)); return true; } + + private void simulateRelationshipHistory(Person person) { + // how many weeks should the simulation run? + // we use weeks as we can get similar results to days for 1/7 of the processing debt + LocalDate localDate = getLocalDate(); + long weeksBetween = ChronoUnit.WEEKS.between(person.getBirthday().plusYears(18), localDate); + + LogManager.getLogger().info(weeksBetween); + + // this means there is nothing to simulate + if (weeksBetween == 0) { + return; + } + + // get all the variables needed for the simulation + + // procreation chances + double childChanceRelationship = getCampaignOptions().getRandomProcreationMethod().isPercentage() ? + getCampaignOptions().getPercentageRandomProcreationRelationshipChance() * 7 : 0; + + double childChanceRelationshipless = getCampaignOptions().getRandomProcreationMethod().isPercentage() ? + getCampaignOptions().getPercentageRandomProcreationRelationshiplessChance() * 7 : 0; + + // marriage chances & age range + double relationshipChanceOppositeSex = getCampaignOptions().getRandomMarriageMethod().isPercentage() ? + getCampaignOptions().getPercentageRandomMarriageOppositeSexChance() * 7 : 0; + + double relationshipChanceSameSex = (getCampaignOptions().isUseRandomSameSexMarriages() && getCampaignOptions().getRandomMarriageMethod().isPercentage()) ? + getCampaignOptions().getPercentageRandomMarriageSameSexChance() * 7 : 0; + + int relationshipAgeRange = getCampaignOptions().getRandomMarriageAgeRange(); + + double relationshipChance = Math.max(relationshipChanceOppositeSex, relationshipChanceSameSex); + + // divorce chances + double divorceChanceOppositeSex = getCampaignOptions().getRandomDivorceMethod().isPercentage() ? + getCampaignOptions().getPercentageRandomDivorceOppositeSexChance() * 7 : 0; + + double divorceChanceSameSex = (getCampaignOptions().isUseRandomSameSexDivorce() && getCampaignOptions().getRandomDivorceMethod().isPercentage()) ? + getCampaignOptions().getPercentageRandomDivorceSameSexChance() * 7 : 0; + + double divorceChance = Math.max(divorceChanceOppositeSex, divorceChanceSameSex); + + List children = new ArrayList<>(); + Person currentSpouse = null; + + Gender spouseGender = Gender.FEMALE; + + if (getCampaignOptions().isUseRandomSameSexMarriages()) { + spouseGender = Gender.RANDOMIZE; + } else if (person.getGender().isFemale()) { + spouseGender = Gender.MALE; + } + + // run the simulation + for (long weeksRemaining = weeksBetween; weeksRemaining >= 0; weeksRemaining--) { + if (currentSpouse == null) { + // first, we check for out-of-relationship children + if (person.getGender().isFemale()) { + if (Compute.randomFloat() <= childChanceRelationshipless) { + // if the person was not old enough at potential conception, we skip + if (person.getAge(localDate.minusWeeks(weeksRemaining + 40)) < 18) { + continue; + } + + getProcreation().addPregnancy(this, localDate.minusWeeks(weeksRemaining + 40), person, true); + children.addAll(getProcreation().birthHistoric(this, localDate.minusWeeks(weeksRemaining), person, null)); + } + } + + // then, we check for new relationships + if (Compute.randomFloat() <= relationshipChance) { + currentSpouse = newDependent(false, spouseGender); + + currentSpouse.setOriginFaction(person.getOriginFaction()); + currentSpouse.setOriginPlanet(person.getOriginPlanet()); + + + // this needs to be 19, not 18, due to rounding errors making it possible to have 17-year-old spouses if we put 18 + currentSpouse.setBirthday(localDate.minusYears(Math.max(19, person.getAge(localDate) - Compute.randomInt(relationshipAgeRange)))); + + AbstractMarriage.performMarriageChanges(this, localDate.minusWeeks(weeksRemaining), person, currentSpouse, MergingSurnameStyle.WEIGHTED); + } + } else { + // add age appropriate female personnel to a list + List potentialMothers = new ArrayList<>(); + + if ((person.getGender().isFemale()) && (person.getAge(localDate.minusWeeks(weeksRemaining + 40)) >= 18)) { + potentialMothers.add(person); + } + + if ((currentSpouse.getGender().isFemale()) && (person.getAge(localDate.minusWeeks(weeksRemaining + 40)) >= 18)) { + potentialMothers.add(currentSpouse); + } + + if (!potentialMothers.isEmpty()) { + Collections.shuffle(potentialMothers); + + // pick mother and father, if there are no males in the relationship father remains null + Person potentialMother = potentialMothers.get(0); + Person potentialFather = null; + + if (person.equals(potentialMother)) { + if (currentSpouse.getGender().isMale()) { + potentialFather = currentSpouse; + } + } else { + if (person.getGender().isMale()) { + potentialFather = person; + } + } + + // next we check for out-of-relationship children + if (Compute.randomFloat() <= childChanceRelationship) { + getProcreation().addPregnancy(this, localDate.minusWeeks(weeksRemaining + 40), potentialMother, true); + children.addAll(getProcreation().birthHistoric(this, localDate.minusWeeks(weeksRemaining), potentialMother, potentialFather)); + } + + // here, we check for relationships ending + if (Compute.randomFloat() <= divorceChance) { + getDivorce().divorceHistoric(this, localDate.minusWeeks(weeksRemaining), person); + + // there is a chance the departing spouse will take some children with them + children.removeIf(child -> (Compute.randomInt(1) == 0)); + + currentSpouse = null; + } + } + } + } + + // finally, we add the current spouse (if any) and any remaining children to the unit + if (currentSpouse != null) { + + recruitPerson(currentSpouse, PrisonerStatus.FREE, true, true); + } + + if (!children.isEmpty()) { + for (Person child : children) { + child.setOriginFaction(person.getOriginFaction()); + child.setOriginPlanet(person.getOriginPlanet()); + + recruitPerson(child, PrisonerStatus.FREE, true, true); + } + } + } //endregion Personnel Recruitment //region Bloodnames @@ -1753,6 +1910,17 @@ public List getActivePersonnel() { .collect(Collectors.toList()); } + /** + * Provides a filtered list of personnel including only active Dependents. + * @return a {@link Person} List containing all active personnel + */ + public List getActiveDependents() { + return getPersonnel().stream() + .filter(person -> person.getPrimaryRole().isDependent()) + .filter(person -> person.getStatus().isActive()) + .collect(Collectors.toList()); + } + /** * Provides a filtered list of personnel including only active prisoners. * @return a {@link Person} List containing all active personnel @@ -3347,45 +3515,6 @@ private void processNewDayATB() { .forEach(this::awardTrainingXP); } - // Add or remove dependents - only if one of the two options makes this possible is enabled - if ((getLocalDate().getDayOfYear() == 1) - && getCampaignOptions().getRandomDependentMethod().isAgainstTheBot() - && (getCampaignOptions().isUseRandomDependentRemoval() || getCampaignOptions().isUseRandomDependentAddition())) { - int numPersonnel = 0; - List dependents = new ArrayList<>(); - for (Person p : getActivePersonnel()) { - numPersonnel++; - if (p.getPrimaryRole().isDependent() && p.getGenealogy().isEmpty()) { - dependents.add(p); - } - } - - final int roll = MathUtility.clamp(Compute.d6(2) + getUnitRatingMod() - 2, 2, 12); - - int change = numPersonnel * (roll - 5) / 100; - if (change < 0) { - if (getCampaignOptions().isUseRandomDependentRemoval()) { - while ((change < 0) && !dependents.isEmpty()) { - final Person person = ObjectUtility.getRandomItem(dependents); - addReport(String.format(resources.getString("dependentLeavesForce.text"), - person.getFullTitle())); - removePerson(person, false); - dependents.remove(person); - change++; - } - } - } else { - if (getCampaignOptions().isUseRandomDependentAddition()) { - for (int i = 0; i < change; i++) { - final Person person = newDependent(false); - recruitPerson(person, PrisonerStatus.FREE, true, false); - addReport(String.format(resources.getString("dependentJoinsForce.text"), - person.getFullTitle())); - } - } - } - } - if (getLocalDate().getDayOfMonth() == 1) { /* * First of the month; roll Morale. @@ -3692,6 +3821,10 @@ public boolean newDay() { autoAwardsController.ManualController(this, false); } + if ((getLocation().isOnPlanet()) && (getLocalDate().getDayOfMonth() == 1)) { + processRandomDependents(); + } + resetAstechMinutes(); processNewDayUnits(); @@ -3722,6 +3855,103 @@ public boolean newDay() { return true; } + /** + * This method processes the random dependents for a campaign. It shuffles the active dependents list and performs + * actions based on the campaign options and unit rating modifiers. + * + * First, it determines the dependent capacity based on 20% of the active personnel count. Then, it calculates + * the number of dependents currently in the list. + * + * If the campaign options allow random dependent removal, it iterates over each dependent and determines if they + * should leave the force based on a lower roll value. If the roll value is less than or equal to 4 minus the unit + * rating modifier, the dependent is removed from the force. + * + * If the campaign options allow random dependent addition and the number of dependents is less than the dependent + * capacity, it iterates a number of times equal to the difference between the dependent capacity and the number of + * dependents. It determines if a lower roll value is less than or equal to the unit rating modifier multiplied by 2. + * If true, it recruits a new dependent and adds a report indicating the dependent has joined the force. + */ + private void processRandomDependents() { + List dependents = getActiveDependents(); + Collections.shuffle(dependents); + + // we use this value a lot, so might as well store it for easier retrieval + LocalDate currentDate = getLocalDate(); + + // we don't want to include Dependents or children when determining capacity + List activeNonDependents = getActivePersonnel().stream() + .filter(person -> !person.getPrimaryRole().isDependent()) + .filter(person -> !person.isChild(currentDate)) + .toList(); + + int dependentCapacity = (int) Math.max(1, (activeNonDependents.size() * 0.05)); + int dependentCount = dependents.size(); + + // roll for random removal + if (getCampaignOptions().isUseRandomDependentRemoval()) { + for (Person dependent : dependents) { + if (!isRemovalEligible(dependent, currentDate)) { + continue; + } + + int lowerRoll = (dependents.size() > dependentCapacity) ? getLowerRandomInt() : Compute.randomInt(100); + + if (lowerRoll <= 4 - getUnitRatingMod()) { + addReport(String.format(resources.getString("dependentLeavesForce.text"), + dependent.getFullTitle())); + + removePerson(dependent, false); + dependentCount--; + } + } + } + + // then roll for random addition + if ((getCampaignOptions().isUseRandomDependentAddition()) && (dependentCount < dependentCapacity)) { + int availableCapacity = dependentCapacity - dependentCount; + int rollCount = (int) Math.max(1, availableCapacity * 0.2); + + for (int i = 0; i < rollCount; i++) { + int lowerRoll = (dependentCount <= (dependentCapacity / 2)) ? getLowerRandomInt() : Compute.randomInt(100); + + if (lowerRoll <= (getUnitRatingMod() * 2)) { + final Person dependent = newDependent(false, Gender.RANDOMIZE); + + recruitPerson(dependent, PrisonerStatus.FREE, true, false); + + addReport(String.format(resources.getString("dependentJoinsForce.text"), + dependent.getHyperlinkedFullTitle())); + + dependentCount++; + } + } + } + } + + /** + * Returns the lower value between two random integers generated between 0 and 99 (inclusive). + * + * @return the lower random integer value + */ + private int getLowerRandomInt() { + int roll = Compute.randomInt(100); + int secondRoll = Compute.randomInt(100); + return Math.min(roll, secondRoll); + } + + /** + * Checks if a dependent is eligible for removal. + * + * @param dependent the person to check + * @param currentDate the current date + * @return {@code true} if the person is eligible for removal, {@code false} otherwise + */ + private boolean isRemovalEligible(Person dependent, LocalDate currentDate) { + return !(dependent.getGenealogy().hasNonAdultChildren(currentDate) + || dependent.getGenealogy().hasSpouse() + || dependent.isChild(currentDate)); + } + /** * This method iterates through the list of personnel and deletes the records of those who have * departed the unit and who match additional checks. diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 2af895e375..3e070a2459 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -272,58 +272,11 @@ public static String getTransitUnitName(final int unit) { // Personnel Randomization private boolean useDylansRandomXP; // Unofficial private RandomOriginOptions randomOriginOptions; - private boolean useRandomPersonalities; - - // Retirement - private boolean useRandomRetirement; - private TurnoverTargetNumberMethod turnoverTargetNumberMethod; - private SkillLevel turnoverDifficulty; - private int turnoverFixedTargetNumber; - private boolean aeroRecruitsHaveUnits; - private boolean trackOriginalUnit; - private TurnoverFrequency turnoverFrequency; - private boolean useContractCompletionRandomRetirement; - private boolean useRandomFounderTurnover; - private boolean useFounderRetirement; - private boolean useSubContractSoldiers; - private int serviceContractDuration; - private int serviceContractModifier; - private boolean payBonusDefault; - private int payBonusDefaultThreshold; - - private boolean useCustomRetirementModifiers; - private boolean useFatigueModifiers; - private boolean useSkillModifiers; - private boolean useAgeModifiers; - private boolean useUnitRatingModifiers; - private boolean useFactionModifiers; - private boolean useHostileTerritoryModifiers; - private boolean useMissionStatusModifiers; - private boolean useFamilyModifiers; - private boolean useLoyaltyModifiers; - private boolean useHideLoyalty; - - private int payoutRateOfficer; - private int payoutRateEnlisted; - private int payoutRetirementMultiplier; - private boolean usePayoutServiceBonus; - private int payoutServiceBonusRate; - - private boolean useAdministrativeStrain; - private int administrativeCapacity; - private int multiCrewStrainDivider; - - private boolean useManagementSkill; - private boolean useCommanderLeadershipOnly; - private int managementSkillPenalty; + // Random Histories + private boolean useRandomPersonalities; + private boolean useSimulatedRelationships; - private boolean useFatigue; - private int fatigueRate; - private boolean useInjuryFatigue; - private int fieldKitchenCapacity; - private boolean fieldKitchenIgnoreNonCombatants; - private int fatigueLeaveThreshold; // Family private FamilialRelationshipDisplayLevel familyDisplayLevel; @@ -411,6 +364,58 @@ public static String getTransitUnitName(final int unit) { private Map ageRangeRandomDeathFemaleValues; //endregion Life Paths Tab + //region Turnover and Retention + private boolean useRandomRetirement; + + private TurnoverTargetNumberMethod turnoverTargetNumberMethod; + private SkillLevel turnoverDifficulty; + private int turnoverFixedTargetNumber; + private boolean aeroRecruitsHaveUnits; + private boolean trackOriginalUnit; + private TurnoverFrequency turnoverFrequency; + private boolean useContractCompletionRandomRetirement; + private boolean useRandomFounderTurnover; + private boolean useFounderRetirement; + private boolean useSubContractSoldiers; + private int serviceContractDuration; + private int serviceContractModifier; + private boolean payBonusDefault; + private int payBonusDefaultThreshold; + + private boolean useCustomRetirementModifiers; + private boolean useFatigueModifiers; + private boolean useSkillModifiers; + private boolean useAgeModifiers; + private boolean useUnitRatingModifiers; + private boolean useFactionModifiers; + private boolean useHostileTerritoryModifiers; + private boolean useMissionStatusModifiers; + private boolean useFamilyModifiers; + private boolean useLoyaltyModifiers; + private boolean useHideLoyalty; + + private int payoutRateOfficer; + private int payoutRateEnlisted; + private int payoutRetirementMultiplier; + private boolean usePayoutServiceBonus; + private int payoutServiceBonusRate; + + private boolean useAdministrativeStrain; + private int administrativeCapacity; + private int multiCrewStrainDivider; + + private boolean useManagementSkill; + private boolean useCommanderLeadershipOnly; + private int managementSkillPenalty; + + private boolean useFatigue; + private int fatigueRate; + private boolean useInjuryFatigue; + private int fieldKitchenCapacity; + private boolean fieldKitchenIgnoreNonCombatants; + private int fatigueLeaveThreshold; + //endregion Turnover and Retention + //region Finance tab private boolean payForParts; private boolean payForRepairs; @@ -820,7 +825,10 @@ public CampaignOptions() { // Personnel Randomization setUseDylansRandomXP(false); setRandomOriginOptions(new RandomOriginOptions(true)); + + // Random Histories setUseRandomPersonalities(false); + setUseSimulatedRelationships(false); // Family setFamilyDisplayLevel(FamilialRelationshipDisplayLevel.SPOUSE); @@ -1825,7 +1833,9 @@ public RandomOriginOptions getRandomOriginOptions() { public void setRandomOriginOptions(final RandomOriginOptions randomOriginOptions) { this.randomOriginOptions = randomOriginOptions; } + //endregion Personnel Randomization + //region Random Histories public boolean isUseRandomPersonalities() { return useRandomPersonalities; } @@ -1833,7 +1843,15 @@ public boolean isUseRandomPersonalities() { public void setUseRandomPersonalities(final boolean useRandomPersonalities) { this.useRandomPersonalities = useRandomPersonalities; } - //endregion Personnel Randomization + + public boolean isUseSimulatedRelationships() { + return useSimulatedRelationships; + } + + public void setUseSimulatedRelationships(final boolean useSimulatedRelationships) { + this.useSimulatedRelationships = useSimulatedRelationships; + } + //endregion Random Histories //region Retirement public boolean isUseRandomRetirement() { @@ -4633,9 +4651,13 @@ public void writeToXml(final PrintWriter pw, int indent) { //region Personnel Randomization MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useDylansRandomXP", isUseDylansRandomXP()); getRandomOriginOptions().writeToXML(pw, indent); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPersonalities", isUseRandomPersonalities()); //endregion Personnel Randomization + //region Random Histories + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPersonalities", isUseRandomPersonalities()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useSimulatedRelationships", isUseSimulatedRelationships()); + //endregion Random Histories + //region Retirement MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomRetirement", isUseRandomRetirement()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "turnoverTargetNumberMethod", getTurnoverTargetNumberMethod().name()); @@ -5374,9 +5396,14 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve continue; } retVal.setRandomOriginOptions(randomOriginOptions); + //endregion Personnel Randomization + + //region Random Histories } else if (wn2.getNodeName().equalsIgnoreCase("useRandomPersonalities")) { retVal.setUseRandomPersonalities(Boolean.parseBoolean(wn2.getTextContent().trim())); - //endregion Personnel Randomization + } else if (wn2.getNodeName().equalsIgnoreCase("useSimulatedRelationships")) { + retVal.setUseSimulatedRelationships(Boolean.parseBoolean(wn2.getTextContent().trim())); + //endregion Random Histories //region Family } else if (wn2.getNodeName().equalsIgnoreCase("familyDisplayLevel") diff --git a/MekHQ/src/mekhq/campaign/mission/AtBContract.java b/MekHQ/src/mekhq/campaign/mission/AtBContract.java index 83eac209ce..32973512ea 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBContract.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBContract.java @@ -24,6 +24,7 @@ import megamek.client.generator.RandomUnitGenerator; import megamek.client.ui.swing.util.PlayerColour; import megamek.common.*; +import megamek.common.enums.Gender; import megamek.common.enums.SkillLevel; import megamek.common.icons.Camouflage; import megamek.common.loaders.EntityLoadingException; @@ -480,12 +481,12 @@ public void doBonusRoll(Campaign c) { int roll = Compute.d6(); switch (roll) { case 1: /* 1d6 dependents */ - if (c.getCampaignOptions().getRandomDependentMethod().isAgainstTheBot() - && c.getCampaignOptions().isUseRandomDependentAddition()) { + if (c.getCampaignOptions().isUseRandomDependentAddition()) { number = Compute.d6(); c.addReport("Bonus: " + number + " dependent" + ((number > 1) ? "s" : "")); + for (int i = 0; i < number; i++) { - Person p = c.newDependent(false); + Person p = c.newDependent(false, Gender.RANDOMIZE); c.recruitPerson(p); } } @@ -974,7 +975,7 @@ public void setEmployerCode(String code, int year) { } public String getEmployerName(int year) { - return isMercSubcontract() ? "Mercenary (" + getEmployerFaction().getFullName(year) + ")" + return isMercSubcontract() ? "Mercenary (" + getEmployerFaction().getFullName(year) + ')' : getEmployerFaction().getFullName(year); } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 015c16a91b..610ea21b25 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -242,6 +242,33 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person MekHQ.triggerEvent(new PersonChangedEvent(origin)); } + /** + * This divorces two married people. + * This version is meant to be used to log historic divorces that occur during a characters' random background. + * It is a watered down version of divorce() + * + * @param campaign the campaign the two people are a part of + * @param today the current date + * @param origin the origin person being divorced + */ + public void divorceHistoric(final Campaign campaign, final LocalDate today, final Person origin) { + final Person spouse = origin.getGenealogy().getSpouse(); + + SplittingSurnameStyle.WEIGHTED.apply(campaign, origin, spouse); + + PersonalLogger.divorcedFrom(origin, spouse, today); + PersonalLogger.divorcedFrom(spouse, origin, today); + + spouse.setMaidenName(null); + origin.setMaidenName(null); + + spouse.getGenealogy().setSpouse(null); + origin.getGenealogy().setSpouse(null); + + spouse.getGenealogy().addFormerSpouse(new FormerSpouse(origin, today, FormerSpouseReason.DIVORCE)); + origin.getGenealogy().addFormerSpouse(new FormerSpouse(spouse, today, FormerSpouseReason.DIVORCE)); + } + //region New Day /** * Processes new day random divorce for an individual. diff --git a/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java b/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java index 6ca7096f57..be0cc61852 100644 --- a/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java +++ b/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java @@ -29,6 +29,7 @@ import org.w3c.dom.NodeList; import java.io.PrintWriter; +import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @@ -194,6 +195,13 @@ public boolean hasChildren() { return getFamily().get(FamilialRelationshipType.CHILD) != null; } + /** + * @return true if the person has at least one kid, false otherwise + */ + public boolean hasNonAdultChildren(LocalDate localDate) { + return getChildren().stream().anyMatch(child -> child.isChild(localDate)); + } + /** * @return true if the Person has any parents, otherwise false */ diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 3dad3f772b..f24bb9469f 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -189,6 +189,32 @@ public void marry(final Campaign campaign, final LocalDate today, final Person o return; } + performMarriageChanges(campaign, today, origin, spouse, surnameStyle); + + campaign.addReport(String.format(resources.getString("marriage.report"), origin.getHyperlinkedName(), + spouse.getHyperlinkedName())); + + // Process the loyalty change + if (campaign.getCampaignOptions().isUseLoyaltyModifiers()) { + origin.performRandomizedLoyaltyChange(campaign, false, true); + spouse.performRandomizedLoyaltyChange(campaign, false, true); + } + + // And finally we trigger person changed events + MekHQ.triggerEvent(new PersonChangedEvent(origin)); + MekHQ.triggerEvent(new PersonChangedEvent(spouse)); + } + + /** + * Updates the necessary information to perform a marriage between two individuals. + * + * @param campaign the campaign in which the marriage is taking place + * @param today the current date of the marriage + * @param origin the first person getting married + * @param spouse the second person getting married + * @param surnameStyle the style of surname changes to be applied + */ + public static void performMarriageChanges(Campaign campaign, LocalDate today, Person origin, Person spouse, MergingSurnameStyle surnameStyle) { // Immediately set both Maiden Names, to avoid any divorce bugs (as the default is now an empty string) origin.setMaidenName(origin.getSurname()); spouse.setMaidenName(spouse.getSurname()); diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 8ef7c41146..33e903be2c 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -21,6 +21,7 @@ import megamek.codeUtilities.MathUtility; import megamek.common.Compute; import megamek.common.annotations.Nullable; +import megamek.common.enums.Gender; import mekhq.MHQConstants; import mekhq.MekHQ; import mekhq.campaign.Campaign; @@ -39,6 +40,8 @@ import java.time.LocalDate; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; import java.util.ResourceBundle; import java.util.UUID; @@ -243,38 +246,54 @@ public int determinePregnancyWeek(final LocalDate today, final Person person) { * @param campaign the campaign the person is a part of * @param today the current date * @param mother the newly pregnant mother + * @param isNoReport true if no message should be posted to the daily report */ - public void addPregnancy(final Campaign campaign, final LocalDate today, final Person mother) { - addPregnancy(campaign, today, mother, determineNumberOfBabies( - campaign.getCampaignOptions().getMultiplePregnancyOccurrences())); + public void addPregnancy(final Campaign campaign, final LocalDate today, final Person mother, boolean isNoReport) { + addPregnancy( + campaign, + today, + mother, + determineNumberOfBabies(campaign.getCampaignOptions().getMultiplePregnancyOccurrences()), + isNoReport + ); } /** * This method is how a person becomes pregnant with the specified number of children. They have - * their due date set and the parentage of the pregnancy determined. + * their due date set, and the parentage of the pregnancy is determined. * * @param campaign the campaign the person is a part of * @param today the current date * @param mother the newly pregnant mother * @param size the number of children the mother is having + * @param isNoReport true if no message should be posted to the daily report */ public void addPregnancy(final Campaign campaign, final LocalDate today, final Person mother, - final int size) { + final int size, boolean isNoReport) { if (size < 1) { return; } mother.setExpectedDueDate(today.plusDays(MHQConstants.PREGNANCY_STANDARD_DURATION)); + mother.setDueDate(today.plusDays(determinePregnancyDuration())); + mother.getExtraData().set(PREGNANCY_CHILDREN_DATA, size); + mother.getExtraData().set(PREGNANCY_FATHER_DATA, mother.getGenealogy().hasSpouse() ? mother.getGenealogy().getSpouse().getId().toString() : null); final String babyAmount = resources.getString("babyAmount.text").split(",")[size - 1]; - campaign.addReport(String.format(resources.getString("babyConceived.report"), - mother.getHyperlinkedName(), babyAmount).trim()); + + if (!isNoReport) { + campaign.addReport(String.format(resources.getString("babyConceived.report"), + mother.getHyperlinkedName(), + babyAmount).trim()); + } + if (campaign.getCampaignOptions().isLogProcreation()) { MedicalLogger.hasConceived(mother, today, babyAmount); + if (mother.getGenealogy().hasSpouse()) { PersonalLogger.spouseConceived(mother.getGenealogy().getSpouse(), mother.getFullName(), today, babyAmount); @@ -321,8 +340,8 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m // Create Babies for (int i = 0; i < size; i++) { - // Create the specific baby - final Person baby = campaign.newDependent(true); + // Create a baby + final Person baby = campaign.newDependent(true, Gender.RANDOMIZE); baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle() .generateBabySurname(mother, father, baby.getGender())); baby.setBirthday(today); @@ -331,20 +350,7 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m campaign.addReport(String.format(resources.getString("babyBorn.report"), mother.getHyperlinkedName(), baby.getHyperlinkedName(), GenderDescriptors.BOY_GIRL.getDescriptor(baby.getGender()))); - if (campaign.getCampaignOptions().isLogProcreation()) { - MedicalLogger.deliveredBaby(mother, baby, today); - if (father != null) { - PersonalLogger.ourChildBorn(father, baby, mother.getFullName(), today); - } - } - - // Create genealogy information - baby.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, mother); - mother.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, baby); - if (father != null) { - baby.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, father); - father.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, baby); - } + logAndUpdateFamily(campaign, today, mother, baby, father); // Founder Tag Assignment if (campaign.getCampaignOptions().isAssignNonPrisonerBabiesFounderTag() @@ -378,6 +384,80 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m removePregnancy(mother); } + /** + * Logs the birth of a baby and updates the genealogy information of the family. + * + * @param campaign the ongoing campaign + * @param today the current date + * @param mother the mother of the baby + * @param baby the newborn baby + * @param father the father of the baby, null if unknown + */ + private static void logAndUpdateFamily(Campaign campaign, LocalDate today, Person mother, Person baby, Person father) { + if (campaign.getCampaignOptions().isLogProcreation()) { + MedicalLogger.deliveredBaby(mother, baby, today); + if (father != null) { + PersonalLogger.ourChildBorn(father, baby, mother.getFullName(), today); + } + } + + // Create genealogy information + baby.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, mother); + mother.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, baby); + if (father != null) { + baby.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, father); + father.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, baby); + } + } + + /** + * Creates baby/babies and performs any necessary operations such as setting birthdate, creating reports, + * updating genealogy, setting education, loyalty, personality, and recruiting the baby. + * This version is for historic births that occur as part of a character's background. + * + * @param campaign the campaign object + * @param today the current date + * @param mother the mother person object + * @param father the father person object, can be null if the father is unknown + * @return the babies + */ + public List birthHistoric(final Campaign campaign, final LocalDate today, final Person mother, @Nullable final Person father) { + List babies = new ArrayList<>(); + + // Determine the number of children + final int size = mother.getExtraData().get(PREGNANCY_CHILDREN_DATA, 1); + // Create Babies + for (int i = 0; i < size; i++) { + // Create the babies + final Person baby = campaign.newDependent(true, Gender.RANDOMIZE); + + baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle() + .generateBabySurname(mother, father, baby.getGender())); + + baby.setBirthday(today); + + // Create reports and log the birth + logAndUpdateFamily(campaign, today, mother, baby, father); + + // set education + baby.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); + + // set loyalty + baby.setLoyalty(Compute.d6(4, 3)); + + // set baby's personality + PersonalityController.generatePersonality(baby); + + // add to the list of babies + babies.add(baby); + } + + // Cleanup Data + removePregnancy(mother); + + return babies; + } + /** * This is used to process procreation when a person dies with the Pregnancy Complications status * @param campaign the campaign to add the baby to @@ -441,7 +521,7 @@ public void processNewDay(final Campaign campaign, final LocalDate today, final // Make the required checks for random procreation if (randomlyProcreates(today, person)) { - addPregnancy(campaign, today, person); + addPregnancy(campaign, today, person, false); } } diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java index e4924d3f8d..93920f8d65 100644 --- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java @@ -327,7 +327,7 @@ public void actionPerformed(ActionEvent action) { gui.getCampaign().getLocalDate(), person, false) == null)) .forEach(person -> { gui.getCampaign().getProcreation().addPregnancy( - gui.getCampaign(), gui.getCampaign().getLocalDate(), person); + gui.getCampaign(), gui.getCampaign().getLocalDate(), person, false); MekHQ.triggerEvent(new PersonChangedEvent(person)); }); break; diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index be0cc86e9d..c74a0e388a 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -358,7 +358,10 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { // Personnel Randomization private JCheckBox chkUseDylansRandomXP; private RandomOriginOptionsPanel randomOriginOptionsPanel; + + // Random Histories private JCheckBox chkUseRandomPersonalities; + private JCheckBox chkUseSimulatedRelationships; // Marriage private JCheckBox chkUseManualMarriages; @@ -3402,15 +3405,17 @@ private JScrollPane createLifePathsPanel() { lifePathsPanel.add(createPersonnelRandomizationPanel(), gbc); gbc.gridx++; - lifePathsPanel.add(createAnniversaryPanel(), gbc); + lifePathsPanel.add(createRandomHistoriesPanel(), gbc); // gbc.gridx = 0; gbc.gridy++; - gbc.gridwidth = 2; lifePathsPanel.add(createFamilyPanel(), gbc); + gbc.gridx++; + lifePathsPanel.add(createAnniversaryPanel(), gbc); + // gbc.gridx = 0; @@ -4978,10 +4983,6 @@ private JPanel createPersonnelRandomizationPanel() { randomOriginOptionsPanel = new RandomOriginOptionsPanel(getFrame(), campaign, comboFaction); - chkUseRandomPersonalities = new JCheckBox(resources.getString("chkUseRandomPersonalities.text")); - chkUseRandomPersonalities.setToolTipText(resources.getString("chkUseRandomPersonalities.toolTipText")); - chkUseRandomPersonalities.setName("chkUseRandomPersonalities"); - // Layout the Panel final JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createTitledBorder(resources.getString("personnelRandomizationPanel.title"))); @@ -4996,14 +4997,46 @@ private JPanel createPersonnelRandomizationPanel() { layout.createSequentialGroup() .addComponent(chkUseDylansRandomXP) .addComponent(randomOriginOptionsPanel) - .addComponent(chkUseRandomPersonalities) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addComponent(chkUseDylansRandomXP) .addComponent(randomOriginOptionsPanel) + ); + + return panel; + } + + private JPanel createRandomHistoriesPanel() { + chkUseRandomPersonalities = new JCheckBox(resources.getString("chkUseRandomPersonalities.text")); + chkUseRandomPersonalities.setToolTipText(resources.getString("chkUseRandomPersonalities.toolTipText")); + chkUseRandomPersonalities.setName("chkUseRandomPersonalities"); + + chkUseSimulatedRelationships = new JCheckBox(resources.getString("chkUseSimulatedRelationships.text")); + chkUseSimulatedRelationships.setToolTipText(resources.getString("chkUseSimulatedRelationships.toolTipText")); + chkUseSimulatedRelationships.setName("chkUseSimulatedRelationships"); + + // Layout the Panel + final JPanel panel = new JPanel(); + panel.setBorder(BorderFactory.createTitledBorder(resources.getString("randomHistoriesPanel.title"))); + panel.setName("randomHistoriesPanel"); + + final GroupLayout layout = new GroupLayout(panel); + layout.setAutoCreateGaps(true); + layout.setAutoCreateContainerGaps(true); + panel.setLayout(layout); + + layout.setVerticalGroup( + layout.createSequentialGroup() .addComponent(chkUseRandomPersonalities) + .addComponent(chkUseSimulatedRelationships) + ); + + layout.setHorizontalGroup( + layout.createParallelGroup(Alignment.LEADING) + .addComponent(chkUseRandomPersonalities) + .addComponent(chkUseSimulatedRelationships) ); return panel; @@ -8196,7 +8229,10 @@ public void setOptions(@Nullable CampaignOptions options, // Personnel Randomization chkUseDylansRandomXP.setSelected(options.isUseDylansRandomXP()); randomOriginOptionsPanel.setOptions(options.getRandomOriginOptions()); + + // Random Histories chkUseRandomPersonalities.setSelected(options.isUseRandomPersonalities()); + chkUseSimulatedRelationships.setSelected(options.isUseSimulatedRelationships()); // Family comboFamilyDisplayLevel.setSelectedItem(options.getFamilyDisplayLevel()); @@ -8891,7 +8927,10 @@ public void updateOptions() { // Personnel Randomization options.setUseDylansRandomXP(chkUseDylansRandomXP.isSelected()); options.setRandomOriginOptions(randomOriginOptionsPanel.createOptionsFromPanel()); + + // Random Histories options.setUseRandomPersonalities(chkUseRandomPersonalities.isSelected()); + options.setUseSimulatedRelationships(chkUseSimulatedRelationships.isSelected()); // Family options.setFamilyDisplayLevel(comboFamilyDisplayLevel.getSelectedItem()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java index 4512439ee4..03e16f49e4 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java @@ -299,20 +299,20 @@ public void testCanProcreate() { @Test public void testAddPregnancy() { - doCallRealMethod().when(mockProcreation).addPregnancy(any(), any(), any()); - doCallRealMethod().when(mockProcreation).addPregnancy(any(), any(), any(), anyInt()); + doCallRealMethod().when(mockProcreation).addPregnancy(any(), any(), any(), eq(false)); + doCallRealMethod().when(mockProcreation).addPregnancy(any(), any(), any(), anyInt(), eq(false)); final Person mother = new Person(mockCampaign); final Person father = new Person(mockCampaign); when(mockProcreation.determineNumberOfBabies(anyInt())).thenReturn(0); - mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother); + mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, false); assertNull(mother.getExpectedDueDate()); assertNull(mother.getDueDate()); assertTrue(mother.getExtraData().isEmpty()); when(mockCampaignOptions.isLogProcreation()).thenReturn(false); - mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, 1); + mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, 1, false); assertEquals(LocalDate.ofYearDay(3025, 281), mother.getExpectedDueDate()); assertNotNull(mother.getDueDate()); assertFalse(mother.getExtraData().isEmpty()); @@ -321,7 +321,7 @@ public void testAddPregnancy() { assertEquals(1, mother.getExtraData().get(AbstractProcreation.PREGNANCY_CHILDREN_DATA)); when(mockCampaignOptions.isLogProcreation()).thenReturn(true); - mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, 2); + mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, 2, false); assertEquals(LocalDate.ofYearDay(3025, 281), mother.getExpectedDueDate()); assertNotNull(mother.getDueDate()); assertFalse(mother.getExtraData().isEmpty()); @@ -330,7 +330,7 @@ public void testAddPregnancy() { assertEquals(2, mother.getExtraData().get(AbstractProcreation.PREGNANCY_CHILDREN_DATA)); mother.getGenealogy().setSpouse(father); - mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, 10); + mockProcreation.addPregnancy(mockCampaign, LocalDate.ofYearDay(3025, 1), mother, 10, false); assertEquals(LocalDate.ofYearDay(3025, 281), mother.getExpectedDueDate()); assertNotNull(mother.getDueDate()); assertFalse(mother.getExtraData().isEmpty()); @@ -450,7 +450,7 @@ public void testProcessPregnancyComplications() { public void testProcessNewDay() { doCallRealMethod().when(mockProcreation).processNewDay(any(), any(), any()); doNothing().when(mockProcreation).birth(any(), any(), any()); - doNothing().when(mockProcreation).addPregnancy(any(), any(), any()); + doNothing().when(mockProcreation).addPregnancy(any(), any(), any(), eq(false)); final Person mockPerson = mock(Person.class); @@ -481,7 +481,7 @@ public void testProcessNewDay() { when(mockProcreation.randomlyProcreates(any(), any())).thenReturn(true); mockProcreation.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockProcreation, times(2)).randomlyProcreates(any(), any()); - verify(mockProcreation, times(1)).addPregnancy(any(), any(), any()); + verify(mockProcreation, times(1)).addPregnancy(any(), any(), any(), eq(false)); } //region Random Procreation From b437dc5d61c554daea021cfb9c3423a6759b73fb Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 12:24:06 -0500 Subject: [PATCH 02/41] Fixed status logic for clan members Previously, the system did not correctly handle clan members when simulating relationship history. Added a check to exclude clan members from simulated relationship history updates. --- MekHQ/src/mekhq/campaign/Campaign.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 0139a557cf..7fe4ba8c12 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -1560,7 +1560,7 @@ public boolean recruitPerson(Person p, PrisonerStatus prisonerStatus, boolean gm p.setPrisonerStatus(this, prisonerStatus, log); if (getCampaignOptions().isUseSimulatedRelationships()) { - if ((prisonerStatus.isFree()) && (!p.getPrimaryRole().isDependent())) { + if ((prisonerStatus.isFree()) && (!p.getOriginFaction().isClan()) && (!p.getPrimaryRole().isDependent())) { simulateRelationshipHistory(p); } } From a2a0aabdc6dbb2748475c6edc452be9c66907c92 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 14:31:02 -0500 Subject: [PATCH 03/41] Replace PercentageRandomProcreation with randomProcreation Replaced `PercentageRandomProcreation` with `randomProcreation` across multiple files to change the logic from percentage-based to dice roll-based. Adjusted test cases and method calls to reflect this change, ensuring consistent functionality. --- .../CampaignOptionsDialog.properties | 8 +- .../mekhq/resources/Personnel.properties | 4 +- MekHQ/src/mekhq/campaign/CampaignOptions.java | 56 +++++------- .../personnel/death/AgeRangeRandomDeath.java | 2 +- .../death/ExponentialRandomDeath.java | 2 +- .../death/PercentageRandomDeath.java | 2 +- .../divorce/PercentageRandomDivorce.java | 4 +- .../enums/RandomProcreationMethod.java | 21 ++--- .../marriage/PercentageRandomMarriage.java | 4 +- .../procreation/AbstractProcreation.java | 78 ++++++++-------- .../DisabledRandomProcreation.java | 7 +- .../PercentageRandomProcreation.java | 67 -------------- .../procreation/randomProcreation.java | 69 +++++++++++++++ MekHQ/src/mekhq/gui/CampaignGUI.java | 71 +++------------ .../mekhq/gui/panes/CampaignOptionsPane.java | 76 ++++++++-------- .../death/AgeRangeRandomDeathTest.java | 12 +-- .../death/ExponentialRandomDeathTest.java | 14 +-- .../death/PercentageRandomDeathTest.java | 8 +- .../divorce/PercentageRandomDivorceTest.java | 16 ++-- .../enums/RandomProcreationMethodTest.java | 22 ++--- .../PercentageRandomMarriageTest.java | 16 ++-- .../procreation/AbstractProcreationTest.java | 15 ++-- .../DisabledRandomProcreationTest.java | 7 +- .../PercentageRandomProcreationTest.java | 88 ------------------- .../procreation/randomProcreationTest.java | 82 +++++++++++++++++ 25 files changed, 338 insertions(+), 413 deletions(-) delete mode 100644 MekHQ/src/mekhq/campaign/personnel/procreation/PercentageRandomProcreation.java create mode 100644 MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java delete mode 100644 MekHQ/unittests/mekhq/campaign/personnel/procreation/PercentageRandomProcreationTest.java create mode 100644 MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 67d212d0d0..f0f553949c 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -539,10 +539,10 @@ chkUseRandomClanPersonnelProcreation.toolTipText=Allow clan-origin personnel to chkUseRandomPrisonerProcreation.text=Use Random Prisoner Procreation chkUseRandomPrisonerProcreation.toolTipText=Allow prisoners to randomly procreate. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. percentageRandomProcreationPanel.title=Percentage Random Procreation -lblPercentageRandomProcreationRelationshipChance.text=Relationship Chance -lblPercentageRandomProcreationRelationshipChance.toolTipText=This is the percent chance per day that a female member of your force in a relationship will have a baby when not deployed. -lblPercentageRandomProcreationRelationshiplessChance.text=Relationshipless Chance -lblPercentageRandomProcreationRelationshiplessChance.toolTipText=This is the percent chance per day that a female member of your force not in a relationship will have a baby when not deployed. +lblRandomProcreationRelationshipDiceSize.text=Relationship Dice Size +lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. +lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Dice Size +lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. # Death deathPanel.title=Death diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index ec2d40042a..c28edf0fdf 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -1027,8 +1027,8 @@ RandomMarriageMethod.PERCENTAGE.toolTipText=This checks if a random value is low # RandomProcreationMethod Enum RandomProcreationMethod.NONE.text=Disabled RandomProcreationMethod.NONE.toolTipText=Random procreation is disabled. -RandomProcreationMethod.PERCENTAGE.text=Percentage -RandomProcreationMethod.PERCENTAGE.toolTipText=This checks if a random value is lower than the percentage to determine if an eligible person procreates on a given day. +RandomProcreationMethod.DICE_ROLL.text=Dice Roll +RandomProcreationMethod.DICE_ROLL.toolTipText=Once per week roll a die with sides equal to those set below. On a roll of 1 the character falls pregnant. # TurnoverTargetNumberMethod Enum TurnoverTargetNumberMethod.FIXED.text=Fixed diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 2af895e375..0f4dd9aee1 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -377,8 +377,8 @@ public static String getTransitUnitName(final int unit) { private boolean useRelationshiplessRandomProcreation; private boolean useRandomClanPersonnelProcreation; private boolean useRandomPrisonerProcreation; - private double percentageRandomProcreationRelationshipChance; - private double percentageRandomProcreationRelationshiplessChance; + private int randomProcreationRelationshipDiceSize; + private int randomProcreationRelationshiplessDiceSize; // Education private boolean useEducationModule; @@ -891,8 +891,8 @@ public CampaignOptions() { setUseRelationshiplessRandomProcreation(false); setUseRandomClanPersonnelProcreation(false); setUseRandomPrisonerProcreation(true); - setPercentageRandomProcreationRelationshipChance(0.0005); - setPercentageRandomProcreationRelationshiplessChance(0.00005); + setRandomProcreationRelationshipDiceSize(621); + setRandomProcreationRelationshiplessDiceSize(1861); // Education setUseEducationModule(false); @@ -2681,32 +2681,31 @@ public void setUseRandomPrisonerProcreation(final boolean useRandomPrisonerProcr * This gets the decimal chance (between 0 and 1) of random procreation occurring * @return the chance, with a value between 0 and 1 */ - public double getPercentageRandomProcreationRelationshipChance() { - return percentageRandomProcreationRelationshipChance; + public int getRandomProcreationRelationshipDiceSize() { + return randomProcreationRelationshipDiceSize; } /** - * This sets the decimal chance (between 0 and 1) of random procreation occurring - * @param percentageRandomProcreationRelationshipChance the chance, with a value between 0 and 1 + * This sets the dice size for random procreation + * @param randomProcreationRelationshipDiceSize the chance, with a value between 0 and 1 */ - public void setPercentageRandomProcreationRelationshipChance(final double percentageRandomProcreationRelationshipChance) { - this.percentageRandomProcreationRelationshipChance = percentageRandomProcreationRelationshipChance; + public void setRandomProcreationRelationshipDiceSize(final int randomProcreationRelationshipDiceSize) { + this.randomProcreationRelationshipDiceSize = randomProcreationRelationshipDiceSize; } /** - * This gets the decimal chance (between 0 and 1) of random procreation occurring without a relationship - * @return the chance, with a value between 0 and 1 + * @return the dice size for random procreation */ - public double getPercentageRandomProcreationRelationshiplessChance() { - return percentageRandomProcreationRelationshiplessChance; + public int getRandomProcreationRelationshiplessDiceSize() { + return randomProcreationRelationshiplessDiceSize; } /** * This sets the decimal chance (between 0 and 1) of random procreation occurring without a relationship - * @param percentageRandomProcreationRelationshiplessChance the chance, with a value between 0 and 1 + * @param randomProcreationRelationshiplessDiceSize the chance, with a value between 0 and 1 */ - public void setPercentageRandomProcreationRelationshiplessChance(final double percentageRandomProcreationRelationshiplessChance) { - this.percentageRandomProcreationRelationshiplessChance = percentageRandomProcreationRelationshiplessChance; + public void setRandomProcreationRelationshiplessDiceSize(final int randomProcreationRelationshiplessDiceSize) { + this.randomProcreationRelationshiplessDiceSize = randomProcreationRelationshiplessDiceSize; } //endregion Procreation @@ -4752,8 +4751,8 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRelationshiplessRandomProcreation", isUseRelationshiplessRandomProcreation()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomClanPersonnelProcreation", isUseRandomClanPersonnelProcreation()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPrisonerProcreation", isUseRandomPrisonerProcreation()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "percentageRandomProcreationRelationshipChance", getPercentageRandomProcreationRelationshipChance()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "percentageRandomProcreationRelationshiplessChance", getPercentageRandomProcreationRelationshiplessChance()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomProcreationRelationshipDiceSize", getRandomProcreationRelationshipDiceSize()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomProcreationRelationshiplessDiceSize", getRandomProcreationRelationshiplessDiceSize()); //endregion Procreation //region Education @@ -5508,10 +5507,10 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUseRandomClanPersonnelProcreation(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("useRandomPrisonerProcreation")) { retVal.setUseRandomPrisonerProcreation(Boolean.parseBoolean(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("percentageRandomProcreationRelationshipChance")) { - retVal.setPercentageRandomProcreationRelationshipChance(Double.parseDouble(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("percentageRandomProcreationRelationshiplessChance")) { - retVal.setPercentageRandomProcreationRelationshiplessChance(Double.parseDouble(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("randomProcreationRelationshipDiceSize")) { + retVal.setRandomProcreationRelationshipDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("randomProcreationRelationshiplessDiceSize")) { + retVal.setRandomProcreationRelationshiplessDiceSize(Integer.parseInt(wn2.getTextContent().trim())); //endregion Procreation //region Education @@ -6016,17 +6015,6 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve } else { LogManager.getLogger().error("Unknown length of randomMarriageSurnameWeights"); } - } else if (wn2.getNodeName().equalsIgnoreCase("useUnofficialProcreation") // Legacy - 0.49.0 Removal - || wn2.getNodeName().equalsIgnoreCase("useProcreation")) { // Legacy - 0.49.4 Removal - retVal.setRandomProcreationMethod(RandomProcreationMethod.PERCENTAGE); - retVal.setUseManualProcreation(true); - } else if (wn2.getNodeName().equalsIgnoreCase("chanceProcreation")) { // Legacy - 0.49.4 Removal - retVal.setPercentageRandomProcreationRelationshipChance(Double.parseDouble(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("useUnofficialProcreationNoRelationship") // Legacy - 0.49.0 Removal - || wn2.getNodeName().equalsIgnoreCase("useProcreationNoRelationship")) { // Legacy - 0.49.4 Removal - retVal.setUseRelationshiplessRandomProcreation(Boolean.parseBoolean(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("chanceProcreationNoRelationship")) { // Legacy - 0.49.4 Removal - retVal.setPercentageRandomProcreationRelationshiplessChance(Double.parseDouble(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("logConception")) { // Legacy - 0.49.4 Removal retVal.setLogProcreation(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("staticRATs")) { // Legacy - 0.49.4 Removal diff --git a/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java index 4f9f59315a..4454342aa7 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java @@ -81,6 +81,6 @@ public void adjustRangeValues(final CampaignOptions options) { @Override public boolean randomlyDies(final int age, final Gender gender) { final TenYearAgeRange ageRange = TenYearAgeRange.determineAgeRange(age); - return Compute.randomFloat() < ((gender.isMale() ? getMale() : getFemale()).get(ageRange)); + return Compute.randomInt() < ((gender.isMale() ? getMale() : getFemale()).get(ageRange)); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java index a3a65ce270..5dcb2b3a90 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java @@ -64,7 +64,7 @@ public void setFemale(final double... female) { */ @Override public boolean randomlyDies(final int age, final Gender gender) { - return Compute.randomFloat() < (gender.isMale() + return Compute.randomInt() < (gender.isMale() ? (getMale()[0] * Math.pow(10, getMale()[1]) * Math.exp(getMale()[2] * age)) : (getFemale()[0] * Math.pow(10, getFemale()[1]) * Math.exp(getFemale()[2] * age))); } diff --git a/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java index e097f00668..7395407ba4 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java @@ -47,6 +47,6 @@ public void setPercentage(final double percentage) { @Override public boolean randomlyDies(final int age, final Gender gender) { - return Compute.randomFloat() < getPercentage(); + return Compute.randomInt() < getPercentage(); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java index b4fd1e4591..149f22c64c 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java @@ -57,11 +57,11 @@ public void setSameSexPercentage(final double sameSexPercentage) { @Override protected boolean randomOppositeSexDivorce(final Person person) { - return Compute.randomFloat() < getOppositeSexPercentage(); + return Compute.randomInt() < getOppositeSexPercentage(); } @Override protected boolean randomSameSexDivorce(final Person person) { - return Compute.randomFloat() < getSameSexPercentage(); + return Compute.randomInt() < getSameSexPercentage(); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java index a5657132ed..c93a512fcc 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java @@ -22,14 +22,14 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.procreation.AbstractProcreation; import mekhq.campaign.personnel.procreation.DisabledRandomProcreation; -import mekhq.campaign.personnel.procreation.PercentageRandomProcreation; +import mekhq.campaign.personnel.procreation.randomProcreation; import java.util.ResourceBundle; public enum RandomProcreationMethod { //region Enum Declarations NONE("RandomProcreationMethod.NONE.text", "RandomProcreationMethod.NONE.toolTipText"), - PERCENTAGE("RandomProcreationMethod.PERCENTAGE.text", "RandomProcreationMethod.PERCENTAGE.toolTipText"); + DICE_ROLL("RandomProcreationMethod.DICE_ROLL.text", "RandomProcreationMethod.DICE_ROLL.toolTipText"); //endregion Enum Declarations //region Variable Declarations @@ -47,28 +47,29 @@ public enum RandomProcreationMethod { //endregion Constructors //region Getters + @SuppressWarnings(value = "unused") public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparison Methods + @SuppressWarnings(value = "unused") public boolean isNone() { return this == NONE; } - public boolean isPercentage() { - return this == PERCENTAGE; + @SuppressWarnings(value = "unused") + public boolean isDiceRoll() { + return this == DICE_ROLL; } //endregion Boolean Comparison Methods public AbstractProcreation getMethod(final CampaignOptions options) { - switch (this) { - case PERCENTAGE: - return new PercentageRandomProcreation(options); - case NONE: - default: - return new DisabledRandomProcreation(options); + if (this == DICE_ROLL) { + return new randomProcreation(options); + } else { + return new DisabledRandomProcreation(options); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java index f36c5f2218..be624d9fa9 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java @@ -57,11 +57,11 @@ public void setSameSexPercentage(final double sameSexPercentage) { @Override protected boolean randomOppositeSexMarriage(final Person person) { - return Compute.randomFloat() < getOppositeSexPercentage(); + return Compute.randomInt() < getOppositeSexPercentage(); } @Override protected boolean randomSameSexMarriage(final Person person) { - return Compute.randomFloat() < getSameSexPercentage(); + return Compute.randomInt() < getSameSexPercentage(); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 8ef7c41146..35acac0515 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -124,7 +124,7 @@ public void setUseRandomPrisonerProcreation(final boolean useRandomPrisonerProcr /** * This method determines the number of babies a person will give birth to. * @param multiplePregnancyOccurrences the X occurrences for there to be a single multiple - * child occurrence (i.e. 1 in X) + * child occurrence (i.e., 1 in X) * @return the number of babies the person will give birth to, limited to decuplets */ protected int determineNumberOfBabies(final int multiplePregnancyOccurrences) { @@ -138,7 +138,6 @@ protected int determineNumberOfBabies(final int multiplePregnancyOccurrences) { /** * This method determines the duration for a pregnancy, with a variance determined through a * Gaussian distribution with a maximum spread of approximately six weeks. - * * TODO : Swap me to instead use a distribution function that generates an overall length, * TODO : Including pre-term and post-term births * @@ -149,8 +148,8 @@ private int determinePregnancyDuration() { // pregnancy duration to create a randomized pregnancy duration final double gaussian = Math.sqrt(-2.0 * Math.log(Math.random())) * Math.cos(2.0 * Math.PI * Math.random()); - // To not get weird results, we limit the variance to +/- 4.0 (almost 6 weeks). A base - // length of 268 creates a solid enough duration for now. + // To not get unusual results, we limit the variance to +/- 4.0 (almost 6 weeks). + // A base length of 268 creates a solid enough duration for now. return 268 + (int) Math.round(MathUtility.clamp(gaussian, -4d, 4d) * 10.0); } @@ -251,7 +250,7 @@ public void addPregnancy(final Campaign campaign, final LocalDate today, final P /** * This method is how a person becomes pregnant with the specified number of children. They have - * their due date set and the parentage of the pregnancy determined. + * their due date set, and the parentage of the pregnancy is determined. * * @param campaign the campaign the person is a part of * @param today the current date @@ -321,7 +320,7 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m // Create Babies for (int i = 0; i < size; i++) { - // Create the specific baby + // Create a baby final Person baby = campaign.newDependent(true); baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle() .generateBabySurname(mother, father, baby.getGender())); @@ -388,35 +387,47 @@ public void processPregnancyComplications(final Campaign campaign, final LocalDa final Person person) { // The child might be able to be born, albeit into a world without their mother. // The status, however, can be manually set for males and for those who are not pregnant. - // This is purposeful, to allow for player customization, and thus we first check if they + // This is purposeful to allow for player customization, and thus we first check if they // are pregnant before checking if the birth occurs if (!person.isPregnant()) { return; } final int pregnancyWeek = determinePregnancyWeek(today, person); - final double babyBornChance; - if (pregnancyWeek > 35) { - babyBornChance = 0.99; - } else if (pregnancyWeek > 29) { - babyBornChance = 0.95; - } else if (pregnancyWeek > 25) { - babyBornChance = 0.9; - } else if (pregnancyWeek == 25) { - babyBornChance = 0.8; - } else if (pregnancyWeek == 24) { - babyBornChance = 0.5; - } else if (pregnancyWeek == 23) { - babyBornChance = 0.25; - } else { - babyBornChance = 0.0; - } + final double babyBornChance = getBabyBornChance(pregnancyWeek); - if (Compute.randomFloat() < babyBornChance) { + if (Compute.randomInt() < babyBornChance) { birth(campaign, today, person); } } + /** + * Calculates the chance of a baby being born based on the pregnancy week. + * + * @param pregnancyWeek the week of the pregnancy + * @return the chance of a baby being born, ranging from 0.0 to 1.0 + */ + private static double getBabyBornChance(int pregnancyWeek) { + int range = switch (pregnancyWeek) { + case 23 -> 1; + case 24 -> 2; + case 25 -> 3; + default -> (pregnancyWeek > 25 && pregnancyWeek <= 29) ? 4 : + (pregnancyWeek > 29 && pregnancyWeek <=35) ? 5 : + (pregnancyWeek > 35) ? 6 : 0; + }; + + return switch (range) { + case 1 -> 0.25; + case 2 -> 0.5; + case 3 -> 0.8; + case 4 -> 0.9; + case 5 -> 0.95; + case 6 -> 0.99; + default -> 0.0; + }; + } + //region New Day /** * Process new day procreation for an individual @@ -447,7 +458,7 @@ public void processNewDay(final Campaign campaign, final LocalDate today, final //region Random Procreation /** - * Determines if a non-pregnant female person procreates on a given day + * Determines if a non-pregnant woman procreates on a given day * @param today the current day * @param person the person in question * @return true if they do, otherwise false @@ -455,12 +466,8 @@ public void processNewDay(final Campaign campaign, final LocalDate today, final protected boolean randomlyProcreates(final LocalDate today, final Person person) { if (canProcreate(today, person, true) != null) { return false; - } else if (person.getGenealogy().hasSpouse()) { - return relationshipProcreation(person); - } else if (isUseRelationshiplessProcreation()) { - return relationshiplessProcreation(person); } else { - return false; + return procreation(person); } } @@ -469,14 +476,5 @@ protected boolean randomlyProcreates(final LocalDate today, final Person person) * @param person the person to determine for * @return true if they do, otherwise false */ - protected abstract boolean relationshipProcreation(final Person person); - - /** - * Determines if a person without a partner procreates - * @param person the person to determine for - * @return true if they do, otherwise false - */ - protected abstract boolean relationshiplessProcreation(final Person person); - //endregion Random Procreation - //endregion New Day + protected abstract boolean procreation(final Person person); } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java index 2f729cc609..78d096c32f 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java @@ -37,12 +37,7 @@ protected boolean randomlyProcreates(final LocalDate today, final Person person) } @Override - protected boolean relationshipProcreation(final Person person) { - return false; - } - - @Override - protected boolean relationshiplessProcreation(final Person person) { + protected boolean procreation(final Person person) { return false; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/PercentageRandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/PercentageRandomProcreation.java deleted file mode 100644 index 513729917c..0000000000 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/PercentageRandomProcreation.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2021 - The MegaMek Team. All Rights Reserved. - * - * This file is part of MekHQ. - * - * MekHQ is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * MekHQ is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with MekHQ. If not, see . - */ -package mekhq.campaign.personnel.procreation; - -import megamek.common.Compute; -import mekhq.campaign.CampaignOptions; -import mekhq.campaign.personnel.Person; -import mekhq.campaign.personnel.enums.RandomProcreationMethod; - -public class PercentageRandomProcreation extends AbstractProcreation { - //region Variable Declarations - private double percentage; - private double relationshiplessPercentage; - //endregion Variable Declarations - - //region Constructors - public PercentageRandomProcreation(final CampaignOptions options) { - super(RandomProcreationMethod.PERCENTAGE, options); - setPercentage(options.getPercentageRandomProcreationRelationshipChance()); - setRelationshiplessPercentage(options.getPercentageRandomProcreationRelationshiplessChance()); - } - //endregion Constructors - - //region Getters/Setters - public double getPercentage() { - return percentage; - } - - public void setPercentage(final double percentage) { - this.percentage = percentage; - } - - public double getRelationshiplessPercentage() { - return relationshiplessPercentage; - } - - public void setRelationshiplessPercentage(final double relationshiplessPercentage) { - this.relationshiplessPercentage = relationshiplessPercentage; - } - //endregion Getters/Setters - - @Override - protected boolean relationshipProcreation(final Person person) { - return Compute.randomFloat() < getPercentage(); - } - - @Override - protected boolean relationshiplessProcreation(final Person person) { - return Compute.randomFloat() < getRelationshiplessPercentage(); - } -} diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java new file mode 100644 index 0000000000..c21cac49d0 --- /dev/null +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 - The MegaMek Team. All Rights Reserved. + * + * This file is part of MekHQ. + * + * MekHQ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MekHQ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MekHQ. If not, see . + */ +package mekhq.campaign.personnel.procreation; + +import megamek.common.Compute; +import mekhq.campaign.CampaignOptions; +import mekhq.campaign.personnel.Person; +import mekhq.campaign.personnel.enums.RandomProcreationMethod; + +public class randomProcreation extends AbstractProcreation { + //region Variable Declarations + private int relationshipDieSize; + private int relationshiplessDieSize; + //endregion Variable Declarations + + //region Constructors + public randomProcreation(final CampaignOptions options) { + super(RandomProcreationMethod.DICE_ROLL, options); + setRelationshipDieSize(options.getRandomProcreationRelationshipDiceSize()); + setRelationshiplessDieSize(options.getRandomProcreationRelationshiplessDiceSize()); + } + //endregion Constructors + + //region Getters/Setters + @SuppressWarnings(value = "unused") + public double getRelationshipDieSize() { + return relationshipDieSize; + } + + @SuppressWarnings(value = "unused") + public void setRelationshipDieSize(final int relationshipDieSize) { + this.relationshipDieSize = relationshipDieSize; + } + + @SuppressWarnings(value = "unused") + public double getRelationshiplessDieSize() { + return relationshiplessDieSize; + } + + @SuppressWarnings(value = "unused") + public void setRelationshiplessDieSize(final int relationshiplessDieSize) { + this.relationshiplessDieSize = relationshiplessDieSize; + } + //endregion Getters/Setters + + @Override + protected boolean procreation(final Person person) { + int diceSize = person.getGenealogy().hasSpouse() ? relationshipDieSize : relationshiplessDieSize; + int multiplier = Math.max(1, person.getGenealogy().getChildren().size()); + + return Compute.randomInt(diceSize * multiplier) == 0; + } +} diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index 04bcc237c6..ebcbb8ae8d 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -21,38 +21,6 @@ */ package mekhq.gui; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.nio.charset.StandardCharsets; -import java.time.format.DateTimeFormatter; -import java.util.*; -import java.util.List; -import java.util.stream.IntStream; -import java.util.zip.GZIPOutputStream; - -import javax.swing.*; -import javax.swing.UIManager.LookAndFeelInfo; -import javax.xml.parsers.DocumentBuilder; - -import org.apache.logging.log4j.LogManager; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.client.generator.RandomUnitGenerator; import megamek.client.ui.preferences.JWindowPreference; @@ -61,20 +29,11 @@ import megamek.client.ui.swing.UnitLoadingDialog; import megamek.client.ui.swing.dialog.AbstractUnitSelectorDialog; import megamek.client.ui.swing.util.UIUtil; -import megamek.common.Dropship; -import megamek.common.Entity; -import megamek.common.Jumpship; -import megamek.common.MULParser; -import megamek.common.MechSummaryCache; +import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.event.Subscribe; import megamek.common.loaders.EntityLoadingException; -import mekhq.IconPackage; -import mekhq.MHQConstants; -import mekhq.MHQOptionsChangedEvent; -import mekhq.MHQStaticDirectoryManager; -import mekhq.MekHQ; -import mekhq.Utilities; +import mekhq.*; import mekhq.campaign.Campaign; import mekhq.campaign.CampaignController; import mekhq.campaign.CampaignOptions; @@ -95,14 +54,10 @@ import mekhq.campaign.personnel.death.ExponentialRandomDeath; import mekhq.campaign.personnel.death.PercentageRandomDeath; import mekhq.campaign.personnel.divorce.PercentageRandomDivorce; -import mekhq.campaign.personnel.enums.PersonnelRole; -import mekhq.campaign.personnel.enums.RandomDeathMethod; -import mekhq.campaign.personnel.enums.RandomDivorceMethod; -import mekhq.campaign.personnel.enums.RandomMarriageMethod; -import mekhq.campaign.personnel.enums.RandomProcreationMethod; +import mekhq.campaign.personnel.enums.*; import mekhq.campaign.personnel.marriage.PercentageRandomMarriage; import mekhq.campaign.personnel.procreation.AbstractProcreation; -import mekhq.campaign.personnel.procreation.PercentageRandomProcreation; +import mekhq.campaign.personnel.procreation.randomProcreation; import mekhq.campaign.personnel.ranks.RankSystem; import mekhq.campaign.personnel.ranks.Ranks; import mekhq.campaign.report.CargoReport; @@ -114,12 +69,7 @@ import mekhq.gui.dialog.*; import mekhq.gui.dialog.CampaignExportWizard.CampaignExportWizardState; import mekhq.gui.dialog.nagDialogs.*; -import mekhq.gui.dialog.reportDialogs.CargoReportDialog; -import mekhq.gui.dialog.reportDialogs.HangarReportDialog; -import mekhq.gui.dialog.reportDialogs.NewsReportDialog; -import mekhq.gui.dialog.reportDialogs.PersonnelReportDialog; -import mekhq.gui.dialog.reportDialogs.TransportReportDialog; -import mekhq.gui.dialog.reportDialogs.UnitRatingReportDialog; +import mekhq.gui.dialog.reportDialogs.*; import mekhq.gui.enums.MHQTabType; import mekhq.gui.model.PartsTableModel; import mekhq.io.FileType; @@ -136,7 +86,6 @@ import java.awt.*; import java.awt.event.*; import java.io.*; -import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; @@ -1570,11 +1519,11 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { getCampaign().getProcreation() .setUseRandomClanPersonnelProcreation(newOptions.isUseRandomClanPersonnelProcreation()); getCampaign().getProcreation().setUseRandomPrisonerProcreation(newOptions.isUseRandomPrisonerProcreation()); - if (getCampaign().getProcreation().getMethod().isPercentage()) { - ((PercentageRandomProcreation) getCampaign().getProcreation()).setPercentage( - newOptions.getPercentageRandomProcreationRelationshipChance()); - ((PercentageRandomProcreation) getCampaign().getProcreation()).setRelationshiplessPercentage( - newOptions.getPercentageRandomProcreationRelationshiplessChance()); + if (getCampaign().getProcreation().getMethod().isDiceRoll()) { + ((randomProcreation) getCampaign().getProcreation()).setRelationshipDieSize( + newOptions.getRandomProcreationRelationshipDiceSize()); + ((randomProcreation) getCampaign().getProcreation()).setRelationshiplessDieSize( + newOptions.getRandomProcreationRelationshiplessDiceSize()); } } diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index be0cc86e9d..304571029f 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -95,6 +95,8 @@ import java.util.Map.Entry; import java.util.stream.IntStream; +import static megamek.client.ui.WrapLayout.wordWrap; + /** * @author Justin 'Windchild' Bowen */ @@ -407,9 +409,9 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseRelationshiplessRandomProcreation; private JCheckBox chkUseRandomClanPersonnelProcreation; private JCheckBox chkUseRandomPrisonerProcreation; - private JSpinner spnPercentageRandomProcreationRelationshipChance; - private JLabel lblPercentageRandomProcreationRelationshiplessChance; - private JSpinner spnPercentageRandomProcreationRelationshiplessChance; + private JSpinner spnRandomProcreationRelationshipDiceSize; + private JLabel lblRandomProcreationRelationshiplessDiceSize; + private JSpinner spnRandomProcreationRelationshiplessDiceSize; // Awards private MMComboBox comboAwardBonusStyle; @@ -6542,14 +6544,14 @@ public Component getListCellRendererComponent(final JList list, final Object return; } final boolean enabled = !method.isNone(); - final boolean percentageEnabled = method.isPercentage(); + final boolean percentageEnabled = method.isDiceRoll(); final boolean relationshiplessEnabled = enabled && chkUseRelationshiplessRandomProcreation.isSelected(); chkUseRelationshiplessRandomProcreation.setEnabled(enabled); chkUseRandomClanPersonnelProcreation.setEnabled(enabled && chkUseClanPersonnelProcreation.isSelected()); chkUseRandomPrisonerProcreation.setEnabled(enabled && chkUsePrisonerProcreation.isSelected()); percentageRandomProcreationPanel.setEnabled(percentageEnabled); - lblPercentageRandomProcreationRelationshiplessChance.setEnabled(relationshiplessEnabled && percentageEnabled); - spnPercentageRandomProcreationRelationshiplessChance.setEnabled(relationshiplessEnabled && percentageEnabled); + lblRandomProcreationRelationshiplessDiceSize.setEnabled(relationshiplessEnabled && percentageEnabled); + spnRandomProcreationRelationshiplessDiceSize.setEnabled(relationshiplessEnabled && percentageEnabled); }); chkUseRelationshiplessRandomProcreation = new JCheckBox(resources.getString("chkUseRelationshiplessRandomProcreation.text")); @@ -6562,9 +6564,9 @@ public Component getListCellRendererComponent(final JList list, final Object } final boolean sameSexEnabled = chkUseRelationshiplessRandomProcreation.isEnabled() && chkUseRelationshiplessRandomProcreation.isSelected(); - final boolean percentageEnabled = sameSexEnabled && method.isPercentage(); - lblPercentageRandomProcreationRelationshiplessChance.setEnabled(percentageEnabled); - spnPercentageRandomProcreationRelationshiplessChance.setEnabled(percentageEnabled); + final boolean percentageEnabled = sameSexEnabled && method.isDiceRoll(); + lblRandomProcreationRelationshiplessDiceSize.setEnabled(percentageEnabled); + spnRandomProcreationRelationshiplessDiceSize.setEnabled(percentageEnabled); }); chkUseRandomClanPersonnelProcreation = new JCheckBox(resources.getString("chkUseRandomClanPersonnelProcreation.text")); @@ -6617,29 +6619,29 @@ public Component getListCellRendererComponent(final JList list, final Object private void createPercentageRandomProcreationPanel(final JPanel panel) { // Create Panel Components - final JLabel lblPercentageRandomProcreationRelationshipChance = new JLabel(resources.getString("lblPercentageRandomProcreationRelationshipChance.text")); - lblPercentageRandomProcreationRelationshipChance.setToolTipText(resources.getString("lblPercentageRandomProcreationRelationshipChance.toolTipText")); - lblPercentageRandomProcreationRelationshipChance.setName("lblPercentageRandomProcreationRelationshipChance"); + final JLabel lblRandomProcreationRelationshipDiceSize = new JLabel(resources.getString("lblRandomProcreationRelationshipDiceSize.text")); + lblRandomProcreationRelationshipDiceSize.setToolTipText(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText")); + lblRandomProcreationRelationshipDiceSize.setName("lblRandomProcreationRelationshipDiceSize"); - spnPercentageRandomProcreationRelationshipChance = new JSpinner(new SpinnerNumberModel(0, 0, 100, 0.001)); - spnPercentageRandomProcreationRelationshipChance.setToolTipText(resources.getString("lblPercentageRandomProcreationRelationshipChance.toolTipText")); - spnPercentageRandomProcreationRelationshipChance.setName("spnPercentageRandomProcreationRelationshipChance"); + spnRandomProcreationRelationshipDiceSize = new JSpinner(new SpinnerNumberModel(621, 0, 100000, 1)); + spnRandomProcreationRelationshipDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"), 100)); + spnRandomProcreationRelationshipDiceSize.setName("spnRandomProcreationRelationshipDiceSize"); - lblPercentageRandomProcreationRelationshiplessChance = new JLabel(resources.getString("lblPercentageRandomProcreationRelationshiplessChance.text")); - lblPercentageRandomProcreationRelationshiplessChance.setToolTipText(resources.getString("lblPercentageRandomProcreationRelationshiplessChance.toolTipText")); - lblPercentageRandomProcreationRelationshiplessChance.setName("lblPercentageRandomProcreationRelationshiplessChance"); + lblRandomProcreationRelationshiplessDiceSize = new JLabel(resources.getString("lblRandomProcreationRelationshiplessDiceSize.text")); + lblRandomProcreationRelationshiplessDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshiplessDiceSize.toolTipText"), 100)); + lblRandomProcreationRelationshiplessDiceSize.setName("lblRandomProcreationRelationshiplessDiceSize"); - spnPercentageRandomProcreationRelationshiplessChance = new JSpinner(new SpinnerNumberModel(0, 0, 100, 0.001)); - spnPercentageRandomProcreationRelationshiplessChance.setToolTipText(resources.getString("lblPercentageRandomProcreationRelationshiplessChance.toolTipText")); - spnPercentageRandomProcreationRelationshiplessChance.setName("spnPercentageRandomProcreationRelationshiplessChance"); + spnRandomProcreationRelationshiplessDiceSize = new JSpinner(new SpinnerNumberModel(1861, 0, 100000, 1)); + spnRandomProcreationRelationshiplessDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"), 100)); + spnRandomProcreationRelationshiplessDiceSize.setName("spnRandomProcreationRelationshiplessDiceSize"); // Programmatically Assign Accessibility Labels - lblPercentageRandomProcreationRelationshipChance.setLabelFor(spnPercentageRandomProcreationRelationshipChance); - lblPercentageRandomProcreationRelationshiplessChance.setLabelFor(spnPercentageRandomProcreationRelationshiplessChance); + lblRandomProcreationRelationshipDiceSize.setLabelFor(spnRandomProcreationRelationshipDiceSize); + lblRandomProcreationRelationshiplessDiceSize.setLabelFor(spnRandomProcreationRelationshipDiceSize); // Layout the Panel panel.setBorder(BorderFactory.createTitledBorder(resources.getString("percentageRandomProcreationPanel.title"))); - panel.setToolTipText(RandomProcreationMethod.PERCENTAGE.getToolTipText()); + panel.setToolTipText(RandomProcreationMethod.DICE_ROLL.getToolTipText()); final GroupLayout layout = new GroupLayout(panel); layout.setAutoCreateGaps(true); @@ -6649,21 +6651,21 @@ private void createPercentageRandomProcreationPanel(final JPanel panel) { layout.setVerticalGroup( layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblPercentageRandomProcreationRelationshipChance) - .addComponent(spnPercentageRandomProcreationRelationshipChance, Alignment.LEADING)) + .addComponent(lblRandomProcreationRelationshipDiceSize) + .addComponent(spnRandomProcreationRelationshipDiceSize, Alignment.LEADING)) .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblPercentageRandomProcreationRelationshiplessChance) - .addComponent(spnPercentageRandomProcreationRelationshiplessChance, Alignment.LEADING)) + .addComponent(lblRandomProcreationRelationshiplessDiceSize) + .addComponent(spnRandomProcreationRelationshiplessDiceSize, Alignment.LEADING)) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(lblPercentageRandomProcreationRelationshipChance) - .addComponent(spnPercentageRandomProcreationRelationshipChance)) + .addComponent(lblRandomProcreationRelationshipDiceSize) + .addComponent(spnRandomProcreationRelationshipDiceSize)) .addGroup(layout.createSequentialGroup() - .addComponent(lblPercentageRandomProcreationRelationshiplessChance) - .addComponent(spnPercentageRandomProcreationRelationshiplessChance)) + .addComponent(lblRandomProcreationRelationshiplessDiceSize) + .addComponent(spnRandomProcreationRelationshiplessDiceSize)) ); } @@ -6847,7 +6849,7 @@ private void createPercentageRandomDeathPanel(final JPanel panel) { // Layout the Panel panel.setBorder(BorderFactory.createTitledBorder(resources.getString("percentageRandomDeathPanel.title"))); - panel.setToolTipText(RandomProcreationMethod.PERCENTAGE.getToolTipText()); + panel.setToolTipText(RandomProcreationMethod.DICE_ROLL.getToolTipText()); final GroupLayout layout = new GroupLayout(panel); layout.setAutoCreateGaps(true); @@ -8279,8 +8281,8 @@ public void setOptions(@Nullable CampaignOptions options, } chkUseRandomClanPersonnelProcreation.setSelected(options.isUseRandomClanPersonnelProcreation()); chkUseRandomPrisonerProcreation.setSelected(options.isUseRandomPrisonerProcreation()); - spnPercentageRandomProcreationRelationshipChance.setValue(options.getPercentageRandomProcreationRelationshipChance() * 100.0); - spnPercentageRandomProcreationRelationshiplessChance.setValue(options.getPercentageRandomProcreationRelationshiplessChance() * 100.0); + spnRandomProcreationRelationshipDiceSize.setValue(options.getRandomProcreationRelationshipDiceSize()); + spnRandomProcreationRelationshiplessDiceSize.setValue(options.getRandomProcreationRelationshiplessDiceSize()); // Education chkUseEducationModule.setSelected(options.isUseEducationModule()); @@ -8949,8 +8951,8 @@ public void updateOptions() { options.setUseRelationshiplessRandomProcreation(chkUseRelationshiplessRandomProcreation.isSelected()); options.setUseRandomClanPersonnelProcreation(chkUseRandomClanPersonnelProcreation.isSelected()); options.setUseRandomPrisonerProcreation(chkUseRandomPrisonerProcreation.isSelected()); - options.setPercentageRandomProcreationRelationshipChance((Double) spnPercentageRandomProcreationRelationshipChance.getValue() / 100.0); - options.setPercentageRandomProcreationRelationshiplessChance((Double) spnPercentageRandomProcreationRelationshiplessChance.getValue() / 100.0); + options.setRandomProcreationRelationshipDiceSize((Integer) spnRandomProcreationRelationshipDiceSize.getValue()); + options.setRandomProcreationRelationshiplessDiceSize((Integer) spnRandomProcreationRelationshiplessDiceSize.getValue()); // Education options.setUseEducationModule(chkUseEducationModule.isSelected()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java b/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java index bf4b1c288a..78156ffc99 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java @@ -65,22 +65,22 @@ public void testRandomlyDies() { // We're using the same percentages for all age ranges, so we only need to test Genders // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.39f); + compute.when(Compute::randomInt).thenReturn(0.39f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.40f); + compute.when(Compute::randomInt).thenReturn(0.40f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.49f); + compute.when(Compute::randomInt).thenReturn(0.49f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.5f); + compute.when(Compute::randomInt).thenReturn(0.5f); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java b/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java index 149e23b761..e7d77bef94 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java @@ -54,27 +54,27 @@ public void beforeEach() { public void testRandomlyDies() { final ExponentialRandomDeath exponentialRandomDeath = new ExponentialRandomDeath(mockOptions, false); try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(exponentialRandomDeath.randomlyDies(0, Gender.MALE)); assertTrue(exponentialRandomDeath.randomlyDies(0, Gender.FEMALE)); assertTrue(exponentialRandomDeath.randomlyDies(50, Gender.MALE)); assertTrue(exponentialRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.000001f); + compute.when(Compute::randomInt).thenReturn(0.000001f); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.0000692f); + compute.when(Compute::randomInt).thenReturn(0.0000692f); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.0000694f); + compute.when(Compute::randomInt).thenReturn(0.0000694f); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.000111f); + compute.when(Compute::randomInt).thenReturn(0.000111f); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(0.000112f); + compute.when(Compute::randomInt).thenReturn(0.000112f); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.FEMALE)); assertFalse(exponentialRandomDeath.randomlyDies(50, Gender.MALE)); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java b/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java index 1096281654..b6157dffcf 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java @@ -55,13 +55,13 @@ public void testRandomlyDies() { // This ignores age and gender, so just using 50 and Male. // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(percentageRandomDeath.randomlyDies(50, Gender.MALE)); - compute.when(Compute::randomFloat).thenReturn(0.49f); + compute.when(Compute::randomInt).thenReturn(0.49f); assertTrue(percentageRandomDeath.randomlyDies(50, Gender.MALE)); - compute.when(Compute::randomFloat).thenReturn(0.5f); + compute.when(Compute::randomInt).thenReturn(0.5f); assertFalse(percentageRandomDeath.randomlyDies(50, Gender.MALE)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(percentageRandomDeath.randomlyDies(50, Gender.MALE)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java index 7ad64a7f29..43df2addc1 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java @@ -59,13 +59,13 @@ public void testRandomOppositeSexDivorce() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); + compute.when(Compute::randomInt).thenReturn(0.49f); assertTrue(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); + compute.when(Compute::randomInt).thenReturn(0.5f); assertFalse(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); } } @@ -76,13 +76,13 @@ public void testRandomSameSexDivorce() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); + compute.when(Compute::randomInt).thenReturn(0.49f); assertTrue(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); + compute.when(Compute::randomInt).thenReturn(0.5f); assertFalse(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java index 7156a5ea25..5db071803f 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java @@ -21,7 +21,7 @@ import mekhq.MekHQ; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.procreation.DisabledRandomProcreation; -import mekhq.campaign.personnel.procreation.PercentageRandomProcreation; +import mekhq.campaign.personnel.procreation.randomProcreation; import org.junit.jupiter.api.Test; import java.util.ResourceBundle; @@ -46,8 +46,8 @@ public class RandomProcreationMethodTest { public void testGetToolTipText() { assertEquals(resources.getString("RandomProcreationMethod.NONE.toolTipText"), RandomProcreationMethod.NONE.getToolTipText()); - assertEquals(resources.getString("RandomProcreationMethod.PERCENTAGE.toolTipText"), - RandomProcreationMethod.PERCENTAGE.getToolTipText()); + assertEquals(resources.getString("RandomProcreationMethod.DICE_ROLL.toolTipText"), + RandomProcreationMethod.DICE_ROLL.getToolTipText()); } //endregion Getters @@ -66,10 +66,10 @@ public void testIsNone() { @Test public void testIsPercentage() { for (final RandomProcreationMethod randomProcreationMethod : methods) { - if (randomProcreationMethod == RandomProcreationMethod.PERCENTAGE) { - assertTrue(randomProcreationMethod.isPercentage()); + if (randomProcreationMethod == RandomProcreationMethod.DICE_ROLL) { + assertTrue(randomProcreationMethod.isDiceRoll()); } else { - assertFalse(randomProcreationMethod.isPercentage()); + assertFalse(randomProcreationMethod.isDiceRoll()); } } } @@ -83,18 +83,18 @@ public void testGetMethod() { when(mockOptions.isUseRelationshiplessRandomProcreation()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelProcreation()).thenReturn(false); when(mockOptions.isUseRandomPrisonerProcreation()).thenReturn(false); - when(mockOptions.getPercentageRandomProcreationRelationshipChance()).thenReturn(0.5); - when(mockOptions.getPercentageRandomProcreationRelationshiplessChance()).thenReturn(0.5); + when(mockOptions.getRandomProcreationRelationshipDiceSize()).thenReturn(5); + when(mockOptions.getRandomProcreationRelationshiplessDiceSize()).thenReturn(5); assertInstanceOf(DisabledRandomProcreation.class, RandomProcreationMethod.NONE.getMethod(mockOptions)); - assertInstanceOf(PercentageRandomProcreation.class, RandomProcreationMethod.PERCENTAGE.getMethod(mockOptions)); + assertInstanceOf(randomProcreation.class, RandomProcreationMethod.DICE_ROLL.getMethod(mockOptions)); } @Test public void testToStringOverride() { assertEquals(resources.getString("RandomProcreationMethod.NONE.text"), RandomProcreationMethod.NONE.toString()); - assertEquals(resources.getString("RandomProcreationMethod.PERCENTAGE.text"), - RandomProcreationMethod.PERCENTAGE.toString()); + assertEquals(resources.getString("RandomProcreationMethod.DICE_ROLL.text"), + RandomProcreationMethod.DICE_ROLL.toString()); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java index 070edf7b8c..ceb2a5ec31 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java @@ -58,13 +58,13 @@ public void testRandomOppositeSexMarriage() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); + compute.when(Compute::randomInt).thenReturn(0.49f); assertTrue(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); + compute.when(Compute::randomInt).thenReturn(0.5f); assertFalse(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); } } @@ -75,13 +75,13 @@ public void testRandomSameSexMarriage() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); + compute.when(Compute::randomInt).thenReturn(0f); assertTrue(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); + compute.when(Compute::randomInt).thenReturn(0.49f); assertTrue(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); + compute.when(Compute::randomInt).thenReturn(0.5f); assertFalse(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); + compute.when(Compute::randomInt).thenReturn(1f); assertFalse(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java index 4512439ee4..dda6e51ac3 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java @@ -407,7 +407,7 @@ public void testProcessPregnancyComplications() { final Person mockPerson = mock(Person.class); try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0.24f); + compute.when(Compute::randomInt).thenReturn(0.24f); when(mockPerson.isPregnant()).thenReturn(false); mockProcreation.processPregnancyComplications(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); @@ -494,18 +494,19 @@ public void testRandomlyProcreates() { when(mockProcreation.canProcreate(any(), any(), anyBoolean())).thenReturn("Pregnant"); assertFalse(mockProcreation.randomlyProcreates(LocalDate.ofYearDay(3025, 1), person)); + reset(mockProcreation); + doCallRealMethod().when(mockProcreation).randomlyProcreates(any(), any()); + when(mockProcreation.canProcreate(any(), any(), anyBoolean())).thenReturn(null); when(mockProcreation.isUseRelationshiplessProcreation()).thenReturn(false); assertFalse(mockProcreation.randomlyProcreates(LocalDate.ofYearDay(3025, 1), person)); - when(mockProcreation.isUseRelationshiplessProcreation()).thenReturn(true); - when(mockProcreation.relationshiplessProcreation(any())).thenReturn(true); - assertTrue(mockProcreation.randomlyProcreates(LocalDate.ofYearDay(3025, 1), person)); + reset(mockProcreation); + doCallRealMethod().when(mockProcreation).randomlyProcreates(any(), any()); person.getGenealogy().setSpouse(mock(Person.class)); - when(mockProcreation.relationshipProcreation(any())).thenReturn(true); + when(mockProcreation.canProcreate(any(), any(), anyBoolean())).thenReturn(null); + when(mockProcreation.procreation(any())).thenReturn(true); assertTrue(mockProcreation.randomlyProcreates(LocalDate.ofYearDay(3025, 1), person)); } - //endregion Random Procreation - //endregion New Day } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java index 41470c0a69..6a92556dae 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java @@ -55,11 +55,6 @@ public void testRandomlyProcreates() { @Test public void testRandomlyDies() { - assertFalse(new DisabledRandomProcreation(mockOptions).relationshipProcreation(mockPerson)); - } - - @Test - public void testRelationshiplessProcreation() { - assertFalse(new DisabledRandomProcreation(mockOptions).relationshiplessProcreation(mockPerson)); + assertFalse(new DisabledRandomProcreation(mockOptions).procreation(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/PercentageRandomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/PercentageRandomProcreationTest.java deleted file mode 100644 index 9a322d582f..0000000000 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/PercentageRandomProcreationTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. - * - * This file is part of MekHQ. - * - * MekHQ is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * MekHQ is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with MekHQ. If not, see . - */ -package mekhq.campaign.personnel.procreation; - -import megamek.common.Compute; -import mekhq.campaign.CampaignOptions; -import mekhq.campaign.personnel.Person; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.when; - -@ExtendWith(value = MockitoExtension.class) -public class PercentageRandomProcreationTest { - @Mock - private CampaignOptions mockOptions; - - @Mock - private Person mockPerson; - - @BeforeEach - public void beforeEach() { - when(mockOptions.isUseClanPersonnelProcreation()).thenReturn(false); - when(mockOptions.isUsePrisonerProcreation()).thenReturn(false); - when(mockOptions.isUseRelationshiplessRandomProcreation()).thenReturn(false); - when(mockOptions.isUseRandomClanPersonnelProcreation()).thenReturn(false); - when(mockOptions.isUseRandomPrisonerProcreation()).thenReturn(false); - when(mockOptions.getPercentageRandomProcreationRelationshipChance()).thenReturn(0.5); - when(mockOptions.getPercentageRandomProcreationRelationshiplessChance()).thenReturn(0.5); - } - - @Test - public void testRelationshipProcreation() { - final PercentageRandomProcreation percentageRandomProcreation = new PercentageRandomProcreation(mockOptions); - // This ignores the person, so just using a mocked person - // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) - try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); - assertTrue(percentageRandomProcreation.relationshipProcreation(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); - assertTrue(percentageRandomProcreation.relationshipProcreation(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); - assertFalse(percentageRandomProcreation.relationshipProcreation(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); - assertFalse(percentageRandomProcreation.relationshipProcreation(mockPerson)); - } - } - - @Test - public void testRelationshiplessProcreation() { - final PercentageRandomProcreation percentageRandomProcreation = new PercentageRandomProcreation(mockOptions); - // This ignores the person, so just using a mocked person - // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) - try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); - assertTrue(percentageRandomProcreation.relationshiplessProcreation(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); - assertTrue(percentageRandomProcreation.relationshiplessProcreation(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); - assertFalse(percentageRandomProcreation.relationshiplessProcreation(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); - assertFalse(percentageRandomProcreation.relationshiplessProcreation(mockPerson)); - } - } -} diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java new file mode 100644 index 0000000000..455e2cf08b --- /dev/null +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * + * This file is part of MekHQ. + * + * MekHQ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MekHQ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MekHQ. If not, see . + */ +package mekhq.campaign.personnel.procreation; + +import megamek.common.Compute; +import mekhq.campaign.CampaignOptions; +import mekhq.campaign.personnel.Person; +import mekhq.campaign.personnel.familyTree.Genealogy; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ExtendWith(value = MockitoExtension.class) +public class randomProcreationTest { + @Mock + private CampaignOptions mockOptions; + + @Mock + private Person mockPerson; + + @BeforeEach + public void beforeEach() { + when(mockOptions.isUseClanPersonnelProcreation()).thenReturn(false); + when(mockOptions.isUsePrisonerProcreation()).thenReturn(false); + when(mockOptions.isUseRelationshiplessRandomProcreation()).thenReturn(false); + when(mockOptions.isUseRandomClanPersonnelProcreation()).thenReturn(false); + when(mockOptions.isUseRandomPrisonerProcreation()).thenReturn(false); + when(mockOptions.getRandomProcreationRelationshipDiceSize()).thenReturn(5); + when(mockOptions.getRandomProcreationRelationshiplessDiceSize()).thenReturn(5); + } + + @Test + public void testProcreation() { + final randomProcreation randomProcreation = new randomProcreation(mockOptions); + Genealogy mockGenealogy = mock(Genealogy.class); + + when(mockGenealogy.hasSpouse()).thenReturn(true); + when(mockGenealogy.getChildren()).thenReturn(new ArrayList<>(Collections.singleton(mock(Person.class)))); + + // Make sure getGenealogy returns mocked Genealogy + when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); + + // Assuming diceSize and multiplier are defined... + int diceSize = 5; + int multiplier = 1; + + try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { + compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(0); + assertTrue(randomProcreation.procreation(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(1); + assertFalse(randomProcreation.procreation(mockPerson)); + } + } +} From 532fc807b674c3ed92d06e4c62c51ae73f90a2be Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 15:00:51 -0500 Subject: [PATCH 04/41] Rolled Back accidental switch from `randomFloat` to `randomInt` in tests and codebase --- .../personnel/death/AgeRangeRandomDeath.java | 2 +- .../personnel/death/ExponentialRandomDeath.java | 2 +- .../personnel/death/PercentageRandomDeath.java | 2 +- .../divorce/PercentageRandomDivorce.java | 4 ++-- .../marriage/PercentageRandomMarriage.java | 4 ++-- .../procreation/AbstractProcreation.java | 2 +- .../personnel/death/AgeRangeRandomDeathTest.java | 12 ++++++------ .../death/ExponentialRandomDeathTest.java | 14 +++++++------- .../death/PercentageRandomDeathTest.java | 8 ++++---- .../divorce/PercentageRandomDivorceTest.java | 16 ++++++++-------- .../marriage/PercentageRandomMarriageTest.java | 16 ++++++++-------- .../procreation/AbstractProcreationTest.java | 2 +- .../DisabledRandomProcreationTest.java | 5 +++++ ...ationTest.java => RandomProcreationTest.java} | 2 +- 14 files changed, 48 insertions(+), 43 deletions(-) rename MekHQ/unittests/mekhq/campaign/personnel/procreation/{randomProcreationTest.java => RandomProcreationTest.java} (98%) diff --git a/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java index 4454342aa7..4f9f59315a 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/AgeRangeRandomDeath.java @@ -81,6 +81,6 @@ public void adjustRangeValues(final CampaignOptions options) { @Override public boolean randomlyDies(final int age, final Gender gender) { final TenYearAgeRange ageRange = TenYearAgeRange.determineAgeRange(age); - return Compute.randomInt() < ((gender.isMale() ? getMale() : getFemale()).get(ageRange)); + return Compute.randomFloat() < ((gender.isMale() ? getMale() : getFemale()).get(ageRange)); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java index 5dcb2b3a90..a3a65ce270 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/ExponentialRandomDeath.java @@ -64,7 +64,7 @@ public void setFemale(final double... female) { */ @Override public boolean randomlyDies(final int age, final Gender gender) { - return Compute.randomInt() < (gender.isMale() + return Compute.randomFloat() < (gender.isMale() ? (getMale()[0] * Math.pow(10, getMale()[1]) * Math.exp(getMale()[2] * age)) : (getFemale()[0] * Math.pow(10, getFemale()[1]) * Math.exp(getFemale()[2] * age))); } diff --git a/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java index 7395407ba4..e097f00668 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/PercentageRandomDeath.java @@ -47,6 +47,6 @@ public void setPercentage(final double percentage) { @Override public boolean randomlyDies(final int age, final Gender gender) { - return Compute.randomInt() < getPercentage(); + return Compute.randomFloat() < getPercentage(); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java index 149f22c64c..b4fd1e4591 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java @@ -57,11 +57,11 @@ public void setSameSexPercentage(final double sameSexPercentage) { @Override protected boolean randomOppositeSexDivorce(final Person person) { - return Compute.randomInt() < getOppositeSexPercentage(); + return Compute.randomFloat() < getOppositeSexPercentage(); } @Override protected boolean randomSameSexDivorce(final Person person) { - return Compute.randomInt() < getSameSexPercentage(); + return Compute.randomFloat() < getSameSexPercentage(); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java index be624d9fa9..f36c5f2218 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java @@ -57,11 +57,11 @@ public void setSameSexPercentage(final double sameSexPercentage) { @Override protected boolean randomOppositeSexMarriage(final Person person) { - return Compute.randomInt() < getOppositeSexPercentage(); + return Compute.randomFloat() < getOppositeSexPercentage(); } @Override protected boolean randomSameSexMarriage(final Person person) { - return Compute.randomInt() < getSameSexPercentage(); + return Compute.randomFloat() < getSameSexPercentage(); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 35acac0515..6de55f5b9d 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -396,7 +396,7 @@ public void processPregnancyComplications(final Campaign campaign, final LocalDa final int pregnancyWeek = determinePregnancyWeek(today, person); final double babyBornChance = getBabyBornChance(pregnancyWeek); - if (Compute.randomInt() < babyBornChance) { + if (Compute.randomFloat() < babyBornChance) { birth(campaign, today, person); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java b/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java index 78156ffc99..bf4b1c288a 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/death/AgeRangeRandomDeathTest.java @@ -65,22 +65,22 @@ public void testRandomlyDies() { // We're using the same percentages for all age ranges, so we only need to test Genders // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.39f); + compute.when(Compute::randomFloat).thenReturn(0.39f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.40f); + compute.when(Compute::randomFloat).thenReturn(0.40f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.49f); + compute.when(Compute::randomFloat).thenReturn(0.49f); assertTrue(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.5f); + compute.when(Compute::randomFloat).thenReturn(0.5f); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.MALE)); assertFalse(ageRangeRandomDeath.randomlyDies(50, Gender.FEMALE)); } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java b/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java index e7d77bef94..149e23b761 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/death/ExponentialRandomDeathTest.java @@ -54,27 +54,27 @@ public void beforeEach() { public void testRandomlyDies() { final ExponentialRandomDeath exponentialRandomDeath = new ExponentialRandomDeath(mockOptions, false); try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(exponentialRandomDeath.randomlyDies(0, Gender.MALE)); assertTrue(exponentialRandomDeath.randomlyDies(0, Gender.FEMALE)); assertTrue(exponentialRandomDeath.randomlyDies(50, Gender.MALE)); assertTrue(exponentialRandomDeath.randomlyDies(50, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.000001f); + compute.when(Compute::randomFloat).thenReturn(0.000001f); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.0000692f); + compute.when(Compute::randomFloat).thenReturn(0.0000692f); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.0000694f); + compute.when(Compute::randomFloat).thenReturn(0.0000694f); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.000111f); + compute.when(Compute::randomFloat).thenReturn(0.000111f); assertTrue(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(0.000112f); + compute.when(Compute::randomFloat).thenReturn(0.000112f); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(75, Gender.FEMALE)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.MALE)); assertFalse(exponentialRandomDeath.randomlyDies(0, Gender.FEMALE)); assertFalse(exponentialRandomDeath.randomlyDies(50, Gender.MALE)); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java b/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java index b6157dffcf..1096281654 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/death/PercentageRandomDeathTest.java @@ -55,13 +55,13 @@ public void testRandomlyDies() { // This ignores age and gender, so just using 50 and Male. // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(percentageRandomDeath.randomlyDies(50, Gender.MALE)); - compute.when(Compute::randomInt).thenReturn(0.49f); + compute.when(Compute::randomFloat).thenReturn(0.49f); assertTrue(percentageRandomDeath.randomlyDies(50, Gender.MALE)); - compute.when(Compute::randomInt).thenReturn(0.5f); + compute.when(Compute::randomFloat).thenReturn(0.5f); assertFalse(percentageRandomDeath.randomlyDies(50, Gender.MALE)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(percentageRandomDeath.randomlyDies(50, Gender.MALE)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java index 43df2addc1..7ad64a7f29 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java @@ -59,13 +59,13 @@ public void testRandomOppositeSexDivorce() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.49f); + compute.when(Compute::randomFloat).thenReturn(0.49f); assertTrue(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.5f); + compute.when(Compute::randomFloat).thenReturn(0.5f); assertFalse(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); } } @@ -76,13 +76,13 @@ public void testRandomSameSexDivorce() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.49f); + compute.when(Compute::randomFloat).thenReturn(0.49f); assertTrue(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.5f); + compute.when(Compute::randomFloat).thenReturn(0.5f); assertFalse(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java index ceb2a5ec31..070edf7b8c 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java @@ -58,13 +58,13 @@ public void testRandomOppositeSexMarriage() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.49f); + compute.when(Compute::randomFloat).thenReturn(0.49f); assertTrue(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.5f); + compute.when(Compute::randomFloat).thenReturn(0.5f); assertFalse(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); } } @@ -75,13 +75,13 @@ public void testRandomSameSexMarriage() { // This ignores the person, so just using a mocked person // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0f); + compute.when(Compute::randomFloat).thenReturn(0f); assertTrue(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.49f); + compute.when(Compute::randomFloat).thenReturn(0.49f); assertTrue(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomInt).thenReturn(0.5f); + compute.when(Compute::randomFloat).thenReturn(0.5f); assertFalse(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomInt).thenReturn(1f); + compute.when(Compute::randomFloat).thenReturn(1f); assertFalse(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java index dda6e51ac3..f8b5ec50a9 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java @@ -407,7 +407,7 @@ public void testProcessPregnancyComplications() { final Person mockPerson = mock(Person.class); try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomInt).thenReturn(0.24f); + compute.when(Compute::randomFloat).thenReturn(0.24f); when(mockPerson.isPregnant()).thenReturn(false); mockProcreation.processPregnancyComplications(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java index 6a92556dae..324a1dc6fb 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java @@ -57,4 +57,9 @@ public void testRandomlyProcreates() { public void testRandomlyDies() { assertFalse(new DisabledRandomProcreation(mockOptions).procreation(mockPerson)); } + + @Test + public void testRelationshiplessProcreation() { + assertFalse(new DisabledRandomProcreation(mockOptions).procreation(mockPerson)); + } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java similarity index 98% rename from MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java rename to MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java index 455e2cf08b..e42b95e3e2 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/randomProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java @@ -39,7 +39,7 @@ import static org.mockito.Mockito.when; @ExtendWith(value = MockitoExtension.class) -public class randomProcreationTest { +public class RandomProcreationTest { @Mock private CampaignOptions mockOptions; From b5ce81db5dc041319f7c9304afb8729a0d3ca2f2 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 15:05:08 -0500 Subject: [PATCH 05/41] Update the procreation process to weekly instead of daily Changed the procreation process to occur weekly instead of daily throughout the codebase. This will help reduce the advance day loan on larger campaigns. --- MekHQ/src/mekhq/campaign/Campaign.java | 6 ++++-- .../personnel/procreation/AbstractProcreation.java | 2 +- .../AbstractCompanyGenerator.java | 2 +- .../procreation/AbstractProcreationTest.java | 14 +++++++------- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 31bf6c2bd8..e95ae43e49 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -3469,7 +3469,9 @@ public void processNewDayPersonnel() { getDivorce().processNewDay(this, getLocalDate(), p); // Procreation - getProcreation().processNewDay(this, getLocalDate(), p); + if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { + getProcreation().processNewWeek(this, getLocalDate(), p); + } // Anniversaries if ((p.getRank().isOfficer()) || (!getCampaignOptions().isAnnounceOfficersOnly())) { @@ -3671,7 +3673,7 @@ public boolean newDay() { getPersonnelMarket().generatePersonnelForDay(this); // TODO : AbstractContractMarket : Uncomment - //getContractMarket().processNewDay(this); + //getContractMarket().processNewWeek(this); getUnitMarket().processNewDay(this); // Process New Day for AtB diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 6de55f5b9d..d88b64d128 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -435,7 +435,7 @@ private static double getBabyBornChance(int pregnancyWeek) { * @param today the current day * @param person the person to process */ - public void processNewDay(final Campaign campaign, final LocalDate today, final Person person) { + public void processNewWeek(final Campaign campaign, final LocalDate today, final Person person) { // Instantly return for male personnel if (person.getGender().isMale()) { return; diff --git a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java index 1612da5b1c..eba570dda9 100644 --- a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java +++ b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java @@ -625,7 +625,7 @@ private void finalizePersonnel(final Campaign campaign, } if (getOptions().isSimulateRandomProcreation()) { - campaign.getProcreation().processNewDay(campaign, date, tracker.getPerson()); + campaign.getProcreation().processNewWeek(campaign, date, tracker.getPerson()); } } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java index f8b5ec50a9..e8bf0ace3e 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java @@ -447,39 +447,39 @@ public void testProcessPregnancyComplications() { //region New Day @Test - public void testProcessNewDay() { - doCallRealMethod().when(mockProcreation).processNewDay(any(), any(), any()); + public void testProcessNewWeek() { + doCallRealMethod().when(mockProcreation).processNewWeek(any(), any(), any()); doNothing().when(mockProcreation).birth(any(), any(), any()); doNothing().when(mockProcreation).addPregnancy(any(), any(), any()); final Person mockPerson = mock(Person.class); when(mockPerson.getGender()).thenReturn(Gender.MALE); - mockProcreation.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockPerson, never()).isPregnant(); verify(mockProcreation, never()).randomlyProcreates(any(), any()); when(mockPerson.getGender()).thenReturn(Gender.FEMALE); when(mockPerson.isPregnant()).thenReturn(true); when(mockPerson.getDueDate()).thenReturn(LocalDate.ofYearDay(3025, 2)); - mockProcreation.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockProcreation, never()).birth(any(), any(), any()); verify(mockProcreation, never()).randomlyProcreates(any(), any()); when(mockPerson.getDueDate()).thenReturn(LocalDate.ofYearDay(3025, 1)); - mockProcreation.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockProcreation, times(1)).birth(any(), any(), any()); verify(mockProcreation, never()).randomlyProcreates(any(), any()); when(mockPerson.isPregnant()).thenReturn(false); when(mockProcreation.randomlyProcreates(any(), any())).thenReturn(false); - mockProcreation.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockProcreation, times(1)).birth(any(), any(), any()); verify(mockProcreation, times(1)).randomlyProcreates(any(), any()); when(mockProcreation.randomlyProcreates(any(), any())).thenReturn(true); - mockProcreation.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockProcreation, times(2)).randomlyProcreates(any(), any()); verify(mockProcreation, times(1)).addPregnancy(any(), any(), any()); } From 350f599f7c15b9626a0f4ba4f0d5a9c4a89f4c90 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 15:11:18 -0500 Subject: [PATCH 06/41] Adjust simulation duration to use weeks instead of days Changed the duration adjustment for starting simulations to use weeks. This should reduce load by approximately 85% --- .../companyGenerators/AbstractCompanyGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java index eba570dda9..c4be34c247 100644 --- a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java +++ b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java @@ -615,9 +615,9 @@ private void finalizePersonnel(final Campaign campaign, } if (getOptions().isRunStartingSimulation()) { - LocalDate date = campaign.getLocalDate().minusYears(getOptions().getSimulationDuration()).minusDays(1); + LocalDate date = campaign.getLocalDate().minusYears(getOptions().getSimulationDuration()).minusWeeks(1); while (date.isBefore(campaign.getLocalDate())) { - date = date.plusDays(1); + date = date.plusWeeks(1); for (final CompanyGenerationPersonTracker tracker : trackers) { if (getOptions().isSimulateRandomMarriages()) { From c8dacd29a711344b0bf738c1d17f39eef4d3a99b Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 19:41:41 -0500 Subject: [PATCH 07/41] Refactored marriage logic to use dice roll method Replaced percentage-based random marriage with a dice-roll method. Converted existing percentage configurations to dice size configurations. --- .../CampaignOptionsDialog.properties | 8 +-- .../mekhq/resources/Personnel.properties | 4 +- MekHQ/src/mekhq/campaign/Campaign.java | 4 +- MekHQ/src/mekhq/campaign/CampaignOptions.java | 59 ++++++++------- .../personnel/enums/RandomMarriageMethod.java | 25 ++++--- .../enums/RandomProcreationMethod.java | 4 +- .../personnel/marriage/AbstractMarriage.java | 2 +- ...andomMarriage.java => RandomMarriage.java} | 44 +++++++----- .../AbstractCompanyGenerator.java | 2 +- MekHQ/src/mekhq/gui/CampaignGUI.java | 12 ++-- .../mekhq/gui/panes/CampaignOptionsPane.java | 72 +++++++++---------- .../enums/RandomMarriageMethodTest.java | 29 ++++---- .../enums/RandomProcreationMethodTest.java | 8 +-- .../marriage/AbstractMarriageTest.java | 14 ++-- .../PercentageRandomMarriageTest.java | 58 ++++++++------- 15 files changed, 185 insertions(+), 160 deletions(-) rename MekHQ/src/mekhq/campaign/personnel/marriage/{PercentageRandomMarriage.java => RandomMarriage.java} (51%) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index f0f553949c..fea2ec9ebf 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -474,10 +474,10 @@ chkUseRandomPrisonerMarriages.toolTipText=Allow prisoners to randomly marry othe lblRandomMarriageAgeRange.text=Random Marriage Age Range lblRandomMarriageAgeRange.toolTipText=This plus/minus the age forms the possible range of ages for spouses in the forming of a random marriage. percentageRandomMarriagePanel.title=Percentage Random Marriage -lblPercentageRandomMarriageOppositeSexChance.text=Opposite Sex Chance -lblPercentageRandomMarriageOppositeSexChance.toolTipText=This is the percent chance that a fitting member of your force will marry another fitting member of your force of the opposite sex. -lblPercentageRandomMarriageSameSexChance.text=Same Sex Chance -lblPercentageRandomMarriageSameSexChance.toolTipText=This is the percent chance that a fitting member of your force will marry another fitting member of your force of the same sex. +lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Dice Size +lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 25% chance of a character getting married every 3 years. +lblRandomMarriageSameSexDiceSize.text=Same Sex Dice Size +lblRandomMarriageSameSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 5% chance of a character getting married every 3 years. The difference between opposite sex and same sex dice chances are based on 2022 US census data. # Divorce divorcePanel.title=Divorce diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index c28edf0fdf..8b84876804 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -1021,8 +1021,8 @@ RandomDivorceMethod.PERCENTAGE.toolTipText=This checks if a random value is lowe # RandomMarriageMethod Enum RandomMarriageMethod.NONE.text=Disabled RandomMarriageMethod.NONE.toolTipText=Random marriage is disabled. -RandomMarriageMethod.PERCENTAGE.text=Percentage -RandomMarriageMethod.PERCENTAGE.toolTipText=This checks if a random value is lower than the percentage to determine if an eligible person marries on a given day. +RandomMarriageMethod.DICE_ROLL.text=Dice Roll +RandomMarriageMethod.DICE_ROLL.toolTipText=A die is rolled each week to determine whether an eligible character gets married to another eligible character. The options below determine how many sides this dice has. Marriage occurs on a roll of 1. # RandomProcreationMethod Enum RandomProcreationMethod.NONE.text=Disabled diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index e95ae43e49..0b0fa2a04e 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -3414,7 +3414,9 @@ public void processNewDayPersonnel() { } // Marriage - getMarriage().processNewDay(this, getLocalDate(), p); + if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { + getMarriage().processNewWeek(this, getLocalDate(), p); + } p.resetMinutesLeft(); // Reset acquisitions made to 0 diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 0f4dd9aee1..fe7b37b7dc 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -346,8 +346,8 @@ public static String getTransitUnitName(final int unit) { private boolean useRandomClanPersonnelMarriages; private boolean useRandomPrisonerMarriages; private int randomMarriageAgeRange; - private double percentageRandomMarriageOppositeSexChance; - private double percentageRandomMarriageSameSexChance; + private int randomMarriageOppositeSexDiceSize; + private int randomMarriageSameSexDiceSize; // Divorce private boolean useManualDivorce; @@ -856,8 +856,9 @@ public CampaignOptions() { setUseRandomClanPersonnelMarriages(false); setUseRandomPrisonerMarriages(true); setRandomMarriageAgeRange(10); - setPercentageRandomMarriageOppositeSexChance(0.00025); - setPercentageRandomMarriageSameSexChance(0.00002); + setRandomMarriageOppositeSexDiceSize(542); + // this number was determined based on 2* the % of recorded same-sex marriages in the US circa 2022 + setRandomMarriageSameSexDiceSize(3042); // Divorce setUseManualDivorce(true); @@ -2405,35 +2406,35 @@ public void setRandomMarriageAgeRange(final int randomMarriageAgeRange) { } /** - * This gets the decimal chance (between 0 and 1) of a random opposite sex marriage occurring - * @return the chance, with a value between 0 and 1 + * @return the number of sides on the die used to determine random opposite sex marriage */ - public double getPercentageRandomMarriageOppositeSexChance() { - return percentageRandomMarriageOppositeSexChance; + public int getRandomMarriageOppositeSexDiceSize() { + return randomMarriageOppositeSexDiceSize; } /** - * This sets the decimal chance (between 0 and 1) of a random opposite sex marriage occurring - * @param percentageRandomMarriageOppositeSexChance the chance, with a value between 0 and 1 + * Sets the size of the random opposite sex marriage die. + * + * @param randomMarriageOppositeSexDiceSize the size of the random opposite sex marriage die */ - public void setPercentageRandomMarriageOppositeSexChance(final double percentageRandomMarriageOppositeSexChance) { - this.percentageRandomMarriageOppositeSexChance = percentageRandomMarriageOppositeSexChance; + public void setRandomMarriageOppositeSexDiceSize(final int randomMarriageOppositeSexDiceSize) { + this.randomMarriageOppositeSexDiceSize = randomMarriageOppositeSexDiceSize; } /** - * This gets the decimal chance (between 0 and 1) of a random same-sex marriage occurring - * @return the chance, with a value between 0 and 1 + * @return the number of sides on the die used to determine random same-sex marriage */ - public double getPercentageRandomMarriageSameSexChance() { - return percentageRandomMarriageSameSexChance; + public int getRandomMarriageSameSexDiceSize() { + return randomMarriageSameSexDiceSize; } /** - * This sets the decimal chance (between 0 and 1) of a random same-sex marriage occurring - * @param percentageRandomMarriageSameSexChance the chance, with a value between 0 and 1 + * Sets the size of the random same-sex marriage die. + * + * @param randomMarriageSameSexDiceSize the size of the random opposite sex marriage die */ - public void setPercentageRandomMarriageSameSexChance(final double percentageRandomMarriageSameSexChance) { - this.percentageRandomMarriageSameSexChance = percentageRandomMarriageSameSexChance; + public void setRandomMarriageSameSexDiceSize(final int randomMarriageSameSexDiceSize) { + this.randomMarriageSameSexDiceSize = randomMarriageSameSexDiceSize; } //endregion Marriage @@ -4714,8 +4715,8 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomClanPersonnelMarriages", isUseRandomClanPersonnelMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPrisonerMarriages", isUseRandomPrisonerMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageAgeRange", getRandomMarriageAgeRange()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "percentageRandomMarriageOppositeSexChance", getPercentageRandomMarriageOppositeSexChance()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "percentageRandomMarriageSameSexChance", getPercentageRandomMarriageSameSexChance()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageOppositeSexDiceSize", getRandomMarriageOppositeSexDiceSize()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageSameSexChance", getRandomMarriageSameSexDiceSize()); //endregion Marriage //region Divorce @@ -5431,10 +5432,10 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUseRandomPrisonerMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageAgeRange")) { retVal.setRandomMarriageAgeRange(Integer.parseInt(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("percentageRandomMarriageOppositeSexChance")) { - retVal.setPercentageRandomMarriageOppositeSexChance(Double.parseDouble(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("percentageRandomMarriageSameSexChance")) { - retVal.setPercentageRandomMarriageSameSexChance(Double.parseDouble(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageOppositeSexChance")) { + retVal.setRandomMarriageOppositeSexDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageSameSexChance")) { + retVal.setRandomMarriageSameSexDiceSize(Integer.parseInt(wn2.getTextContent().trim())); //endregion Marriage //region Divorce @@ -5992,15 +5993,11 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUseRandomDependentAddition(value); } else if (wn2.getNodeName().equalsIgnoreCase("dependentsNeverLeave")) { // Legacy - 0.49.7 Removal retVal.setUseRandomDependentRemoval(!Boolean.parseBoolean(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("chanceRandomMarriages")) { // Legacy - 0.49.6 Removal - retVal.setPercentageRandomMarriageOppositeSexChance(Double.parseDouble(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("chanceRandomSameSexMarriages")) { // Legacy - 0.49.6 Removal - retVal.setPercentageRandomMarriageSameSexChance(Double.parseDouble(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("marriageAgeRange")) { // Legacy - 0.49.6 Removal retVal.setRandomMarriageAgeRange(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("useRandomMarriages")) { // Legacy - 0.49.6 Removal retVal.setRandomMarriageMethod(Boolean.parseBoolean(wn2.getTextContent().trim()) - ? RandomMarriageMethod.PERCENTAGE : RandomMarriageMethod.NONE); + ? RandomMarriageMethod.DICE_ROLL : RandomMarriageMethod.NONE); } else if (wn2.getNodeName().equalsIgnoreCase("logMarriageNameChange")) { // Legacy - 0.49.6 Removal retVal.setLogMarriageNameChanges(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageSurnameWeights")) { // Legacy - 0.49.6 Removal diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java index 6d926f07e0..a1517a61dc 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java @@ -22,14 +22,16 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.marriage.AbstractMarriage; import mekhq.campaign.personnel.marriage.DisabledRandomMarriage; -import mekhq.campaign.personnel.marriage.PercentageRandomMarriage; +import mekhq.campaign.personnel.marriage.RandomMarriage; import java.util.ResourceBundle; +import static megamek.client.ui.WrapLayout.wordWrap; + public enum RandomMarriageMethod { //region Enum Declarations NONE("RandomMarriageMethod.NONE.text", "RandomMarriageMethod.NONE.toolTipText"), - PERCENTAGE("RandomMarriageMethod.PERCENTAGE.text", "RandomMarriageMethod.PERCENTAGE.toolTipText"); + DICE_ROLL("RandomMarriageMethod.DICE_ROLL.text", "RandomMarriageMethod.DICE_ROLL.toolTipText"); //endregion Enum Declarations //region Variable Declarations @@ -42,33 +44,34 @@ public enum RandomMarriageMethod { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); this.name = resources.getString(name); - this.toolTipText = resources.getString(toolTipText); + this.toolTipText = wordWrap(resources.getString(toolTipText)); } //endregion Constructors //region Getters + @SuppressWarnings(value = "unused") public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparison Methods + @SuppressWarnings(value = "unused") public boolean isNone() { return this == NONE; } - public boolean isPercentage() { - return this == PERCENTAGE; + @SuppressWarnings(value = "unused") + public boolean isDiceRoll() { + return this == DICE_ROLL; } //endregion Boolean Comparison Methods public AbstractMarriage getMethod(final CampaignOptions options) { - switch (this) { - case PERCENTAGE: - return new PercentageRandomMarriage(options); - case NONE: - default: - return new DisabledRandomMarriage(options); + if (this == DICE_ROLL) { + return new RandomMarriage(options); + } else { + return new DisabledRandomMarriage(options); } } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java index c93a512fcc..decb35c4c9 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java @@ -26,6 +26,8 @@ import java.util.ResourceBundle; +import static megamek.client.ui.WrapLayout.wordWrap; + public enum RandomProcreationMethod { //region Enum Declarations NONE("RandomProcreationMethod.NONE.text", "RandomProcreationMethod.NONE.toolTipText"), @@ -42,7 +44,7 @@ public enum RandomProcreationMethod { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); this.name = resources.getString(name); - this.toolTipText = resources.getString(toolTipText); + this.toolTipText = wordWrap(resources.getString(toolTipText)); } //endregion Constructors diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 3dad3f772b..696680b365 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -225,7 +225,7 @@ public void marry(final Campaign campaign, final LocalDate today, final Person o * @param today the current day * @param person the person to process */ - public void processNewDay(final Campaign campaign, final LocalDate today, final Person person) { + public void processNewWeek(final Campaign campaign, final LocalDate today, final Person person) { if (canMarry(campaign, today, person, true) != null) { return; } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java similarity index 51% rename from MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java rename to MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index f36c5f2218..67f5c79012 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/PercentageRandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -23,45 +23,55 @@ import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomMarriageMethod; -public class PercentageRandomMarriage extends AbstractMarriage { +public class RandomMarriage extends AbstractMarriage { //region Variable Declarations - private double oppositeSexPercentage; - private double sameSexPercentage; + private int oppositeSexDiceSize; + private int sameSexDiceSize; //endregion Variable Declarations //region Constructors - public PercentageRandomMarriage(final CampaignOptions options) { - super(RandomMarriageMethod.PERCENTAGE, options); - setOppositeSexPercentage(options.getPercentageRandomMarriageOppositeSexChance()); - setSameSexPercentage(options.getPercentageRandomMarriageSameSexChance()); + public RandomMarriage(final CampaignOptions options) { + super(RandomMarriageMethod.DICE_ROLL, options); + + setOppositeSexDiceSize(options.getRandomMarriageOppositeSexDiceSize()); + + setSameSexDiceSize(options.getRandomMarriageSameSexDiceSize()); } //endregion Constructors //region Getters/Setters - public double getOppositeSexPercentage() { - return oppositeSexPercentage; + @SuppressWarnings(value = "unused") + public int getOppositeSexDiceSize() { + return oppositeSexDiceSize; } - public void setOppositeSexPercentage(final double oppositeSexPercentage) { - this.oppositeSexPercentage = oppositeSexPercentage; + @SuppressWarnings(value = "unused") + public void setOppositeSexDiceSize(final int oppositeSexDiceSize) { + this.oppositeSexDiceSize = oppositeSexDiceSize; } - public double getSameSexPercentage() { - return sameSexPercentage; + @SuppressWarnings(value = "unused") + public int getSameSexDiceSize() { + return sameSexDiceSize; } - public void setSameSexPercentage(final double sameSexPercentage) { - this.sameSexPercentage = sameSexPercentage; + @SuppressWarnings(value = "unused") + public void setSameSexDiceSize(final int sameSexDiceSize) { + this.sameSexDiceSize = sameSexDiceSize; } //endregion Getters/Setters @Override protected boolean randomOppositeSexMarriage(final Person person) { - return Compute.randomFloat() < getOppositeSexPercentage(); + int multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size()); + + return Compute.randomInt(oppositeSexDiceSize * multiplier) == 0; } @Override protected boolean randomSameSexMarriage(final Person person) { - return Compute.randomFloat() < getSameSexPercentage(); + int multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size()); + + return Compute.randomInt(sameSexDiceSize * multiplier) == 0; } } diff --git a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java index c4be34c247..790fc7fdd5 100644 --- a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java +++ b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java @@ -621,7 +621,7 @@ private void finalizePersonnel(final Campaign campaign, for (final CompanyGenerationPersonTracker tracker : trackers) { if (getOptions().isSimulateRandomMarriages()) { - campaign.getMarriage().processNewDay(campaign, date, tracker.getPerson()); + campaign.getMarriage().processNewWeek(campaign, date, tracker.getPerson()); } if (getOptions().isSimulateRandomProcreation()) { diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index ebcbb8ae8d..99b85f5864 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -55,7 +55,7 @@ import mekhq.campaign.personnel.death.PercentageRandomDeath; import mekhq.campaign.personnel.divorce.PercentageRandomDivorce; import mekhq.campaign.personnel.enums.*; -import mekhq.campaign.personnel.marriage.PercentageRandomMarriage; +import mekhq.campaign.personnel.marriage.RandomMarriage; import mekhq.campaign.personnel.procreation.AbstractProcreation; import mekhq.campaign.personnel.procreation.randomProcreation; import mekhq.campaign.personnel.ranks.RankSystem; @@ -1501,11 +1501,11 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { getCampaign().getMarriage() .setUseRandomClanPersonnelMarriages(newOptions.isUseRandomClanPersonnelMarriages()); getCampaign().getMarriage().setUseRandomPrisonerMarriages(newOptions.isUseRandomPrisonerMarriages()); - if (getCampaign().getMarriage().getMethod().isPercentage()) { - ((PercentageRandomMarriage) getCampaign().getMarriage()).setOppositeSexPercentage( - newOptions.getPercentageRandomMarriageOppositeSexChance()); - ((PercentageRandomMarriage) getCampaign().getMarriage()).setSameSexPercentage( - newOptions.getPercentageRandomMarriageSameSexChance()); + if (getCampaign().getMarriage().getMethod().isDiceRoll()) { + ((RandomMarriage) getCampaign().getMarriage()).setOppositeSexDiceSize( + newOptions.getRandomMarriageOppositeSexDiceSize()); + ((RandomMarriage) getCampaign().getMarriage()).setSameSexDiceSize( + newOptions.getRandomMarriageSameSexDiceSize()); } } diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index 304571029f..7f944488f7 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -375,9 +375,9 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseRandomClanPersonnelMarriages; private JCheckBox chkUseRandomPrisonerMarriages; private JSpinner spnRandomMarriageAgeRange; - private JSpinner spnPercentageRandomMarriageOppositeSexChance; - private JLabel lblPercentageRandomMarriageSameSexChance; - private JSpinner spnPercentageRandomMarriageSameSexChance; + private JSpinner spnRandomMarriageOppositeSexDiceSize; + private JLabel lblRandomMarriageSameSexDiceSize; + private JSpinner spnRandomMarriageSameSexDiceSize; // Divorce private JCheckBox chkUseManualDivorce; @@ -5632,15 +5632,15 @@ public Component getListCellRendererComponent(final JList list, final Object } final boolean enabled = !method.isNone(); final boolean sameSexEnabled = enabled && chkUseRandomSameSexMarriages.isSelected(); - final boolean percentageEnabled = method.isPercentage(); + final boolean percentageEnabled = method.isDiceRoll(); chkUseRandomSameSexMarriages.setEnabled(enabled); chkUseRandomClanPersonnelMarriages.setEnabled(enabled && chkUseClanPersonnelMarriages.isSelected()); chkUseRandomPrisonerMarriages.setEnabled(enabled && chkUsePrisonerMarriages.isSelected()); lblRandomMarriageAgeRange.setEnabled(enabled); spnRandomMarriageAgeRange.setEnabled(enabled); percentageRandomMarriagePanel.setEnabled(percentageEnabled); - lblPercentageRandomMarriageSameSexChance.setEnabled(sameSexEnabled && percentageEnabled); - spnPercentageRandomMarriageSameSexChance.setEnabled(sameSexEnabled && percentageEnabled); + lblRandomMarriageSameSexDiceSize.setEnabled(sameSexEnabled && percentageEnabled); + spnRandomMarriageSameSexDiceSize.setEnabled(sameSexEnabled && percentageEnabled); }); chkUseRandomSameSexMarriages = new JCheckBox(resources.getString("chkUseRandomSameSexMarriages.text")); @@ -5653,9 +5653,9 @@ public Component getListCellRendererComponent(final JList list, final Object } final boolean sameSexEnabled = chkUseRandomSameSexMarriages.isEnabled() && chkUseRandomSameSexMarriages.isSelected(); - final boolean percentageEnabled = sameSexEnabled && method.isPercentage(); - lblPercentageRandomMarriageSameSexChance.setEnabled(percentageEnabled); - spnPercentageRandomMarriageSameSexChance.setEnabled(percentageEnabled); + final boolean percentageEnabled = sameSexEnabled && method.isDiceRoll(); + lblRandomMarriageSameSexDiceSize.setEnabled(percentageEnabled); + spnRandomMarriageSameSexDiceSize.setEnabled(percentageEnabled); }); chkUseRandomClanPersonnelMarriages = new JCheckBox(resources.getString("chkUseRandomClanPersonnelMarriages.text")); @@ -5723,29 +5723,29 @@ public Component getListCellRendererComponent(final JList list, final Object private void createPercentageRandomMarriagePanel(final JPanel panel) { // Create Panel Components - final JLabel lblPercentageRandomMarriageOppositeSexChance = new JLabel(resources.getString("lblPercentageRandomMarriageOppositeSexChance.text")); - lblPercentageRandomMarriageOppositeSexChance.setToolTipText(resources.getString("lblPercentageRandomMarriageOppositeSexChance.toolTipText")); - lblPercentageRandomMarriageOppositeSexChance.setName("lblPercentageRandomMarriageOppositeSexChance"); + final JLabel lblRandomMarriageOppositeSexDiceSize = new JLabel(resources.getString("lblRandomMarriageOppositeSexDiceSize.text")); + lblRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"), 100)); + lblRandomMarriageOppositeSexDiceSize.setName("lblRandomMarriageOppositeSexDiceSize"); - spnPercentageRandomMarriageOppositeSexChance = new JSpinner(new SpinnerNumberModel(0, 0, 100, 0.001)); - spnPercentageRandomMarriageOppositeSexChance.setToolTipText(resources.getString("lblPercentageRandomMarriageOppositeSexChance.toolTipText")); - spnPercentageRandomMarriageOppositeSexChance.setName("spnPercentageRandomMarriageOppositeSexChance"); + spnRandomMarriageOppositeSexDiceSize = new JSpinner(new SpinnerNumberModel(0, 0, 100000, 1)); + spnRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"), 100)); + spnRandomMarriageOppositeSexDiceSize.setName("spnPercentageRandomMarriageOppositeSexChance"); - lblPercentageRandomMarriageSameSexChance = new JLabel(resources.getString("lblPercentageRandomMarriageSameSexChance.text")); - lblPercentageRandomMarriageSameSexChance.setToolTipText(resources.getString("lblPercentageRandomMarriageSameSexChance.toolTipText")); - lblPercentageRandomMarriageSameSexChance.setName("lblPercentageRandomMarriageSameSexChance"); + lblRandomMarriageSameSexDiceSize = new JLabel(resources.getString("lblRandomMarriageSameSexDiceSize.text")); + lblRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"), 100)); + lblRandomMarriageSameSexDiceSize.setName("lblRandomMarriageSameSexDiceSize"); - spnPercentageRandomMarriageSameSexChance = new JSpinner(new SpinnerNumberModel(0, 0, 100, 0.001)); - spnPercentageRandomMarriageSameSexChance.setToolTipText(resources.getString("lblPercentageRandomMarriageSameSexChance.toolTipText")); - spnPercentageRandomMarriageSameSexChance.setName("spnPercentageRandomMarriageSameSexChance"); + spnRandomMarriageSameSexDiceSize = new JSpinner(new SpinnerNumberModel(0, 0, 100000, 1)); + spnRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"), 100)); + spnRandomMarriageSameSexDiceSize.setName("spnRandomMarriageSameSexDiceSize"); // Programmatically Assign Accessibility Labels - lblPercentageRandomMarriageOppositeSexChance.setLabelFor(spnPercentageRandomMarriageOppositeSexChance); - lblPercentageRandomMarriageSameSexChance.setLabelFor(spnPercentageRandomMarriageSameSexChance); + lblRandomMarriageOppositeSexDiceSize.setLabelFor(spnRandomMarriageOppositeSexDiceSize); + lblRandomMarriageSameSexDiceSize.setLabelFor(spnRandomMarriageSameSexDiceSize); // Layout the Panel panel.setBorder(BorderFactory.createTitledBorder(resources.getString("percentageRandomMarriagePanel.title"))); - panel.setToolTipText(RandomMarriageMethod.PERCENTAGE.getToolTipText()); + panel.setToolTipText(RandomMarriageMethod.DICE_ROLL.getToolTipText()); final GroupLayout layout = new GroupLayout(panel); layout.setAutoCreateGaps(true); @@ -5755,21 +5755,21 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { layout.setVerticalGroup( layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblPercentageRandomMarriageOppositeSexChance) - .addComponent(spnPercentageRandomMarriageOppositeSexChance, Alignment.LEADING)) + .addComponent(lblRandomMarriageOppositeSexDiceSize) + .addComponent(spnRandomMarriageOppositeSexDiceSize, Alignment.LEADING)) .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblPercentageRandomMarriageSameSexChance) - .addComponent(spnPercentageRandomMarriageSameSexChance, Alignment.LEADING)) + .addComponent(lblRandomMarriageSameSexDiceSize) + .addComponent(spnRandomMarriageSameSexDiceSize, Alignment.LEADING)) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(lblPercentageRandomMarriageOppositeSexChance) - .addComponent(spnPercentageRandomMarriageOppositeSexChance)) + .addComponent(lblRandomMarriageOppositeSexDiceSize) + .addComponent(spnRandomMarriageOppositeSexDiceSize)) .addGroup(layout.createSequentialGroup() - .addComponent(lblPercentageRandomMarriageSameSexChance) - .addComponent(spnPercentageRandomMarriageSameSexChance)) + .addComponent(lblRandomMarriageSameSexDiceSize) + .addComponent(spnRandomMarriageSameSexDiceSize)) ); } @@ -8229,8 +8229,8 @@ public void setOptions(@Nullable CampaignOptions options, chkUseRandomClanPersonnelMarriages.setSelected(options.isUseRandomClanPersonnelMarriages()); chkUseRandomPrisonerMarriages.setSelected(options.isUseRandomPrisonerMarriages()); spnRandomMarriageAgeRange.setValue(options.getRandomMarriageAgeRange()); - spnPercentageRandomMarriageOppositeSexChance.setValue(options.getPercentageRandomMarriageOppositeSexChance() * 100.0); - spnPercentageRandomMarriageSameSexChance.setValue(options.getPercentageRandomMarriageSameSexChance() * 100.0); + spnRandomMarriageOppositeSexDiceSize.setValue(options.getRandomMarriageOppositeSexDiceSize()); + spnRandomMarriageSameSexDiceSize.setValue(options.getRandomMarriageSameSexDiceSize()); // Divorce chkUseManualDivorce.setSelected(options.isUseManualDivorce()); @@ -8918,8 +8918,8 @@ public void updateOptions() { options.setUseRandomClanPersonnelMarriages(chkUseRandomClanPersonnelMarriages.isSelected()); options.setUseRandomPrisonerMarriages(chkUseRandomPrisonerMarriages.isSelected()); options.setRandomMarriageAgeRange((Integer) spnRandomMarriageAgeRange.getValue()); - options.setPercentageRandomMarriageOppositeSexChance((Double) spnPercentageRandomMarriageOppositeSexChance.getValue() / 100.0); - options.setPercentageRandomMarriageSameSexChance((Double) spnPercentageRandomMarriageSameSexChance.getValue() / 100.0); + options.setRandomMarriageOppositeSexDiceSize((int) spnRandomMarriageOppositeSexDiceSize.getValue()); + options.setRandomMarriageSameSexDiceSize((int) spnRandomMarriageSameSexDiceSize.getValue()); // Divorce options.setUseManualDivorce(chkUseManualDivorce.isSelected()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java index 76ea787648..94ffad32f8 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java @@ -21,11 +21,12 @@ import mekhq.MekHQ; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.marriage.DisabledRandomMarriage; -import mekhq.campaign.personnel.marriage.PercentageRandomMarriage; +import mekhq.campaign.personnel.marriage.RandomMarriage; import org.junit.jupiter.api.Test; import java.util.ResourceBundle; +import static megamek.client.ui.WrapLayout.wordWrap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -44,10 +45,10 @@ public class RandomMarriageMethodTest { //region Getters @Test public void testGetToolTipText() { - assertEquals(resources.getString("RandomMarriageMethod.NONE.toolTipText"), + assertEquals(wordWrap(resources.getString("RandomMarriageMethod.NONE.toolTipText")), RandomMarriageMethod.NONE.getToolTipText()); - assertEquals(resources.getString("RandomMarriageMethod.PERCENTAGE.toolTipText"), - RandomMarriageMethod.PERCENTAGE.getToolTipText()); + assertEquals(wordWrap(resources.getString("RandomMarriageMethod.DICE_ROLL.toolTipText")), + RandomMarriageMethod.DICE_ROLL.getToolTipText()); } //endregion Getters @@ -66,10 +67,10 @@ public void testIsNone() { @Test public void testIsPercentage() { for (final RandomMarriageMethod randomMarriageMethod : methods) { - if (randomMarriageMethod == RandomMarriageMethod.PERCENTAGE) { - assertTrue(randomMarriageMethod.isPercentage()); + if (randomMarriageMethod == RandomMarriageMethod.DICE_ROLL) { + assertTrue(randomMarriageMethod.isDiceRoll()); } else { - assertFalse(randomMarriageMethod.isPercentage()); + assertFalse(randomMarriageMethod.isDiceRoll()); } } } @@ -83,18 +84,18 @@ public void testGetMethod() { when(mockOptions.isUseRandomSameSexMarriages()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUseRandomPrisonerMarriages()).thenReturn(false); - when(mockOptions.getPercentageRandomMarriageOppositeSexChance()).thenReturn(0.5); - when(mockOptions.getPercentageRandomMarriageSameSexChance()).thenReturn(0.5); + when(mockOptions.getRandomMarriageOppositeSexDiceSize()).thenReturn(5); + when(mockOptions.getRandomMarriageSameSexDiceSize()).thenReturn(5); assertInstanceOf(DisabledRandomMarriage.class, RandomMarriageMethod.NONE.getMethod(mockOptions)); - assertInstanceOf(PercentageRandomMarriage.class, RandomMarriageMethod.PERCENTAGE.getMethod(mockOptions)); + assertInstanceOf(RandomMarriage.class, RandomMarriageMethod.DICE_ROLL.getMethod(mockOptions)); } @Test public void testToStringOverride() { - assertEquals(resources.getString("RandomMarriageMethod.NONE.text"), - RandomMarriageMethod.NONE.toString()); - assertEquals(resources.getString("RandomMarriageMethod.PERCENTAGE.text"), - RandomMarriageMethod.PERCENTAGE.toString()); + assertEquals(wordWrap(resources.getString("RandomMarriageMethod.NONE.text")).trim(), + RandomMarriageMethod.NONE.toString().trim()); + assertEquals(wordWrap(resources.getString("RandomMarriageMethod.DICE_ROLL.text")).trim(), + RandomMarriageMethod.DICE_ROLL.toString().trim()); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java index 5db071803f..55cc8f41a8 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java @@ -44,10 +44,10 @@ public class RandomProcreationMethodTest { //region Getters @Test public void testGetToolTipText() { - assertEquals(resources.getString("RandomProcreationMethod.NONE.toolTipText"), - RandomProcreationMethod.NONE.getToolTipText()); - assertEquals(resources.getString("RandomProcreationMethod.DICE_ROLL.toolTipText"), - RandomProcreationMethod.DICE_ROLL.getToolTipText()); + assertEquals(resources.getString("RandomProcreationMethod.NONE.toolTipText").trim(), + RandomProcreationMethod.NONE.getToolTipText().trim()); + assertEquals(resources.getString("RandomProcreationMethod.DICE_ROLL.toolTipText").trim(), + RandomProcreationMethod.DICE_ROLL.getToolTipText().trim()); } //endregion Getters diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index 925d0e6371..4e5b4976ed 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -260,41 +260,41 @@ public void testMarry() { //region New Day @Test - public void testProcessNewDay() { - doCallRealMethod().when(mockMarriage).processNewDay(any(), any(), any()); + public void testProcessNewWeek() { + doCallRealMethod().when(mockMarriage).processNewWeek(any(), any(), any()); doNothing().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean()); final Person mockPerson = mock(Person.class); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn("Married"); - mockMarriage.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(0)).randomOppositeSexMarriage(any()); verify(mockMarriage, times(0)).randomSameSexMarriage(any()); verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean()); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn(null); when(mockMarriage.randomOppositeSexMarriage(any())).thenReturn(true); - mockMarriage.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(1)).randomOppositeSexMarriage(any()); verify(mockMarriage, times(0)).randomSameSexMarriage(any()); verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); when(mockMarriage.randomOppositeSexMarriage(any())).thenReturn(false); when(mockMarriage.isUseRandomSameSexMarriages()).thenReturn(false); - mockMarriage.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(2)).randomOppositeSexMarriage(any()); verify(mockMarriage, times(0)).randomSameSexMarriage(any()); verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); when(mockMarriage.isUseRandomSameSexMarriages()).thenReturn(true); when(mockMarriage.randomSameSexMarriage(any())).thenReturn(false); - mockMarriage.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(3)).randomOppositeSexMarriage(any()); verify(mockMarriage, times(1)).randomSameSexMarriage(any()); verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); when(mockMarriage.randomSameSexMarriage(any())).thenReturn(true); - mockMarriage.processNewDay(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); + mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(4)).randomOppositeSexMarriage(any()); verify(mockMarriage, times(2)).randomSameSexMarriage(any()); verify(mockMarriage, times(2)).marryRandomSpouse(any(), any(), any(), anyBoolean()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java index 070edf7b8c..e3e4a9b7cc 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java @@ -21,6 +21,7 @@ import megamek.common.Compute; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.Person; +import mekhq.campaign.personnel.familyTree.Genealogy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,8 +30,11 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.Collections; + import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @ExtendWith(value = MockitoExtension.class) @@ -48,41 +52,47 @@ public void beforeEach() { when(mockOptions.isUseRandomSameSexMarriages()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUseRandomPrisonerMarriages()).thenReturn(false); - when(mockOptions.getPercentageRandomMarriageOppositeSexChance()).thenReturn(0.5); - when(mockOptions.getPercentageRandomMarriageSameSexChance()).thenReturn(0.5); + when(mockOptions.getRandomMarriageOppositeSexDiceSize()).thenReturn(5); + when(mockOptions.getRandomMarriageSameSexDiceSize()).thenReturn(5); } @Test public void testRandomOppositeSexMarriage() { - final PercentageRandomMarriage percentageRandomMarriage = new PercentageRandomMarriage(mockOptions); - // This ignores the person, so just using a mocked person - // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) + final RandomMarriage randomMarriage = new RandomMarriage(mockOptions); + Genealogy mockGenealogy = mock(Genealogy.class); + + when(mockGenealogy.getFormerSpouses()).thenReturn(Collections.emptyList()); + + when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); + + int diceSize = 5; + int multiplier = 1; + try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); - assertTrue(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); - assertTrue(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); - assertFalse(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); - assertFalse(percentageRandomMarriage.randomOppositeSexMarriage(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(0); + assertTrue(randomMarriage.randomOppositeSexMarriage(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(1); + assertFalse(randomMarriage.randomOppositeSexMarriage(mockPerson)); } } @Test public void testRandomSameSexMarriage() { - final PercentageRandomMarriage percentageRandomMarriage = new PercentageRandomMarriage(mockOptions); - // This ignores the person, so just using a mocked person - // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) + final RandomMarriage randomMarriage = new RandomMarriage(mockOptions); + Genealogy mockGenealogy = mock(Genealogy.class); + + when(mockGenealogy.getFormerSpouses()).thenReturn(Collections.emptyList()); + + when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); + + int diceSize = 5; + int multiplier = 1; + try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); - assertTrue(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); - assertTrue(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); - assertFalse(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); - assertFalse(percentageRandomMarriage.randomSameSexMarriage(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(0); + assertTrue(randomMarriage.randomSameSexMarriage(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(1); + assertFalse(randomMarriage.randomSameSexMarriage(mockPerson)); } } } From 24ffa559aa1d9c5f822c42d7b71fe5aa56ccb651 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 20:42:27 -0500 Subject: [PATCH 08/41] Switch random divorce method to dice roll Replaced the percentage-based random divorce method with a dice roll system. --- .../CampaignOptionsDialog.properties | 36 +++--- .../mekhq/resources/Personnel.properties | 4 +- MekHQ/src/mekhq/campaign/Campaign.java | 12 +- MekHQ/src/mekhq/campaign/CampaignOptions.java | 34 ++---- .../personnel/divorce/AbstractDivorce.java | 4 +- ...eRandomDivorce.java => RandomDivorce.java} | 38 ++++--- .../personnel/enums/RandomDivorceMethod.java | 25 +++-- MekHQ/src/mekhq/gui/CampaignGUI.java | 12 +- .../mekhq/gui/panes/CampaignOptionsPane.java | 105 +++++------------- .../divorce/AbstractDivorceTest.java | 2 +- .../divorce/PercentageRandomDivorceTest.java | 41 +++---- .../enums/RandomDivorceMethodTest.java | 28 ++--- 12 files changed, 132 insertions(+), 209 deletions(-) rename MekHQ/src/mekhq/campaign/personnel/divorce/{PercentageRandomDivorce.java => RandomDivorce.java} (56%) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index fea2ec9ebf..321d1bd1ef 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -130,8 +130,6 @@ personnelPanel.title=Personnel turnoverAndRetentionPanel.title=Turnover and Retention ## Header -chkUseRetirementDateTracking.text=Track Departure Date -chkUseRetirementDateTracking.toolTipText=Track the date of a person's departure from the unit. chkUseRandomRetirement.text=Enable Employee Turnover chkUseRandomRetirement.toolTipText=Determines whether personnel will randomly leave the unit. @@ -437,17 +435,17 @@ chkUseDylansRandomXP.toolTipText=Use Dylan's optional random XP on creation of a chkUseRandomPersonalities.text=Use Random Personalities chkUseRandomPersonalities.toolTipText=Personnel are generated with random personality traits, quirks and intelligence.\
\ -
Intelligence affects a characters ability to graduate from education module academies.\ +
Intelligence affects a character's ability to graduate from education module academies.\
\
While traits and quirks do not currently have a mechanical effect, they will be used by the upcoming Random Events module. # Family -familyPanel.title=Family (Unofficial) +familyPanel.title=Family lblFamilyDisplayLevel.text=The Level of Relation to be Displayed in the Personnel Panel lblFamilyDisplayLevel.toolTipText=This setting is the relation to the selected person that MekHQ will display up to, including the previous levels
(higher levels require more processing when loading a person in the personnel table) # Marriage -marriagePanel.title=Marriage +marriagePanel.title=Marriage (Unofficial) chkUseManualMarriages.text=Use Manual Marriages chkUseManualMarriages.toolTipText=This allows the player to disable the Choose Spouse (Mate) option in the personnel table mouse adapter.
This option is provided for performance reasons for extremely large campaigns (10k+ personnel). chkUseClanPersonnelMarriages.text=Use Clan Personnel Marriages @@ -455,9 +453,9 @@ chkUseClanPersonnelMarriages.toolTipText=Allow clan-origin personnel to marry ot chkUsePrisonerMarriages.text=Use Prisoner Marriages chkUsePrisonerMarriages.toolTipText=Allow prisoners to marry other prisoners, and manually marrying a prisoner to a free member of the force. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. lblMinimumMarriageAge.text=Minimum Marital Age -lblMinimumMarriageAge.toolTipText=This is the minimum age that is allowed for a person to be married. +lblMinimumMarriageAge.toolTipText=This is the minimum age allowed for a person to be married. lblCheckMutualAncestorsDepth.text=Minimum Mutual Ancestor Check Depth for Marriage to be Possible -lblCheckMutualAncestorsDepth.toolTipText=This is the depth to which the ancestry of two people are checked for mutual ancestors to determine if they can marry.
Set to 0 to disable the ancestry check. +lblCheckMutualAncestorsDepth.toolTipText=This is the depth to which the ancestry of two people is checked for mutual ancestors to determine if they can marry.
Set to 0 to disable the ancestry check. chkLogMarriageNameChanges.text=Log Marriage Name Changes chkLogMarriageNameChanges.toolTipText=This enables the addition of a personnel log entry whenever a name is changed during marriage. marriageSurnameWeightsPanel.title=Marriage Surname Weights @@ -472,15 +470,15 @@ chkUseRandomClanPersonnelMarriages.toolTipText=Allow clan-origin personnel to ra chkUseRandomPrisonerMarriages.text=Use Random Prisoner Marriages chkUseRandomPrisonerMarriages.toolTipText=Allow prisoners to randomly marry other prisoners. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. lblRandomMarriageAgeRange.text=Random Marriage Age Range -lblRandomMarriageAgeRange.toolTipText=This plus/minus the age forms the possible range of ages for spouses in the forming of a random marriage. +lblRandomMarriageAgeRange.toolTipText=This plus/minus age forms the possible range of ages for spouses in the forming of a random marriage. percentageRandomMarriagePanel.title=Percentage Random Marriage lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Dice Size -lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 25% chance of a character getting married every 3 years. +lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 25% chance of a character getting married every 3 years. Set to 0 to disable opposite sex marriages. lblRandomMarriageSameSexDiceSize.text=Same Sex Dice Size -lblRandomMarriageSameSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 5% chance of a character getting married every 3 years. The difference between opposite sex and same sex dice chances are based on 2022 US census data. +lblRandomMarriageSameSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 5% chance of a character getting married every 3 years. The difference between opposite sex and same sex dice chances are based on 2022 US census data. Set to 0 to disable opposite sex marriages. # Divorce -divorcePanel.title=Divorce +divorcePanel.title=Divorce (Unofficial) chkUseManualDivorce.text=Use Manual Divorce chkUseManualDivorce.toolTipText=This allows the player to disable the Remove Spouse option in the personnel table mouse adapter. chkUseClanPersonnelDivorce.text=Use Clan Personnel Divorce @@ -501,10 +499,8 @@ chkUseRandomClanPersonnelDivorce.toolTipText=Allow clan-origin personnel to rand chkUseRandomPrisonerDivorce.text=Use Random Prisoner Divorce chkUseRandomPrisonerDivorce.toolTipText=Allow random divorce when one or both of the couple are currently prisoners. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. percentageRandomDivorcePanel.title=Percentage Random Divorce -lblPercentageRandomDivorceOppositeSexChance.text=Opposite Sex Chance -lblPercentageRandomDivorceOppositeSexChance.toolTipText=This is the percent chance that a fitting member of your force will divorce their opposite sex spouse. -lblPercentageRandomDivorceSameSexChance.text=Same Sex Chance -lblPercentageRandomDivorceSameSexChance.toolTipText=This is the percent chance that a fitting member of your force will divorce their same-sex spouse. +lblRandomDivorceDiceSize.text=Divorce Dice Size +lblRandomDivorceDiceSize.toolTipText=This is the number of sides featured on the weekly die rolled to see whether a marriage ends in divorce. Divorce occurs on a roll of 1. Set to 0 to disable random divorces for all personnel. # Procreation procreationPanel.title=Procreation (Unofficial) @@ -540,9 +536,9 @@ chkUseRandomPrisonerProcreation.text=Use Random Prisoner Procreation chkUseRandomPrisonerProcreation.toolTipText=Allow prisoners to randomly procreate. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. percentageRandomProcreationPanel.title=Percentage Random Procreation lblRandomProcreationRelationshipDiceSize.text=Relationship Dice Size -lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. +lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. Set to 0 to disable procreation within a relationship. lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Dice Size -lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. +lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. Set to 0 to disable procreation outside a relationship. # Death deathPanel.title=Death @@ -685,17 +681,11 @@ lblTaxesPercentage.toolTipText=The percentage o \ Tax amount is based on profits recorded at the end of the financial term.\ \ Profits are calculated by comparing current funds against those from the prior financial term (or company starting funds).\ \ Starting Capital and End of Term Carryover sums are excluded from profit calculations. -chkUseNotMercenaryExemption.text=Non-Mercenary Exemption -chkUseNotMercenaryExemption.toolTipText=Campaigns belonging to non-mercenary factions are exempt from paying taxes. -chkUseClanExemption.text=Clan Exemption -chkUseClanExemption.toolTipText=Campaigns belonging to a 'Clan' faction are exempt from paying taxes. # Shares sharesPanel.title=Shares System chkUseShareSystem.text=Use Shares chkUseShareSystem.toolTipText=Gives personnel a stake in the unit. This system lowers profits but can increase retention. -chkSharesExcludeLargeCraft.text=Large Craft Exemption -chkSharesExcludeLargeCraft.toolTipText=Exclude large craft from net worth when calculating share value. chkSharesForAll.text=All Personnel Have Shares chkSharesForAll.toolTipText=All combat and support personnel have shares rather than just MechWarriors ##end Finances Tab diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index 8b84876804..1849cd0a25 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -1015,8 +1015,8 @@ RandomDependentMethod.AGAINST_THE_BOT.toolTipText=This follows the dependent add # RandomDivorceMethod RandomDivorceMethod.NONE.text=Disabled RandomDivorceMethod.NONE.toolTipText=Random divorce is disabled. -RandomDivorceMethod.PERCENTAGE.text=Percentage -RandomDivorceMethod.PERCENTAGE.toolTipText=This checks if a random value is lower than the percentage to determine if an eligible married person divorces on a given day. +RandomDivorceMethod.DICE_ROLL.text=Dice Roll +RandomDivorceMethod.DICE_ROLL.toolTipText=A die is rolled each week to determine whether a marriage ends in divorce. The options below determine how many sides this dice has. Divorce occurs on a roll of 1. # RandomMarriageMethod Enum RandomMarriageMethod.NONE.text=Disabled diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 0b0fa2a04e..e3388d555c 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -3413,11 +3413,6 @@ public void processNewDayPersonnel() { continue; } - // Marriage - if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { - getMarriage().processNewWeek(this, getLocalDate(), p); - } - p.resetMinutesLeft(); // Reset acquisitions made to 0 p.setAcquisition(0); @@ -3467,11 +3462,10 @@ public void processNewDayPersonnel() { } } - // Divorce - getDivorce().processNewDay(this, getLocalDate(), p); - - // Procreation + // Divorce, Marriage, & Procreation if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { + getDivorce().processNewWeek(this, getLocalDate(), p); + getMarriage().processNewWeek(this, getLocalDate(), p); getProcreation().processNewWeek(this, getLocalDate(), p); } diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index fe7b37b7dc..dcab1f7bbf 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -359,8 +359,7 @@ public static String getTransitUnitName(final int unit) { private boolean useRandomSameSexDivorce; private boolean useRandomClanPersonnelDivorce; private boolean useRandomPrisonerDivorce; - private double percentageRandomDivorceOppositeSexChance; - private double percentageRandomDivorceSameSexChance; + private int randomDivorceDiceSize; // Procreation private boolean useManualProcreation; @@ -854,10 +853,9 @@ public CampaignOptions() { setRandomMarriageMethod(RandomMarriageMethod.NONE); setUseRandomSameSexMarriages(false); setUseRandomClanPersonnelMarriages(false); - setUseRandomPrisonerMarriages(true); + setUseRandomPrisonerMarriages(false); setRandomMarriageAgeRange(10); setRandomMarriageOppositeSexDiceSize(542); - // this number was determined based on 2* the % of recorded same-sex marriages in the US circa 2022 setRandomMarriageSameSexDiceSize(3042); // Divorce @@ -874,8 +872,7 @@ public CampaignOptions() { setUseRandomSameSexDivorce(true); setUseRandomClanPersonnelDivorce(true); setUseRandomPrisonerDivorce(false); - setPercentageRandomDivorceOppositeSexChance(0.000001); - setPercentageRandomDivorceSameSexChance(0.000001); + setRandomDivorceDiceSize(3221); // Procreation setUseManualProcreation(true); @@ -2511,20 +2508,12 @@ public void setUseRandomPrisonerDivorce(final boolean useRandomPrisonerDivorce) this.useRandomPrisonerDivorce = useRandomPrisonerDivorce; } - public double getPercentageRandomDivorceOppositeSexChance() { - return percentageRandomDivorceOppositeSexChance; + public int getRandomDivorceDiceSize() { + return randomDivorceDiceSize; } - public void setPercentageRandomDivorceOppositeSexChance(final double percentageRandomDivorceOppositeSexChance) { - this.percentageRandomDivorceOppositeSexChance = percentageRandomDivorceOppositeSexChance; - } - - public double getPercentageRandomDivorceSameSexChance() { - return percentageRandomDivorceSameSexChance; - } - - public void setPercentageRandomDivorceSameSexChance(final double percentageRandomDivorceSameSexChance) { - this.percentageRandomDivorceSameSexChance = percentageRandomDivorceSameSexChance; + public void setRandomDivorceDiceSize(final int randomDivorceDiceSize) { + this.randomDivorceDiceSize = randomDivorceDiceSize; } //endregion Divorce @@ -4733,8 +4722,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomSameSexDivorce", isUseRandomSameSexDivorce()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomClanPersonnelDivorce", isUseRandomClanPersonnelDivorce()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPrisonerDivorce", isUseRandomPrisonerDivorce()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "percentageRandomDivorceOppositeSexChance", getPercentageRandomDivorceOppositeSexChance()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "percentageRandomDivorceSameSexChance", getPercentageRandomDivorceSameSexChance()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomDivorceDiceSize", getRandomDivorceDiceSize()); //endregion Divorce //region Procreation @@ -5471,10 +5459,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUseRandomClanPersonnelDivorce(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("useRandomPrisonerDivorce")) { retVal.setUseRandomPrisonerDivorce(Boolean.parseBoolean(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("percentageRandomDivorceOppositeSexChance")) { - retVal.setPercentageRandomDivorceOppositeSexChance(Double.parseDouble(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("percentageRandomDivorceSameSexChance")) { - retVal.setPercentageRandomDivorceSameSexChance(Double.parseDouble(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("randomDivorceDiceSize")) { + retVal.setRandomDivorceDiceSize(Integer.parseInt(wn2.getTextContent().trim())); //endregion Divorce //region Procreation diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 015c16a91b..4b7b974cc8 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -234,7 +234,7 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person spouse.getGenealogy().setSpouse(null); } - // Add to former spouse list + // Add to the former spouse list spouse.getGenealogy().addFormerSpouse(new FormerSpouse(origin, today, reason)); origin.getGenealogy().addFormerSpouse(new FormerSpouse(spouse, today, reason)); @@ -249,7 +249,7 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person * @param today the current day * @param person the person to process */ - public void processNewDay(final Campaign campaign, final LocalDate today, final Person person) { + public void processNewWeek(final Campaign campaign, final LocalDate today, final Person person) { if (canDivorce(person, true) != null) { return; } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java similarity index 56% rename from MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java rename to MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index b4fd1e4591..8752f59ea3 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/PercentageRandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -23,45 +23,49 @@ import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomDivorceMethod; -public class PercentageRandomDivorce extends AbstractDivorce { +public class RandomDivorce extends AbstractDivorce { //region Variable Declarations - private double oppositeSexPercentage; - private double sameSexPercentage; + private int oppositeSexDiceSize; + private int sameSexDiceSize; //endregion Variable Declarations //region Constructors - public PercentageRandomDivorce(final CampaignOptions options) { - super(RandomDivorceMethod.PERCENTAGE, options); - setOppositeSexPercentage(options.getPercentageRandomDivorceOppositeSexChance()); - setSameSexPercentage(options.getPercentageRandomDivorceSameSexChance()); + public RandomDivorce(final CampaignOptions options) { + super(RandomDivorceMethod.DICE_ROLL, options); + setOppositeSexDiceSize(options.getRandomDivorceDiceSize()); + setSameSexDiceSize(options.getRandomDivorceDiceSize()); } //endregion Constructors //region Getters/Setters - public double getOppositeSexPercentage() { - return oppositeSexPercentage; + @SuppressWarnings(value = "unused") + public int getOppositeSexDiceSize() { + return oppositeSexDiceSize; } - public void setOppositeSexPercentage(final double oppositeSexPercentage) { - this.oppositeSexPercentage = oppositeSexPercentage; + @SuppressWarnings(value = "unused") + public void setOppositeSexDiceSize(final int oppositeSexDiceSize) { + this.oppositeSexDiceSize = oppositeSexDiceSize; } - public double getSameSexPercentage() { - return sameSexPercentage; + @SuppressWarnings(value = "unused") + public int getSameSexDiceSize() { + return sameSexDiceSize; } - public void setSameSexPercentage(final double sameSexPercentage) { - this.sameSexPercentage = sameSexPercentage; + @SuppressWarnings(value = "unused") + public void setSameSexDiceSize(final int sameSexDiceSize) { + this.sameSexDiceSize = sameSexDiceSize; } //endregion Getters/Setters @Override protected boolean randomOppositeSexDivorce(final Person person) { - return Compute.randomFloat() < getOppositeSexPercentage(); + return Compute.randomInt(oppositeSexDiceSize) == 0; } @Override protected boolean randomSameSexDivorce(final Person person) { - return Compute.randomFloat() < getSameSexPercentage(); + return Compute.randomInt(sameSexDiceSize) == 0; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java index c46cda4762..9bef1f1074 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java @@ -22,14 +22,16 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.divorce.AbstractDivorce; import mekhq.campaign.personnel.divorce.DisabledRandomDivorce; -import mekhq.campaign.personnel.divorce.PercentageRandomDivorce; +import mekhq.campaign.personnel.divorce.RandomDivorce; import java.util.ResourceBundle; +import static megamek.client.ui.WrapLayout.wordWrap; + public enum RandomDivorceMethod { //region Enum Declarations NONE("RandomDivorceMethod.NONE.text", "RandomDivorceMethod.NONE.toolTipText"), - PERCENTAGE("RandomDivorceMethod.PERCENTAGE.text", "RandomDivorceMethod.PERCENTAGE.toolTipText"); + DICE_ROLL("RandomDivorceMethod.DICE_ROLL.text", "RandomDivorceMethod.DICE_ROLL.toolTipText"); //endregion Enum Declarations //region Variable Declarations @@ -42,33 +44,34 @@ public enum RandomDivorceMethod { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); this.name = resources.getString(name); - this.toolTipText = resources.getString(toolTipText); + this.toolTipText = wordWrap(resources.getString(toolTipText)); } //endregion Constructors //region Getters + @SuppressWarnings(value = "unused") public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparisons + @SuppressWarnings(value = "unused") public boolean isNone() { return this == NONE; } - public boolean isPercentage() { - return this == PERCENTAGE; + @SuppressWarnings(value = "unused") + public boolean isDiceRoll() { + return this == DICE_ROLL; } //endregion Boolean Comparisons public AbstractDivorce getMethod(final CampaignOptions options) { - switch (this) { - case PERCENTAGE: - return new PercentageRandomDivorce(options); - case NONE: - default: - return new DisabledRandomDivorce(options); + if (this == DICE_ROLL) { + return new RandomDivorce(options); + } else { + return new DisabledRandomDivorce(options); } } diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index 99b85f5864..eb4fc16ddb 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -53,7 +53,7 @@ import mekhq.campaign.personnel.death.AgeRangeRandomDeath; import mekhq.campaign.personnel.death.ExponentialRandomDeath; import mekhq.campaign.personnel.death.PercentageRandomDeath; -import mekhq.campaign.personnel.divorce.PercentageRandomDivorce; +import mekhq.campaign.personnel.divorce.RandomDivorce; import mekhq.campaign.personnel.enums.*; import mekhq.campaign.personnel.marriage.RandomMarriage; import mekhq.campaign.personnel.procreation.AbstractProcreation; @@ -1484,11 +1484,11 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { getCampaign().getDivorce().setUseRandomSameSexDivorce(newOptions.isUseRandomSameSexDivorce()); getCampaign().getDivorce().setUseRandomClanPersonnelDivorce(newOptions.isUseRandomClanPersonnelDivorce()); getCampaign().getDivorce().setUseRandomPrisonerDivorce(newOptions.isUseRandomPrisonerDivorce()); - if (getCampaign().getDivorce().getMethod().isPercentage()) { - ((PercentageRandomDivorce) getCampaign().getDivorce()).setOppositeSexPercentage( - newOptions.getPercentageRandomDivorceOppositeSexChance()); - ((PercentageRandomDivorce) getCampaign().getDivorce()).setSameSexPercentage( - newOptions.getPercentageRandomDivorceSameSexChance()); + if (getCampaign().getDivorce().getMethod().isDiceRoll()) { + ((RandomDivorce) getCampaign().getDivorce()).setOppositeSexDiceSize( + newOptions.getRandomDivorceDiceSize()); + ((RandomDivorce) getCampaign().getDivorce()).setSameSexDiceSize( + newOptions.getRandomDivorceDiceSize()); } } diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index 7f944488f7..3f3c6a57a9 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -389,10 +389,8 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseRandomSameSexDivorce; private JCheckBox chkUseRandomClanPersonnelDivorce; private JCheckBox chkUseRandomPrisonerDivorce; - private JLabel lblPercentageRandomDivorceOppositeSexChance; - private JSpinner spnPercentageRandomDivorceOppositeSexChance; - private JLabel lblPercentageRandomDivorceSameSexChance; - private JSpinner spnPercentageRandomDivorceSameSexChance; + private JLabel lblRandomDivorceDiceSize; + private JSpinner spnRandomDivorceDiceSize; // Procreation private JCheckBox chkUseManualProcreation; @@ -5724,19 +5722,19 @@ public Component getListCellRendererComponent(final JList list, final Object private void createPercentageRandomMarriagePanel(final JPanel panel) { // Create Panel Components final JLabel lblRandomMarriageOppositeSexDiceSize = new JLabel(resources.getString("lblRandomMarriageOppositeSexDiceSize.text")); - lblRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"), 100)); + lblRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"))); lblRandomMarriageOppositeSexDiceSize.setName("lblRandomMarriageOppositeSexDiceSize"); - spnRandomMarriageOppositeSexDiceSize = new JSpinner(new SpinnerNumberModel(0, 0, 100000, 1)); - spnRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"), 100)); + spnRandomMarriageOppositeSexDiceSize = new JSpinner(new SpinnerNumberModel(542, 0, 100000, 1)); + spnRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"))); spnRandomMarriageOppositeSexDiceSize.setName("spnPercentageRandomMarriageOppositeSexChance"); lblRandomMarriageSameSexDiceSize = new JLabel(resources.getString("lblRandomMarriageSameSexDiceSize.text")); - lblRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"), 100)); + lblRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"))); lblRandomMarriageSameSexDiceSize.setName("lblRandomMarriageSameSexDiceSize"); - spnRandomMarriageSameSexDiceSize = new JSpinner(new SpinnerNumberModel(0, 0, 100000, 1)); - spnRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"), 100)); + spnRandomMarriageSameSexDiceSize = new JSpinner(new SpinnerNumberModel(3042, 0, 100000, 1)); + spnRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"))); spnRandomMarriageSameSexDiceSize.setName("spnRandomMarriageSameSexDiceSize"); // Programmatically Assign Accessibility Labels @@ -5893,49 +5891,23 @@ public Component getListCellRendererComponent(final JList list, final Object return; } final boolean enabled = !method.isNone(); - final boolean oppositeSexEnabled = enabled && chkUseRandomOppositeSexDivorce.isSelected(); - final boolean sameSexEnabled = enabled && chkUseRandomSameSexDivorce.isSelected(); - final boolean percentageEnabled = method.isPercentage(); + final boolean percentageEnabled = method.isDiceRoll(); chkUseRandomOppositeSexDivorce.setEnabled(enabled); chkUseRandomSameSexDivorce.setEnabled(enabled); chkUseRandomClanPersonnelDivorce.setEnabled(enabled && chkUseClanPersonnelDivorce.isSelected()); chkUseRandomPrisonerDivorce.setEnabled(enabled && chkUsePrisonerDivorce.isSelected()); percentageRandomDivorcePanel.setEnabled(percentageEnabled); - lblPercentageRandomDivorceOppositeSexChance.setEnabled(oppositeSexEnabled && percentageEnabled); - spnPercentageRandomDivorceOppositeSexChance.setEnabled(oppositeSexEnabled && percentageEnabled); - lblPercentageRandomDivorceSameSexChance.setEnabled(sameSexEnabled && percentageEnabled); - spnPercentageRandomDivorceSameSexChance.setEnabled(sameSexEnabled && percentageEnabled); + lblRandomDivorceDiceSize.setEnabled(percentageEnabled); + spnRandomDivorceDiceSize.setEnabled(percentageEnabled); }); chkUseRandomOppositeSexDivorce = new JCheckBox(resources.getString("chkUseRandomOppositeSexDivorce.text")); chkUseRandomOppositeSexDivorce.setToolTipText(resources.getString("chkUseRandomOppositeSexDivorce.toolTipText")); chkUseRandomOppositeSexDivorce.setName("chkUseRandomOppositeSexDivorce"); - chkUseRandomOppositeSexDivorce.addActionListener(evt -> { - final RandomDivorceMethod method = comboRandomDivorceMethod.getSelectedItem(); - if (method == null) { - return; - } - final boolean selected = chkUseRandomOppositeSexDivorce.isEnabled() - && chkUseRandomOppositeSexDivorce.isSelected(); - final boolean percentageEnabled = selected && method.isPercentage(); - lblPercentageRandomDivorceOppositeSexChance.setEnabled(percentageEnabled); - spnPercentageRandomDivorceOppositeSexChance.setEnabled(percentageEnabled); - }); chkUseRandomSameSexDivorce = new JCheckBox(resources.getString("chkUseRandomSameSexDivorce.text")); chkUseRandomSameSexDivorce.setToolTipText(resources.getString("chkUseRandomSameSexDivorce.toolTipText")); chkUseRandomSameSexDivorce.setName("chkUseRandomSameSexDivorce"); - chkUseRandomSameSexDivorce.addActionListener(evt -> { - final RandomDivorceMethod method = comboRandomDivorceMethod.getSelectedItem(); - if (method == null) { - return; - } - final boolean selected = chkUseRandomSameSexDivorce.isEnabled() - && chkUseRandomSameSexDivorce.isSelected(); - final boolean percentageEnabled = selected && method.isPercentage(); - lblPercentageRandomDivorceSameSexChance.setEnabled(percentageEnabled); - spnPercentageRandomDivorceSameSexChance.setEnabled(percentageEnabled); - }); chkUseRandomClanPersonnelDivorce = new JCheckBox(resources.getString("chkUseRandomClanPersonnelDivorce.text")); chkUseRandomClanPersonnelDivorce.setToolTipText(resources.getString("chkUseRandomClanPersonnelDivorce.toolTipText")); @@ -5989,31 +5961,20 @@ public Component getListCellRendererComponent(final JList list, final Object private void createPercentageRandomDivorcePanel(final JPanel panel) { // Create Panel Components - lblPercentageRandomDivorceOppositeSexChance = new JLabel(resources.getString("lblPercentageRandomDivorceOppositeSexChance.text")); - lblPercentageRandomDivorceOppositeSexChance.setToolTipText(resources.getString("lblPercentageRandomDivorceOppositeSexChance.toolTipText")); - lblPercentageRandomDivorceOppositeSexChance.setName("lblPercentageRandomDivorceOppositeSexChance"); - - spnPercentageRandomDivorceOppositeSexChance = new JSpinner(new SpinnerNumberModel(0, 0, 100, 0.00001)); - spnPercentageRandomDivorceOppositeSexChance.setToolTipText(resources.getString("lblPercentageRandomDivorceOppositeSexChance.toolTipText")); - spnPercentageRandomDivorceOppositeSexChance.setName("spnPercentageRandomDivorceOppositeSexChance"); - spnPercentageRandomDivorceOppositeSexChance.setEditor(new NumberEditor(spnPercentageRandomDivorceOppositeSexChance, "0.00000")); + lblRandomDivorceDiceSize = new JLabel(resources.getString("lblRandomDivorceDiceSize.text")); + lblRandomDivorceDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomDivorceDiceSize.toolTipText"))); + lblRandomDivorceDiceSize.setName("lblRandomDivorceDiceSize"); - lblPercentageRandomDivorceSameSexChance = new JLabel(resources.getString("lblPercentageRandomDivorceSameSexChance.text")); - lblPercentageRandomDivorceSameSexChance.setToolTipText(resources.getString("lblPercentageRandomDivorceSameSexChance.toolTipText")); - lblPercentageRandomDivorceSameSexChance.setName("lblPercentageRandomDivorceSameSexChance"); - - spnPercentageRandomDivorceSameSexChance = new JSpinner(new SpinnerNumberModel(0, 0, 100, 0.00001)); - spnPercentageRandomDivorceSameSexChance.setToolTipText(resources.getString("lblPercentageRandomDivorceSameSexChance.toolTipText")); - spnPercentageRandomDivorceSameSexChance.setName("spnPercentageRandomDivorceSameSexChance"); - spnPercentageRandomDivorceSameSexChance.setEditor(new NumberEditor(spnPercentageRandomDivorceSameSexChance, "0.00000")); + spnRandomDivorceDiceSize = new JSpinner(new SpinnerNumberModel(3221, 0, 100000, 1)); + spnRandomDivorceDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomDivorceDiceSize.toolTipText"))); + spnRandomDivorceDiceSize.setName("spnRandomDivorceDiceSize"); // Programmatically Assign Accessibility Labels - lblPercentageRandomDivorceOppositeSexChance.setLabelFor(spnPercentageRandomDivorceOppositeSexChance); - lblPercentageRandomDivorceSameSexChance.setLabelFor(spnPercentageRandomDivorceSameSexChance); + lblRandomDivorceDiceSize.setLabelFor(spnRandomDivorceDiceSize); // Layout the Panel panel.setBorder(BorderFactory.createTitledBorder(resources.getString("percentageRandomDivorcePanel.title"))); - panel.setToolTipText(RandomDivorceMethod.PERCENTAGE.getToolTipText()); + panel.setToolTipText(RandomDivorceMethod.DICE_ROLL.getToolTipText()); final GroupLayout layout = new GroupLayout(panel); layout.setAutoCreateGaps(true); @@ -6023,21 +5984,15 @@ private void createPercentageRandomDivorcePanel(final JPanel panel) { layout.setVerticalGroup( layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblPercentageRandomDivorceOppositeSexChance) - .addComponent(spnPercentageRandomDivorceOppositeSexChance, Alignment.LEADING)) - .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblPercentageRandomDivorceSameSexChance) - .addComponent(spnPercentageRandomDivorceSameSexChance, Alignment.LEADING)) + .addComponent(lblRandomDivorceDiceSize) + .addComponent(spnRandomDivorceDiceSize, Alignment.LEADING)) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(lblPercentageRandomDivorceOppositeSexChance) - .addComponent(spnPercentageRandomDivorceOppositeSexChance)) - .addGroup(layout.createSequentialGroup() - .addComponent(lblPercentageRandomDivorceSameSexChance) - .addComponent(spnPercentageRandomDivorceSameSexChance)) + .addComponent(lblRandomDivorceDiceSize) + .addComponent(spnRandomDivorceDiceSize)) ); } @@ -6620,19 +6575,19 @@ public Component getListCellRendererComponent(final JList list, final Object private void createPercentageRandomProcreationPanel(final JPanel panel) { // Create Panel Components final JLabel lblRandomProcreationRelationshipDiceSize = new JLabel(resources.getString("lblRandomProcreationRelationshipDiceSize.text")); - lblRandomProcreationRelationshipDiceSize.setToolTipText(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText")); + lblRandomProcreationRelationshipDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"))); lblRandomProcreationRelationshipDiceSize.setName("lblRandomProcreationRelationshipDiceSize"); spnRandomProcreationRelationshipDiceSize = new JSpinner(new SpinnerNumberModel(621, 0, 100000, 1)); - spnRandomProcreationRelationshipDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"), 100)); + spnRandomProcreationRelationshipDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"))); spnRandomProcreationRelationshipDiceSize.setName("spnRandomProcreationRelationshipDiceSize"); lblRandomProcreationRelationshiplessDiceSize = new JLabel(resources.getString("lblRandomProcreationRelationshiplessDiceSize.text")); - lblRandomProcreationRelationshiplessDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshiplessDiceSize.toolTipText"), 100)); + lblRandomProcreationRelationshiplessDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshiplessDiceSize.toolTipText"))); lblRandomProcreationRelationshiplessDiceSize.setName("lblRandomProcreationRelationshiplessDiceSize"); spnRandomProcreationRelationshiplessDiceSize = new JSpinner(new SpinnerNumberModel(1861, 0, 100000, 1)); - spnRandomProcreationRelationshiplessDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"), 100)); + spnRandomProcreationRelationshiplessDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomProcreationRelationshipDiceSize.toolTipText"))); spnRandomProcreationRelationshiplessDiceSize.setName("spnRandomProcreationRelationshiplessDiceSize"); // Programmatically Assign Accessibility Labels @@ -8257,8 +8212,7 @@ public void setOptions(@Nullable CampaignOptions options, } chkUseRandomClanPersonnelDivorce.setSelected(options.isUseRandomClanPersonnelDivorce()); chkUseRandomPrisonerDivorce.setSelected(options.isUseRandomPrisonerDivorce()); - spnPercentageRandomDivorceOppositeSexChance.setValue(options.getPercentageRandomDivorceOppositeSexChance() * 100.0); - spnPercentageRandomDivorceSameSexChance.setValue(options.getPercentageRandomDivorceSameSexChance() * 100.0); + spnRandomDivorceDiceSize.setValue(options.getRandomDivorceDiceSize()); // Procreation chkUseManualProcreation.setSelected(options.isUseManualProcreation()); @@ -8933,8 +8887,7 @@ public void updateOptions() { options.setUseRandomSameSexDivorce(chkUseRandomSameSexDivorce.isSelected()); options.setUseRandomClanPersonnelDivorce(chkUseRandomClanPersonnelDivorce.isSelected()); options.setUseRandomPrisonerDivorce(chkUseRandomPrisonerDivorce.isSelected()); - options.setPercentageRandomDivorceOppositeSexChance((Double) spnPercentageRandomDivorceOppositeSexChance.getValue() / 100.0); - options.setPercentageRandomDivorceSameSexChance((Double) spnPercentageRandomDivorceSameSexChance.getValue() / 100.0); + options.setRandomDivorceDiceSize((int) spnRandomDivorceDiceSize.getValue()); // Procreation options.setUseManualProcreation(chkUseManualProcreation.isSelected()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java index 3076dc8835..9c8809016f 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java @@ -125,7 +125,7 @@ public void testDivorce() { //region New Day @Disabled // FIXME : Windchild : Test Missing @Test - public void testProcessNewDay() { + public void testProcessNewWeek() { } //endregion New Day diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java index 7ad64a7f29..c80db69a90 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java @@ -49,41 +49,34 @@ public void beforeEach() { when(mockOptions.isUseRandomSameSexDivorce()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelDivorce()).thenReturn(false); when(mockOptions.isUseRandomPrisonerDivorce()).thenReturn(false); - when(mockOptions.getPercentageRandomDivorceOppositeSexChance()).thenReturn(0.5); - when(mockOptions.getPercentageRandomDivorceSameSexChance()).thenReturn(0.5); + when(mockOptions.getRandomDivorceDiceSize()).thenReturn(5); } @Test public void testRandomOppositeSexDivorce() { - final PercentageRandomDivorce percentageRandomDivorce = new PercentageRandomDivorce(mockOptions); - // This ignores the person, so just using a mocked person - // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) + final RandomDivorce randomDivorce = new RandomDivorce(mockOptions); + + int diceSize = 5; + try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); - assertTrue(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); - assertTrue(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); - assertFalse(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); - assertFalse(percentageRandomDivorce.randomOppositeSexDivorce(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); + assertTrue(randomDivorce.randomOppositeSexDivorce(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); + assertFalse(randomDivorce.randomOppositeSexDivorce(mockPerson)); } } @Test public void testRandomSameSexDivorce() { - final PercentageRandomDivorce percentageRandomDivorce = new PercentageRandomDivorce(mockOptions); - // This ignores the person, so just using a mocked person - // Testing Minimum (0f), Below Value (0.49f), At Value (0.5f), and Maximum (1f) + final RandomDivorce randomDivorce = new RandomDivorce(mockOptions); + + int diceSize = 5; + try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(Compute::randomFloat).thenReturn(0f); - assertTrue(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.49f); - assertTrue(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(0.5f); - assertFalse(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); - compute.when(Compute::randomFloat).thenReturn(1f); - assertFalse(percentageRandomDivorce.randomSameSexDivorce(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); + assertTrue(randomDivorce.randomOppositeSexDivorce(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); + assertFalse(randomDivorce.randomOppositeSexDivorce(mockPerson)); } } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java index c3de04b461..63b830e974 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java @@ -21,11 +21,12 @@ import mekhq.MekHQ; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.divorce.DisabledRandomDivorce; -import mekhq.campaign.personnel.divorce.PercentageRandomDivorce; +import mekhq.campaign.personnel.divorce.RandomDivorce; import org.junit.jupiter.api.Test; import java.util.ResourceBundle; +import static megamek.client.ui.WrapLayout.wordWrap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -44,10 +45,10 @@ public class RandomDivorceMethodTest { //region Getters @Test public void testGetToolTipText() { - assertEquals(resources.getString("RandomDivorceMethod.NONE.toolTipText"), - RandomDivorceMethod.NONE.getToolTipText()); - assertEquals(resources.getString("RandomDivorceMethod.PERCENTAGE.toolTipText"), - RandomDivorceMethod.PERCENTAGE.getToolTipText()); + String expected = wordWrap(resources.getString("RandomDivorceMethod.NONE.toolTipText")).replaceAll("\\s", ""); + String actual = wordWrap(RandomDivorceMethod.NONE.getToolTipText().trim()).replaceAll("\\s", ""); + + assertEquals(expected, actual); } //endregion Getters @@ -64,12 +65,12 @@ public void testIsNone() { } @Test - public void testIsPercentage() { + public void testIsDiceRoll() { for (final RandomDivorceMethod randomDivorceMethod : methods) { - if (randomDivorceMethod == RandomDivorceMethod.PERCENTAGE) { - assertTrue(randomDivorceMethod.isPercentage()); + if (randomDivorceMethod == RandomDivorceMethod.DICE_ROLL) { + assertTrue(randomDivorceMethod.isDiceRoll()); } else { - assertFalse(randomDivorceMethod.isPercentage()); + assertFalse(randomDivorceMethod.isDiceRoll()); } } } @@ -84,18 +85,17 @@ public void testGetMethod() { when(mockOptions.isUseRandomSameSexDivorce()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelDivorce()).thenReturn(false); when(mockOptions.isUseRandomPrisonerDivorce()).thenReturn(false); - when(mockOptions.getPercentageRandomDivorceOppositeSexChance()).thenReturn(0.5); - when(mockOptions.getPercentageRandomDivorceSameSexChance()).thenReturn(0.5); + when(mockOptions.getRandomDivorceDiceSize()).thenReturn(5); assertInstanceOf(DisabledRandomDivorce.class, RandomDivorceMethod.NONE.getMethod(mockOptions)); - assertInstanceOf(PercentageRandomDivorce.class, RandomDivorceMethod.PERCENTAGE.getMethod(mockOptions)); + assertInstanceOf(RandomDivorce.class, RandomDivorceMethod.DICE_ROLL.getMethod(mockOptions)); } @Test public void testToStringOverride() { assertEquals(resources.getString("RandomDivorceMethod.NONE.text"), RandomDivorceMethod.NONE.toString()); - assertEquals(resources.getString("RandomDivorceMethod.PERCENTAGE.text"), - RandomDivorceMethod.PERCENTAGE.toString()); + assertEquals(resources.getString("RandomDivorceMethod.DICE_ROLL.text"), + RandomDivorceMethod.DICE_ROLL.toString()); } } From bd3f38717ff47b0eebb39484710b05c43b4cbc79 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 20:53:16 -0500 Subject: [PATCH 09/41] Deprecate `useRandomSameSexMarriages` option Marked the `useRandomSameSexMarriages` option as deprecated and removed its handling from various parts of the code. Legacy support was added to ensure compatibility with versions prior to 50.0. --- MekHQ/src/mekhq/campaign/CampaignOptions.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index dcab1f7bbf..c5a574f900 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -342,7 +342,7 @@ public static String getTransitUnitName(final int unit) { private boolean logMarriageNameChanges; private Map marriageSurnameWeights; private RandomMarriageMethod randomMarriageMethod; - private boolean useRandomSameSexMarriages; + private boolean useRandomSameSexMarriages; // legacy, pre-50.0 private boolean useRandomClanPersonnelMarriages; private boolean useRandomPrisonerMarriages; private int randomMarriageAgeRange; @@ -851,7 +851,6 @@ public CampaignOptions() { getMarriageSurnameWeights().put(MergingSurnameStyle.MALE, 500); getMarriageSurnameWeights().put(MergingSurnameStyle.FEMALE, 160); setRandomMarriageMethod(RandomMarriageMethod.NONE); - setUseRandomSameSexMarriages(false); setUseRandomClanPersonnelMarriages(false); setUseRandomPrisonerMarriages(false); setRandomMarriageAgeRange(10); @@ -2359,6 +2358,7 @@ public void setRandomMarriageMethod(final RandomMarriageMethod randomMarriageMet /** * @return whether or not to use random same-sex marriages */ + @Deprecated public boolean isUseRandomSameSexMarriages() { return useRandomSameSexMarriages; } @@ -2366,6 +2366,7 @@ public boolean isUseRandomSameSexMarriages() { /** * @param useRandomSameSexMarriages whether or not to use random same-sex marriages */ + @Deprecated public void setUseRandomSameSexMarriages(final boolean useRandomSameSexMarriages) { this.useRandomSameSexMarriages = useRandomSameSexMarriages; } @@ -4700,7 +4701,6 @@ public void writeToXml(final PrintWriter pw, int indent) { } MHQXMLUtility.writeSimpleXMLCloseTag(pw, --indent, "marriageSurnameWeights"); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageMethod", getRandomMarriageMethod().name()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomSameSexMarriages", isUseRandomSameSexMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomClanPersonnelMarriages", isUseRandomClanPersonnelMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPrisonerMarriages", isUseRandomPrisonerMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageAgeRange", getRandomMarriageAgeRange()); @@ -5411,8 +5411,6 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve } } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageMethod")) { retVal.setRandomMarriageMethod(RandomMarriageMethod.valueOf(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("useRandomSameSexMarriages")) { - retVal.setUseRandomSameSexMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("useRandomClanPersonnelMarriages") || wn2.getNodeName().equalsIgnoreCase("useRandomClannerMarriages")) { // Legacy, 0.49.12 removal retVal.setUseRandomClanPersonnelMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); @@ -5424,6 +5422,10 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setRandomMarriageOppositeSexDiceSize(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageSameSexChance")) { retVal.setRandomMarriageSameSexDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("useRandomSameSexMarriages")) { + if (!Boolean.parseBoolean(wn2.getTextContent().trim())) { + retVal.setRandomMarriageSameSexDiceSize(0); // legacy, pre-50.0 + } //endregion Marriage //region Divorce From 0beba4cababa341cab9f6cf1a5ca09b512f79356 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 20:58:26 -0500 Subject: [PATCH 10/41] Update panel titles in CampaignOptionsDialog Renamed several panels for clarity. Removed terms like "Percentage" and "Unofficial" and standardized titles related to "Random Marriage" and "Random Dice". --- .../mekhq/resources/CampaignOptionsDialog.properties | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 321d1bd1ef..10e63657f2 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -460,7 +460,7 @@ chkLogMarriageNameChanges.text=Log Marriage Name Changes chkLogMarriageNameChanges.toolTipText=This enables the addition of a personnel log entry whenever a name is changed during marriage. marriageSurnameWeightsPanel.title=Marriage Surname Weights marriageSurnameWeightsPanel.toolTipText=These are the weights used in determining the surname change, if any, when using the Weighted Marriage option.
They will be the percent chance if the values for the weights all add up to 100. -randomMarriagePanel.title=Random Marriages (Unofficial) +randomMarriagePanel.title=Random Marriages lblRandomMarriageMethod.text=Random Marriage Method lblRandomMarriageMethod.toolTipText=This is the method used to determine if an eligible person randomly marries. chkUseRandomSameSexMarriages.text=Use Same-sex Random Marriage @@ -471,7 +471,7 @@ chkUseRandomPrisonerMarriages.text=Use Random Prisoner Marriages chkUseRandomPrisonerMarriages.toolTipText=Allow prisoners to randomly marry other prisoners. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. lblRandomMarriageAgeRange.text=Random Marriage Age Range lblRandomMarriageAgeRange.toolTipText=This plus/minus age forms the possible range of ages for spouses in the forming of a random marriage. -percentageRandomMarriagePanel.title=Percentage Random Marriage +percentageRandomMarriagePanel.title=Marriage Dice lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Dice Size lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 25% chance of a character getting married every 3 years. Set to 0 to disable opposite sex marriages. lblRandomMarriageSameSexDiceSize.text=Same Sex Dice Size @@ -487,7 +487,7 @@ chkUsePrisonerDivorce.text=Use Prisoner Divorce chkUsePrisonerDivorce.toolTipText=Allow divorce when one or both of the couple are currently prisoners. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. divorceSurnameWeightsPanel.title=Divorce Surname Weights divorceSurnameWeightsPanel.toolTipText=These are the weights used in determining the surname change, if any, when using the Weighted Divorce option.
They will be the percent chance if the values for the weights all add up to 100. -randomDivorcePanel.title=Random Divorce (Unofficial) +randomDivorcePanel.title=Random Divorce lblRandomDivorceMethod.text=Random Divorce Method lblRandomDivorceMethod.toolTipText=This is the method used to determine if an eligible person randomly divorces. chkUseRandomOppositeSexDivorce.text=Use Random Opposite Sex Divorce @@ -498,7 +498,7 @@ chkUseRandomClanPersonnelDivorce.text=Use Random Clan Personnel Divorce chkUseRandomClanPersonnelDivorce.toolTipText=Allow clan-origin personnel to randomly divorce, whether as the origin or the spouse. chkUseRandomPrisonerDivorce.text=Use Random Prisoner Divorce chkUseRandomPrisonerDivorce.toolTipText=Allow random divorce when one or both of the couple are currently prisoners. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. -percentageRandomDivorcePanel.title=Percentage Random Divorce +percentageRandomDivorcePanel.title=Divorce Dice lblRandomDivorceDiceSize.text=Divorce Dice Size lblRandomDivorceDiceSize.toolTipText=This is the number of sides featured on the weekly die rolled to see whether a marriage ends in divorce. Divorce occurs on a roll of 1. Set to 0 to disable random divorces for all personnel. @@ -534,7 +534,7 @@ chkUseRandomClanPersonnelProcreation.text=Use Random Clan Personnel Procreation chkUseRandomClanPersonnelProcreation.toolTipText=Allow clan-origin personnel to randomly procreate. chkUseRandomPrisonerProcreation.text=Use Random Prisoner Procreation chkUseRandomPrisonerProcreation.toolTipText=Allow prisoners to randomly procreate. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. -percentageRandomProcreationPanel.title=Percentage Random Procreation +percentageRandomProcreationPanel.title=Procreation Dice lblRandomProcreationRelationshipDiceSize.text=Relationship Dice Size lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. Set to 0 to disable procreation within a relationship. lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Dice Size From fcac23535c1c1a300c31c1d7c7a738c4a86afba0 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 29 Jul 2024 22:53:12 -0500 Subject: [PATCH 11/41] Adjusted marriage and procreation dice sizes. Increased the dice sizes for random marriages and procreation to create more diverse outcomes. Also added a preliminary system to simulate failed relationships in both opposite-sex and same-sex marriages. --- MekHQ/src/mekhq/campaign/CampaignOptions.java | 8 ++++---- .../personnel/marriage/RandomMarriage.java | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index c5a574f900..ccd551d79e 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -854,8 +854,8 @@ public CampaignOptions() { setUseRandomClanPersonnelMarriages(false); setUseRandomPrisonerMarriages(false); setRandomMarriageAgeRange(10); - setRandomMarriageOppositeSexDiceSize(542); - setRandomMarriageSameSexDiceSize(3042); + setRandomMarriageOppositeSexDiceSize(6250); + setRandomMarriageSameSexDiceSize(76923); // Divorce setUseManualDivorce(true); @@ -889,9 +889,9 @@ public CampaignOptions() { setUseRandomClanPersonnelProcreation(false); setUseRandomPrisonerProcreation(true); setRandomProcreationRelationshipDiceSize(621); - setRandomProcreationRelationshiplessDiceSize(1861); + setRandomProcreationRelationshiplessDiceSize(8871); - // Education + // Education setUseEducationModule(false); setCurriculumXpRate(3); setMaximumJumpCount(5); diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index 67f5c79012..34f9ae1555 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -63,6 +63,13 @@ public void setSameSexDiceSize(final int sameSexDiceSize) { @Override protected boolean randomOppositeSexMarriage(final Person person) { + // this is used to simulate failed relationships. + // it's very arbitrary but serves its purpose for now. + // TODO: replace this with a proper relationship system + if (Compute.randomInt(100) != 0) { + return false; + } + int multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size()); return Compute.randomInt(oppositeSexDiceSize * multiplier) == 0; @@ -70,6 +77,13 @@ protected boolean randomOppositeSexMarriage(final Person person) { @Override protected boolean randomSameSexMarriage(final Person person) { + // this is used to simulate failed relationships. + // it's very arbitrary but serves its purpose for now. + // TODO: replace this with a proper relationship system + if (Compute.randomInt(100) != 0) { + return false; + } + int multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size()); return Compute.randomInt(sameSexDiceSize * multiplier) == 0; From 27b9c663b83a2fc9053c2db1c6af343f8ff19c7a Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 11:39:22 -0500 Subject: [PATCH 12/41] Refactored random divorce logic and fixed procreation class name Consolidated `randomOppositeSexDivorce` and `randomSameSexDivorce` into `randomDivorce`. Updated method calls and test cases to reflect this change. Fixed class name for `RandomProcreation` to adhere to naming conventions. --- .../mekhq/resources/Personnel.properties | 1 + .../personnel/divorce/AbstractDivorce.java | 26 +++++++------- .../divorce/DisabledRandomDivorce.java | 7 +--- .../personnel/divorce/RandomDivorce.java | 35 ++++++------------- .../enums/RandomProcreationMethod.java | 6 ++-- .../personnel/familyTree/Genealogy.java | 29 ++++++++++++++- .../personnel/marriage/AbstractMarriage.java | 8 +++-- .../personnel/marriage/RandomMarriage.java | 2 +- ...rocreation.java => RandomProcreation.java} | 6 ++-- MekHQ/src/mekhq/gui/CampaignGUI.java | 11 +++--- .../divorce/DisabledRandomDivorceTest.java | 9 ++--- .../divorce/PercentageRandomDivorceTest.java | 27 ++++++-------- .../enums/RandomProcreationMethodTest.java | 6 ++-- .../procreation/RandomProcreationTest.java | 4 +-- 14 files changed, 88 insertions(+), 89 deletions(-) rename MekHQ/src/mekhq/campaign/personnel/procreation/{randomProcreation.java => RandomProcreation.java} (92%) diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index 1849cd0a25..b3bebd9c8b 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -28,6 +28,7 @@ cannotDivorce.RandomClanPersonnel.text=They are from a clan, and random clan per cannotDivorce.RandomClanPersonnelSpouse.text=Their spouse is from a clan, and random clan personnel divorce is disabled. cannotDivorce.RandomPrisoner.text=They are a prisoner, and random prisoner divorce is disabled. cannotDivorce.RandomPrisonerSpouse.text=Their spouse is a prisoner, and random prisoner divorce is disabled. +cannotDivorce.RandomNotOriginSpouse.text=Only the character that initiated a marriage can roll for divorce cannotDivorce.OppositeSexDivorceDisabled.text=They cannot randomly divorce as they are in an opposite sex marriage and opposite sex random divorce is disabled. cannotDivorce.SameSexDivorceDisabled.text=They cannot randomly divorce as they are in a same-sex marriage and same-sex random divorce is disabled. divorce.report=%s has divorced %s. diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 4b7b974cc8..7746484985 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -150,8 +150,12 @@ public void setUseRandomPrisonerDivorce(final boolean useRandomPrisonerDivorce) return resources.getString("cannotDivorce.RandomPrisoner.text"); } else if (!isUseRandomPrisonerDivorce() && person.getGenealogy().getSpouse().getPrisonerStatus().isCurrentPrisoner()) { return resources.getString("cannotDivorce.RandomPrisonerSpouse.text"); + } else if (!person.equals(person.getGenealogy().getOriginSpouse())) { + return resources.getString("cannotDivorce.RandomNotOriginSpouse.text"); } + final boolean sameSex = person.getGenealogy().getSpouse().getGender() == person.getGender(); + if (!isUseRandomOppositeSexDivorce() && !sameSex) { return resources.getString("cannotDivorce.OppositeSexDivorceDisabled.text"); } else if (!isUseRandomSameSexDivorce() && sameSex) { @@ -238,6 +242,10 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person spouse.getGenealogy().addFormerSpouse(new FormerSpouse(origin, today, reason)); origin.getGenealogy().addFormerSpouse(new FormerSpouse(spouse, today, reason)); + // Clear origin spouses + origin.getGenealogy().setOriginSpouse(null); + spouse.getGenealogy().setOriginSpouse(null); + MekHQ.triggerEvent(new PersonChangedEvent(spouse)); MekHQ.triggerEvent(new PersonChangedEvent(origin)); } @@ -254,26 +262,18 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final return; } - if ((person.getGenealogy().getSpouse().getGender() == person.getGender()) - ? randomSameSexDivorce(person) : randomOppositeSexDivorce(person)) { + if (randomDivorce(person)) { divorce(campaign, today, person, SplittingSurnameStyle.WEIGHTED); } } //region Random Divorce /** - * This determines if a person will randomly divorce their opposite sex spouse - * @param person the person to determine if they are to randomly divorce their opposite sex spouse - * @return true if the person is to randomly divorce - */ - protected abstract boolean randomOppositeSexDivorce(final Person person); - - /** - * This determines if a person will randomly divorce their same-sex spouse. - * @param person the person who may be randomly divorcing their same-sex spouse + * This determines if a person will randomly divorce their spouse + * @param person the person to determine if they are to randomly divorce their spouse * @return true if the person is to randomly divorce */ - protected abstract boolean randomSameSexDivorce(final Person person); + protected abstract boolean randomDivorce(final Person person); //endregion Random Divorce //endregion New Day } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java index 1cdfeb0fc8..7f1b143d37 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java @@ -30,12 +30,7 @@ public DisabledRandomDivorce(final CampaignOptions options) { //endregion Constructors @Override - protected boolean randomOppositeSexDivorce(final Person person) { - return false; - } - - @Override - protected boolean randomSameSexDivorce(final Person person) { + protected boolean randomDivorce(final Person person) { return false; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index 8752f59ea3..9041b7b1a8 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -25,47 +25,32 @@ public class RandomDivorce extends AbstractDivorce { //region Variable Declarations - private int oppositeSexDiceSize; - private int sameSexDiceSize; + private int divorceDiceSize; //endregion Variable Declarations //region Constructors public RandomDivorce(final CampaignOptions options) { super(RandomDivorceMethod.DICE_ROLL, options); - setOppositeSexDiceSize(options.getRandomDivorceDiceSize()); - setSameSexDiceSize(options.getRandomDivorceDiceSize()); + setDivorceDiceSize(options.getRandomDivorceDiceSize()); } //endregion Constructors //region Getters/Setters @SuppressWarnings(value = "unused") - public int getOppositeSexDiceSize() { - return oppositeSexDiceSize; + public int getDivorceDiceSize() { + return divorceDiceSize; } @SuppressWarnings(value = "unused") - public void setOppositeSexDiceSize(final int oppositeSexDiceSize) { - this.oppositeSexDiceSize = oppositeSexDiceSize; - } - - @SuppressWarnings(value = "unused") - public int getSameSexDiceSize() { - return sameSexDiceSize; - } - - @SuppressWarnings(value = "unused") - public void setSameSexDiceSize(final int sameSexDiceSize) { - this.sameSexDiceSize = sameSexDiceSize; + public void setDivorceDiceSize(final int divorceDiceSize) { + this.divorceDiceSize = divorceDiceSize; } //endregion Getters/Setters @Override - protected boolean randomOppositeSexDivorce(final Person person) { - return Compute.randomInt(oppositeSexDiceSize) == 0; - } + protected boolean randomDivorce(final Person person) { + double multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size() * 0.5); - @Override - protected boolean randomSameSexDivorce(final Person person) { - return Compute.randomInt(sameSexDiceSize) == 0; + return Compute.randomInt((int) (divorceDiceSize * multiplier)) == 0; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java index decb35c4c9..471bfabc8a 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -22,7 +22,7 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.procreation.AbstractProcreation; import mekhq.campaign.personnel.procreation.DisabledRandomProcreation; -import mekhq.campaign.personnel.procreation.randomProcreation; +import mekhq.campaign.personnel.procreation.RandomProcreation; import java.util.ResourceBundle; @@ -69,7 +69,7 @@ public boolean isDiceRoll() { public AbstractProcreation getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { - return new randomProcreation(options); + return new RandomProcreation(options); } else { return new DisabledRandomProcreation(options); } diff --git a/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java b/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java index 6ca7096f57..21dfae73ba 100644 --- a/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java +++ b/MekHQ/src/mekhq/campaign/personnel/familyTree/Genealogy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2020-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -40,6 +40,7 @@ public class Genealogy { //region Variables private final Person origin; private Person spouse; + private Person originSpouse; // the person who originated the marriage private final List formerSpouses = new ArrayList<>(); private final Map> family = new HashMap<>(); //endregion Variables @@ -58,6 +59,7 @@ public Genealogy(final Person origin) { /** * @return the origin person */ + @SuppressWarnings(value = "unused") public Person getOrigin() { return origin; } @@ -65,6 +67,7 @@ public Person getOrigin() { /** * @return the current person's spouse */ + @SuppressWarnings(value = "unused") public @Nullable Person getSpouse() { return spouse; } @@ -72,13 +75,31 @@ public Person getOrigin() { /** * @param spouse the new spouse for the current person */ + @SuppressWarnings(value = "unused") public void setSpouse(final @Nullable Person spouse) { this.spouse = spouse; } + /** + * @return the person who originated the marriage + */ + @SuppressWarnings(value = "unused") + public @Nullable Person getOriginSpouse() { + return originSpouse; + } + + /** + * @param originSpouse the person who originated the marriage + */ + @SuppressWarnings(value = "unused") + public void setOriginSpouse(final @Nullable Person originSpouse) { + this.originSpouse = originSpouse; + } + /** * @return a list of FormerSpouse objects for all the former spouses of the current person */ + @SuppressWarnings(value = "unused") public List getFormerSpouses() { return formerSpouses; } @@ -86,6 +107,7 @@ public List getFormerSpouses() { /** * @param formerSpouse a former spouse to add to the current person's list */ + @SuppressWarnings(value = "unused") public void addFormerSpouse(final FormerSpouse formerSpouse) { getFormerSpouses().add(formerSpouse); } @@ -95,6 +117,7 @@ public void addFormerSpouse(final FormerSpouse formerSpouse) { * note that this may remove multiple identical former spouses, as we do * not require uniqueness for former spouses. */ + @SuppressWarnings(value = "unused") public void removeFormerSpouse(final FormerSpouse formerSpouse) { getFormerSpouses().removeIf(ex -> ex.equals(formerSpouse)); } @@ -102,6 +125,7 @@ public void removeFormerSpouse(final FormerSpouse formerSpouse) { /** * @param formerSpouse the former spouse to remove from the current person's list */ + @SuppressWarnings(value = "unused") public void removeFormerSpouse(final Person formerSpouse) { getFormerSpouses().removeIf(ex -> ex.getFormerSpouse().equals(formerSpouse)); } @@ -109,6 +133,7 @@ public void removeFormerSpouse(final Person formerSpouse) { /** * @return the family map for this person */ + @SuppressWarnings(value = "unused") public Map> getFamily() { return family; } @@ -118,6 +143,7 @@ public Map> getFamily() { * @param relationshipType the relationship type between the two people * @param person the person to add */ + @SuppressWarnings(value = "unused") public void addFamilyMember(final FamilialRelationshipType relationshipType, final @Nullable Person person) { if (person != null) { @@ -130,6 +156,7 @@ public void addFamilyMember(final FamilialRelationshipType relationshipType, * @param relationshipType the FamilialRelationshipType of the person to remove * @param person the person to remove */ + @SuppressWarnings(value = "unused") public void removeFamilyMember(final @Nullable FamilialRelationshipType relationshipType, final Person person) { if (relationshipType == null) { diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 696680b365..32143a1d6f 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -213,7 +213,11 @@ public void marry(final Campaign campaign, final LocalDate today, final Person o spouse.performRandomizedLoyaltyChange(campaign, false, true); } - // And finally we trigger person changed events + // log the origin spouse for both partners + origin.getGenealogy().setOriginSpouse(spouse); + spouse.getGenealogy().setOriginSpouse(origin); + + // And finally, we trigger person changed events MekHQ.triggerEvent(new PersonChangedEvent(origin)); MekHQ.triggerEvent(new PersonChangedEvent(spouse)); } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index 34f9ae1555..b6a41bb3d0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java similarity index 92% rename from MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java rename to MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java index c21cac49d0..44f9ebf593 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/randomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - The MegaMek Team. All Rights Reserved. + * Copyright (C) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -23,14 +23,14 @@ import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomProcreationMethod; -public class randomProcreation extends AbstractProcreation { +public class RandomProcreation extends AbstractProcreation { //region Variable Declarations private int relationshipDieSize; private int relationshiplessDieSize; //endregion Variable Declarations //region Constructors - public randomProcreation(final CampaignOptions options) { + public RandomProcreation(final CampaignOptions options) { super(RandomProcreationMethod.DICE_ROLL, options); setRelationshipDieSize(options.getRandomProcreationRelationshipDiceSize()); setRelationshiplessDieSize(options.getRandomProcreationRelationshiplessDiceSize()); diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index eb4fc16ddb..74d46d2dbd 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -57,7 +57,7 @@ import mekhq.campaign.personnel.enums.*; import mekhq.campaign.personnel.marriage.RandomMarriage; import mekhq.campaign.personnel.procreation.AbstractProcreation; -import mekhq.campaign.personnel.procreation.randomProcreation; +import mekhq.campaign.personnel.procreation.RandomProcreation; import mekhq.campaign.personnel.ranks.RankSystem; import mekhq.campaign.personnel.ranks.Ranks; import mekhq.campaign.report.CargoReport; @@ -1485,9 +1485,7 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { getCampaign().getDivorce().setUseRandomClanPersonnelDivorce(newOptions.isUseRandomClanPersonnelDivorce()); getCampaign().getDivorce().setUseRandomPrisonerDivorce(newOptions.isUseRandomPrisonerDivorce()); if (getCampaign().getDivorce().getMethod().isDiceRoll()) { - ((RandomDivorce) getCampaign().getDivorce()).setOppositeSexDiceSize( - newOptions.getRandomDivorceDiceSize()); - ((RandomDivorce) getCampaign().getDivorce()).setSameSexDiceSize( + ((RandomDivorce) getCampaign().getDivorce()).setDivorceDiceSize( newOptions.getRandomDivorceDiceSize()); } } @@ -1497,7 +1495,6 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { } else { getCampaign().getMarriage().setUseClanPersonnelMarriages(newOptions.isUseClanPersonnelMarriages()); getCampaign().getMarriage().setUsePrisonerMarriages(newOptions.isUsePrisonerMarriages()); - getCampaign().getMarriage().setUseRandomSameSexMarriages(newOptions.isUseRandomSameSexMarriages()); getCampaign().getMarriage() .setUseRandomClanPersonnelMarriages(newOptions.isUseRandomClanPersonnelMarriages()); getCampaign().getMarriage().setUseRandomPrisonerMarriages(newOptions.isUseRandomPrisonerMarriages()); @@ -1520,9 +1517,9 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { .setUseRandomClanPersonnelProcreation(newOptions.isUseRandomClanPersonnelProcreation()); getCampaign().getProcreation().setUseRandomPrisonerProcreation(newOptions.isUseRandomPrisonerProcreation()); if (getCampaign().getProcreation().getMethod().isDiceRoll()) { - ((randomProcreation) getCampaign().getProcreation()).setRelationshipDieSize( + ((RandomProcreation) getCampaign().getProcreation()).setRelationshipDieSize( newOptions.getRandomProcreationRelationshipDiceSize()); - ((randomProcreation) getCampaign().getProcreation()).setRelationshiplessDieSize( + ((RandomProcreation) getCampaign().getProcreation()).setRelationshiplessDieSize( newOptions.getRandomProcreationRelationshiplessDiceSize()); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java index f527aaee11..1d7e815b03 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java @@ -48,12 +48,7 @@ public void beforeEach() { } @Test - public void testRandomOppositeSexDivorce() { - assertFalse(new DisabledRandomDivorce(mockOptions).randomOppositeSexDivorce(mockPerson)); - } - - @Test - public void testRandomSameSexDivorce() { - assertFalse(new DisabledRandomDivorce(mockOptions).randomSameSexDivorce(mockPerson)); + public void testRandomDivorce() { + assertFalse(new DisabledRandomDivorce(mockOptions).randomDivorce(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java index c80db69a90..d348e3f0c0 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java @@ -21,6 +21,7 @@ import megamek.common.Compute; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.Person; +import mekhq.campaign.personnel.familyTree.Genealogy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -29,6 +30,8 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.when; @@ -53,30 +56,22 @@ public void beforeEach() { } @Test - public void testRandomOppositeSexDivorce() { + public void testRandomDivorce() { final RandomDivorce randomDivorce = new RandomDivorce(mockOptions); - int diceSize = 5; + // Create a mock Genealogy + Genealogy mockGenealogy = Mockito.mock(Genealogy.class); - try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); - assertTrue(randomDivorce.randomOppositeSexDivorce(mockPerson)); - compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); - assertFalse(randomDivorce.randomOppositeSexDivorce(mockPerson)); - } - } - - @Test - public void testRandomSameSexDivorce() { - final RandomDivorce randomDivorce = new RandomDivorce(mockOptions); + when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); + when(mockGenealogy.getFormerSpouses()).thenReturn(new ArrayList<>()); int diceSize = 5; - try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { + try(MockedStatic compute = Mockito.mockStatic(Compute.class)) { compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); - assertTrue(randomDivorce.randomOppositeSexDivorce(mockPerson)); + assertTrue(randomDivorce.randomDivorce(mockPerson)); compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); - assertFalse(randomDivorce.randomOppositeSexDivorce(mockPerson)); + assertFalse(randomDivorce.randomDivorce(mockPerson)); } } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java index 55cc8f41a8..a3f93be194 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomProcreationMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -21,7 +21,7 @@ import mekhq.MekHQ; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.procreation.DisabledRandomProcreation; -import mekhq.campaign.personnel.procreation.randomProcreation; +import mekhq.campaign.personnel.procreation.RandomProcreation; import org.junit.jupiter.api.Test; import java.util.ResourceBundle; @@ -87,7 +87,7 @@ public void testGetMethod() { when(mockOptions.getRandomProcreationRelationshiplessDiceSize()).thenReturn(5); assertInstanceOf(DisabledRandomProcreation.class, RandomProcreationMethod.NONE.getMethod(mockOptions)); - assertInstanceOf(randomProcreation.class, RandomProcreationMethod.DICE_ROLL.getMethod(mockOptions)); + assertInstanceOf(RandomProcreation.class, RandomProcreationMethod.DICE_ROLL.getMethod(mockOptions)); } @Test diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java index e42b95e3e2..8e0a178fe3 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -59,7 +59,7 @@ public void beforeEach() { @Test public void testProcreation() { - final randomProcreation randomProcreation = new randomProcreation(mockOptions); + final RandomProcreation randomProcreation = new RandomProcreation(mockOptions); Genealogy mockGenealogy = mock(Genealogy.class); when(mockGenealogy.hasSpouse()).thenReturn(true); From 01b22d6bb1d51356c51afdc430918dd9a7a95990 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 12:13:06 -0500 Subject: [PATCH 13/41] Refactor marriage logic and simplify dice size settings Consolidated opposite and same-sex marriage logic into a single `randomMarriage` method and removed redundant configurations for different dice sizes. Updated tests and configuration files to reflect the new structure. This streamlines the marriage processing logic and reduces duplication. --- MekHQ/src/mekhq/campaign/CampaignOptions.java | 49 ++------ .../personnel/divorce/AbstractDivorce.java | 11 ++ .../personnel/divorce/RandomDivorce.java | 4 +- .../personnel/marriage/AbstractMarriage.java | 13 +- .../marriage/DisabledRandomMarriage.java | 9 +- .../personnel/marriage/RandomMarriage.java | 52 ++------ MekHQ/src/mekhq/gui/CampaignGUI.java | 6 +- .../mekhq/gui/panes/CampaignOptionsPane.java | 115 ++++-------------- .../divorce/PercentageRandomDivorceTest.java | 11 +- .../enums/RandomMarriageMethodTest.java | 6 +- .../marriage/AbstractMarriageTest.java | 34 +----- .../marriage/DisabledRandomMarriageTest.java | 12 +- .../PercentageRandomMarriageTest.java | 46 ++----- 13 files changed, 82 insertions(+), 286 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index ccd551d79e..73bc9a4a65 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -346,8 +346,7 @@ public static String getTransitUnitName(final int unit) { private boolean useRandomClanPersonnelMarriages; private boolean useRandomPrisonerMarriages; private int randomMarriageAgeRange; - private int randomMarriageOppositeSexDiceSize; - private int randomMarriageSameSexDiceSize; + private int randomMarriageDiceSize; // Divorce private boolean useManualDivorce; @@ -854,8 +853,7 @@ public CampaignOptions() { setUseRandomClanPersonnelMarriages(false); setUseRandomPrisonerMarriages(false); setRandomMarriageAgeRange(10); - setRandomMarriageOppositeSexDiceSize(6250); - setRandomMarriageSameSexDiceSize(76923); + setRandomMarriageDiceSize(6250); // Divorce setUseManualDivorce(true); @@ -2404,35 +2402,19 @@ public void setRandomMarriageAgeRange(final int randomMarriageAgeRange) { } /** - * @return the number of sides on the die used to determine random opposite sex marriage + * @return the number of sides on the die used to determine random marriage */ - public int getRandomMarriageOppositeSexDiceSize() { - return randomMarriageOppositeSexDiceSize; + public int getRandomMarriageDiceSize() { + return randomMarriageDiceSize; } /** - * Sets the size of the random opposite sex marriage die. + * Sets the size of the random marriage die. * - * @param randomMarriageOppositeSexDiceSize the size of the random opposite sex marriage die + * @param randomMarriageDiceSize the size of the random opposite sex marriage die */ - public void setRandomMarriageOppositeSexDiceSize(final int randomMarriageOppositeSexDiceSize) { - this.randomMarriageOppositeSexDiceSize = randomMarriageOppositeSexDiceSize; - } - - /** - * @return the number of sides on the die used to determine random same-sex marriage - */ - public int getRandomMarriageSameSexDiceSize() { - return randomMarriageSameSexDiceSize; - } - - /** - * Sets the size of the random same-sex marriage die. - * - * @param randomMarriageSameSexDiceSize the size of the random opposite sex marriage die - */ - public void setRandomMarriageSameSexDiceSize(final int randomMarriageSameSexDiceSize) { - this.randomMarriageSameSexDiceSize = randomMarriageSameSexDiceSize; + public void setRandomMarriageDiceSize(final int randomMarriageDiceSize) { + this.randomMarriageDiceSize = randomMarriageDiceSize; } //endregion Marriage @@ -4704,8 +4686,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomClanPersonnelMarriages", isUseRandomClanPersonnelMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPrisonerMarriages", isUseRandomPrisonerMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageAgeRange", getRandomMarriageAgeRange()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageOppositeSexDiceSize", getRandomMarriageOppositeSexDiceSize()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageSameSexChance", getRandomMarriageSameSexDiceSize()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageDiceSize", getRandomMarriageDiceSize()); //endregion Marriage //region Divorce @@ -5418,14 +5399,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUseRandomPrisonerMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageAgeRange")) { retVal.setRandomMarriageAgeRange(Integer.parseInt(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageOppositeSexChance")) { - retVal.setRandomMarriageOppositeSexDiceSize(Integer.parseInt(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageSameSexChance")) { - retVal.setRandomMarriageSameSexDiceSize(Integer.parseInt(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("useRandomSameSexMarriages")) { - if (!Boolean.parseBoolean(wn2.getTextContent().trim())) { - retVal.setRandomMarriageSameSexDiceSize(0); // legacy, pre-50.0 - } + } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageDiceSize")) { + retVal.setRandomMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); //endregion Marriage //region Divorce diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 7746484985..6827c7ed37 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -18,6 +18,7 @@ */ package mekhq.campaign.personnel.divorce; +import megamek.common.Compute; import megamek.common.annotations.Nullable; import mekhq.MekHQ; import mekhq.campaign.Campaign; @@ -246,6 +247,16 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person origin.getGenealogy().setOriginSpouse(null); spouse.getGenealogy().setOriginSpouse(null); + // roll for removal of marriageable flag + if (Compute.d6(1) <= 2) { + origin.setMarriageable(false); + } + + if (Compute.d6(1) <= 2) { + spouse.setMarriageable(false); + } + + // trigger person changed events MekHQ.triggerEvent(new PersonChangedEvent(spouse)); MekHQ.triggerEvent(new PersonChangedEvent(origin)); } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index 9041b7b1a8..e958fef456 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -49,8 +49,6 @@ public void setDivorceDiceSize(final int divorceDiceSize) { @Override protected boolean randomDivorce(final Person person) { - double multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size() * 0.5); - - return Compute.randomInt((int) (divorceDiceSize * multiplier)) == 0; + return Compute.randomInt(divorceDiceSize) == 0; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 32143a1d6f..6b8fce7521 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -234,10 +234,8 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final return; } - if (randomOppositeSexMarriage(person)) { + if (randomMarriage(person)) { marryRandomSpouse(campaign, today, person, false); - } else if (isUseRandomSameSexMarriages() && randomSameSexMarriage(person)) { - marryRandomSpouse(campaign, today, person, true); } } @@ -247,14 +245,7 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final * @param person the person to determine if they are getting randomly married * @return true if the person is to randomly marry */ - protected abstract boolean randomOppositeSexMarriage(final Person person); - - /** - * This determines if a person will randomly marry a same-sex spouse. - * @param person the person who may be randomly marrying a same-sex spouse - * @return true if the person is to randomly marry a same-sex spouse - */ - protected abstract boolean randomSameSexMarriage(final Person person); + protected abstract boolean randomMarriage(final Person person); /** * This finds a random spouse and marries them to the provided person. diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java index c2bacf8472..b52377f0b0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -30,12 +30,7 @@ public DisabledRandomMarriage(final CampaignOptions options) { //endregion Constructors @Override - protected boolean randomOppositeSexMarriage(final Person person) { - return false; - } - - @Override - protected boolean randomSameSexMarriage(final Person person) { + protected boolean randomMarriage(final Person person) { return false; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index b6a41bb3d0..f2fae457a5 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -25,67 +25,31 @@ public class RandomMarriage extends AbstractMarriage { //region Variable Declarations - private int oppositeSexDiceSize; - private int sameSexDiceSize; + private int marriageDiceSize; //endregion Variable Declarations //region Constructors public RandomMarriage(final CampaignOptions options) { super(RandomMarriageMethod.DICE_ROLL, options); - setOppositeSexDiceSize(options.getRandomMarriageOppositeSexDiceSize()); - - setSameSexDiceSize(options.getRandomMarriageSameSexDiceSize()); + setMarriageDiceSize(options.getRandomMarriageDiceSize()); } //endregion Constructors //region Getters/Setters @SuppressWarnings(value = "unused") - public int getOppositeSexDiceSize() { - return oppositeSexDiceSize; - } - - @SuppressWarnings(value = "unused") - public void setOppositeSexDiceSize(final int oppositeSexDiceSize) { - this.oppositeSexDiceSize = oppositeSexDiceSize; - } - - @SuppressWarnings(value = "unused") - public int getSameSexDiceSize() { - return sameSexDiceSize; + public int getMarriageDiceSize() { + return marriageDiceSize; } @SuppressWarnings(value = "unused") - public void setSameSexDiceSize(final int sameSexDiceSize) { - this.sameSexDiceSize = sameSexDiceSize; + public void setMarriageDiceSize(final int marriageDiceSize) { + this.marriageDiceSize = marriageDiceSize; } //endregion Getters/Setters @Override - protected boolean randomOppositeSexMarriage(final Person person) { - // this is used to simulate failed relationships. - // it's very arbitrary but serves its purpose for now. - // TODO: replace this with a proper relationship system - if (Compute.randomInt(100) != 0) { - return false; - } - - int multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size()); - - return Compute.randomInt(oppositeSexDiceSize * multiplier) == 0; - } - - @Override - protected boolean randomSameSexMarriage(final Person person) { - // this is used to simulate failed relationships. - // it's very arbitrary but serves its purpose for now. - // TODO: replace this with a proper relationship system - if (Compute.randomInt(100) != 0) { - return false; - } - - int multiplier = Math.max(1, person.getGenealogy().getFormerSpouses().size()); - - return Compute.randomInt(sameSexDiceSize * multiplier) == 0; + protected boolean randomMarriage(final Person person) { + return Compute.randomInt(marriageDiceSize) == 0; } } diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index 74d46d2dbd..e473e41785 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -1499,10 +1499,8 @@ private void menuOptionsActionPerformed(final ActionEvent evt) { .setUseRandomClanPersonnelMarriages(newOptions.isUseRandomClanPersonnelMarriages()); getCampaign().getMarriage().setUseRandomPrisonerMarriages(newOptions.isUseRandomPrisonerMarriages()); if (getCampaign().getMarriage().getMethod().isDiceRoll()) { - ((RandomMarriage) getCampaign().getMarriage()).setOppositeSexDiceSize( - newOptions.getRandomMarriageOppositeSexDiceSize()); - ((RandomMarriage) getCampaign().getMarriage()).setSameSexDiceSize( - newOptions.getRandomMarriageSameSexDiceSize()); + ((RandomMarriage) getCampaign().getMarriage()).setMarriageDiceSize( + newOptions.getRandomMarriageDiceSize()); } } diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index 3f3c6a57a9..da24cb4a3d 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -272,13 +272,11 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { // Settings private JPanel turnoverAndRetentionSettingsPanel = new JPanel(); - private JLabel lblTurnoverTargetNumberMethod; private MMComboBox comboTurnoverTargetNumberMethod; private JLabel lblTurnoverDifficulty; private MMComboBox comboTurnoverDifficulty; private JLabel lblTurnoverFixedTargetNumber; private JSpinner spnTurnoverFixedTargetNumber; - private JLabel lblTurnoverFrequency; private MMComboBox comboTurnoverFrequency; private JCheckBox chkUseContractCompletionRandomRetirement; private JCheckBox chkUseRandomFounderTurnover; @@ -286,9 +284,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkAeroRecruitsHaveUnits; private JCheckBox chkTrackOriginalUnit; private JCheckBox chkUseSubContractSoldiers; - private JLabel lblServiceContractDuration; private JSpinner spnServiceContractDuration; - private JLabel lblServiceContractModifier; private JSpinner spnServiceContractModifier; private JCheckBox chkPayBonusDefault; private JLabel lblPayBonusDefaultThreshold; @@ -312,11 +308,8 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { // Payout private JPanel turnoverAndRetentionPayoutPanel = new JPanel(); - private JLabel lblPayoutRateOfficer; private JSpinner spnPayoutRateOfficer; - private JLabel lblPayoutRateEnlisted; private JSpinner spnPayoutRateEnlisted; - private JLabel lblPayoutRetirementMultiplier; private JSpinner spnPayoutRetirementMultiplier; private JCheckBox chkUsePayoutServiceBonus; @@ -345,14 +338,10 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseFatigue; private JPanel fatigueSubPanel = new JPanel(); - private JLabel lblFatigueWarning; - private JLabel lblFatigueRate; private JSpinner spnFatigueRate; private JCheckBox chkUseInjuryFatigue; - private JLabel lblFieldKitchenCapacity; private JSpinner spnFieldKitchenCapacity; private JCheckBox chkFieldKitchenIgnoreNonCombatants; - private JLabel lblFatigueLeaveThreshold; private JSpinner spnFatigueLeaveThreshold; //endregion Turnover and Retention Tab @@ -371,13 +360,10 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkLogMarriageNameChanges; private Map spnMarriageSurnameWeights; private MMComboBox comboRandomMarriageMethod; - private JCheckBox chkUseRandomSameSexMarriages; private JCheckBox chkUseRandomClanPersonnelMarriages; private JCheckBox chkUseRandomPrisonerMarriages; private JSpinner spnRandomMarriageAgeRange; - private JSpinner spnRandomMarriageOppositeSexDiceSize; - private JLabel lblRandomMarriageSameSexDiceSize; - private JSpinner spnRandomMarriageSameSexDiceSize; + private JSpinner spnRandomMarriageDiceSize; // Divorce private JCheckBox chkUseManualDivorce; @@ -512,10 +498,8 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { // Taxes private JCheckBox chkUseTaxes; private JPanel taxesSubPanel = new JPanel(); - private JLabel lblTaxesPercentage; private JSpinner spnTaxesPercentage; - private JPanel sharesPanel; private JCheckBox chkUseShareSystem; private JPanel sharesSubPanel; private JCheckBox chkSharesForAll; @@ -635,7 +619,6 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseAtB; private JCheckBox chkUseStratCon; private MMComboBox comboSkillLevel; - private JLabel lblAtbCamOpsDivision; private JSpinner spnAtbCamOpsDivision; // unit administration @@ -647,9 +630,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { // contract operations private JCheckBox chkMercSizeLimited; private JCheckBox chkRestrictPartsByMission; - private JLabel lblBonusPartExchangeValue; private JSpinner spnBonusPartExchangeValue; - private JLabel lblBonusPartMaxExchangeCount; private JSpinner spnBonusPartMaxExchangeCount; private JCheckBox chkLimitLanceWeight; private JCheckBox chkLimitLanceNumUnits; @@ -2868,7 +2849,7 @@ private JScrollPane createAgainstTheBotTab() { gridBagConstraints.gridy++; panSubAtBAdmin.add(chkAutoconfigMunitions, gridBagConstraints); - lblAtbCamOpsDivision = new JLabel(resources.getString("lblAtbCamOpsDivision.text")); + JLabel lblAtbCamOpsDivision = new JLabel(resources.getString("lblAtbCamOpsDivision.text")); gridBagConstraints.gridx = 0; gridBagConstraints.gridy++; gridBagConstraints.gridwidth = 1; @@ -2893,7 +2874,7 @@ private JScrollPane createAgainstTheBotTab() { gridBagConstraints.gridwidth = 2; panSubAtBContract.add(chkRestrictPartsByMission, gridBagConstraints); - lblBonusPartExchangeValue = new JLabel(resources.getString("lblBonusPartExchangeValue.text")); + JLabel lblBonusPartExchangeValue = new JLabel(resources.getString("lblBonusPartExchangeValue.text")); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 4; gridBagConstraints.gridwidth = 1; @@ -2905,7 +2886,7 @@ private JScrollPane createAgainstTheBotTab() { gridBagConstraints.gridy = 4; panSubAtBContract.add(spnBonusPartExchangeValue, gridBagConstraints); - lblBonusPartMaxExchangeCount = new JLabel(resources.getString("lblBonusPartMaxExchangeCount.text")); + JLabel lblBonusPartMaxExchangeCount = new JLabel(resources.getString("lblBonusPartMaxExchangeCount.text")); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 5; gridBagConstraints.gridwidth = 1; @@ -3597,11 +3578,11 @@ private JPanel createLogPanel() { } private void createFatigueSubPanel() { - lblFatigueWarning = new JLabel(resources.getString("lblFatigueWarning.text")); + JLabel lblFatigueWarning = new JLabel(resources.getString("lblFatigueWarning.text")); lblFatigueWarning.setName("lblFatigueWarning"); lblFatigueWarning.setEnabled(campaign.getCampaignOptions().isUseFatigue()); - lblFatigueRate = new JLabel(resources.getString("lblFatigueRate.text")); + JLabel lblFatigueRate = new JLabel(resources.getString("lblFatigueRate.text")); lblFatigueRate.setToolTipText(resources.getString("lblFatigueRate.toolTipText")); lblFatigueRate.setName("lblFatigueRate"); lblFatigueRate.setEnabled(campaign.getCampaignOptions().isUseFatigue()); @@ -3616,7 +3597,7 @@ private void createFatigueSubPanel() { chkUseInjuryFatigue.setName("chkUseInjuryFatigue"); chkUseInjuryFatigue.setEnabled(campaign.getCampaignOptions().isUseFatigue()); - lblFieldKitchenCapacity = new JLabel(resources.getString("lblFieldKitchenCapacity.text")); + JLabel lblFieldKitchenCapacity = new JLabel(resources.getString("lblFieldKitchenCapacity.text")); lblFieldKitchenCapacity.setToolTipText(resources.getString("lblFieldKitchenCapacity.toolTipText")); lblFieldKitchenCapacity.setName("lblFieldKitchenCapacity"); lblFieldKitchenCapacity.setEnabled(campaign.getCampaignOptions().isUseFatigue()); @@ -3631,7 +3612,7 @@ private void createFatigueSubPanel() { chkFieldKitchenIgnoreNonCombatants.setName("chkFieldKitchenIgnoreNonCombatants"); chkFieldKitchenIgnoreNonCombatants.setEnabled(campaign.getCampaignOptions().isUseFatigue()); - lblFatigueLeaveThreshold = new JLabel(resources.getString("lblFatigueLeaveThreshold.text")); + JLabel lblFatigueLeaveThreshold = new JLabel(resources.getString("lblFatigueLeaveThreshold.text")); lblFatigueLeaveThreshold.setToolTipText(resources.getString("lblFatigueLeaveThreshold.toolTipText")); lblFatigueLeaveThreshold.setName("lblFatigueLeaveThreshold"); lblFatigueLeaveThreshold.setEnabled(campaign.getCampaignOptions().isUseFatigue()); @@ -4319,7 +4300,7 @@ private JPanel createTurnoverAndRetentionSettingsPanel() { boolean isUseTurnover = campaign.getCampaignOptions().isUseRandomRetirement(); boolean isUseFixedTargetNumber = campaign.getCampaignOptions().getTurnoverTargetNumberMethod().isFixed(); - lblTurnoverTargetNumberMethod = new JLabel(resources.getString("lblTurnoverTargetNumberMethod.text")); + JLabel lblTurnoverTargetNumberMethod = new JLabel(resources.getString("lblTurnoverTargetNumberMethod.text")); lblTurnoverTargetNumberMethod.setToolTipText(resources.getString("lblTurnoverTargetNumberMethod.toolTipText")); lblTurnoverTargetNumberMethod.setName("lblTurnoverTargetNumberMethod"); lblTurnoverTargetNumberMethod.setEnabled(isUseTurnover); @@ -4379,7 +4360,7 @@ public Component getListCellRendererComponent(final JList list, final Object lblTurnoverFixedTargetNumber.setName("lblTurnoverFixedTargetNumber"); lblTurnoverFixedTargetNumber.setEnabled(isUseTurnover); - lblTurnoverFrequency = new JLabel(resources.getString("lblTurnoverFrequency.text")); + JLabel lblTurnoverFrequency = new JLabel(resources.getString("lblTurnoverFrequency.text")); lblTurnoverFrequency.setToolTipText(resources.getString("lblTurnoverFrequency.toolTipText")); lblTurnoverFrequency.setName("lblTurnoverFrequency"); lblTurnoverFrequency.setEnabled(isUseTurnover); @@ -4430,7 +4411,7 @@ public Component getListCellRendererComponent(final JList list, final Object chkUseSubContractSoldiers.setName("chkUseSubContractSoldiers"); chkUseSubContractSoldiers.setEnabled(isUseTurnover); - lblServiceContractDuration = new JLabel(resources.getString("lblServiceContractDuration.text")); + JLabel lblServiceContractDuration = new JLabel(resources.getString("lblServiceContractDuration.text")); lblServiceContractDuration.setToolTipText(resources.getString("lblServiceContractDuration.toolTipText")); lblServiceContractDuration.setName("lblServiceContractDuration"); lblServiceContractDuration.setEnabled(isUseTurnover); @@ -4440,7 +4421,7 @@ public Component getListCellRendererComponent(final JList list, final Object spnServiceContractDuration.setName("spnServiceContractDuration"); spnServiceContractDuration.setEnabled(isUseTurnover); - lblServiceContractModifier = new JLabel(resources.getString("lblServiceContractModifier.text")); + JLabel lblServiceContractModifier = new JLabel(resources.getString("lblServiceContractModifier.text")); lblServiceContractModifier.setToolTipText(resources.getString("lblServiceContractModifier.toolTipText")); lblServiceContractModifier.setName("lblServiceContractModifier"); lblServiceContractModifier.setEnabled(isUseTurnover); @@ -4683,7 +4664,7 @@ private void createLoyaltySubPanel(boolean isUseTurnover) { private JPanel createTurnoverAndRetentionPayoutPanel() { boolean isUseTurnover = campaign.getCampaignOptions().isUseRandomRetirement(); - lblPayoutRateOfficer = new JLabel(resources.getString("lblPayoutRateOfficer.text")); + JLabel lblPayoutRateOfficer = new JLabel(resources.getString("lblPayoutRateOfficer.text")); lblPayoutRateOfficer.setToolTipText(resources.getString("lblPayoutRateOfficer.toolTipText")); lblPayoutRateOfficer.setName("lblPayoutRateOfficer"); lblPayoutRateOfficer.setEnabled(isUseTurnover); @@ -4693,7 +4674,7 @@ private JPanel createTurnoverAndRetentionPayoutPanel() { spnPayoutRateOfficer.setName("spnPayoutRateOfficer"); spnPayoutRateOfficer.setEnabled(isUseTurnover); - lblPayoutRateEnlisted = new JLabel(resources.getString("lblPayoutRateEnlisted.text")); + JLabel lblPayoutRateEnlisted = new JLabel(resources.getString("lblPayoutRateEnlisted.text")); lblPayoutRateEnlisted.setToolTipText(resources.getString("lblPayoutRateEnlisted.toolTipText")); lblPayoutRateEnlisted.setName("lblPayoutRateEnlisted"); lblPayoutRateEnlisted.setEnabled(isUseTurnover); @@ -4703,7 +4684,7 @@ private JPanel createTurnoverAndRetentionPayoutPanel() { spnPayoutRateEnlisted.setName("lblPayoutRateEnlisted"); spnPayoutRateEnlisted.setEnabled(isUseTurnover); - lblPayoutRetirementMultiplier = new JLabel(resources.getString("lblPayoutRetirementMultiplier.text")); + JLabel lblPayoutRetirementMultiplier = new JLabel(resources.getString("lblPayoutRetirementMultiplier.text")); lblPayoutRetirementMultiplier.setToolTipText(resources.getString("lblPayoutRetirementMultiplier.toolTipText")); lblPayoutRetirementMultiplier.setName("lblPayoutRetirementMultiplier"); lblPayoutRetirementMultiplier.setEnabled(isUseTurnover); @@ -5629,31 +5610,12 @@ public Component getListCellRendererComponent(final JList list, final Object return; } final boolean enabled = !method.isNone(); - final boolean sameSexEnabled = enabled && chkUseRandomSameSexMarriages.isSelected(); final boolean percentageEnabled = method.isDiceRoll(); - chkUseRandomSameSexMarriages.setEnabled(enabled); chkUseRandomClanPersonnelMarriages.setEnabled(enabled && chkUseClanPersonnelMarriages.isSelected()); chkUseRandomPrisonerMarriages.setEnabled(enabled && chkUsePrisonerMarriages.isSelected()); lblRandomMarriageAgeRange.setEnabled(enabled); spnRandomMarriageAgeRange.setEnabled(enabled); percentageRandomMarriagePanel.setEnabled(percentageEnabled); - lblRandomMarriageSameSexDiceSize.setEnabled(sameSexEnabled && percentageEnabled); - spnRandomMarriageSameSexDiceSize.setEnabled(sameSexEnabled && percentageEnabled); - }); - - chkUseRandomSameSexMarriages = new JCheckBox(resources.getString("chkUseRandomSameSexMarriages.text")); - chkUseRandomSameSexMarriages.setToolTipText(resources.getString("chkUseRandomSameSexMarriages.toolTipText")); - chkUseRandomSameSexMarriages.setName("chkUseRandomSameSexMarriages"); - chkUseRandomSameSexMarriages.addActionListener(evt -> { - final RandomMarriageMethod method = comboRandomMarriageMethod.getSelectedItem(); - if (method == null) { - return; - } - final boolean sameSexEnabled = chkUseRandomSameSexMarriages.isEnabled() - && chkUseRandomSameSexMarriages.isSelected(); - final boolean percentageEnabled = sameSexEnabled && method.isDiceRoll(); - lblRandomMarriageSameSexDiceSize.setEnabled(percentageEnabled); - spnRandomMarriageSameSexDiceSize.setEnabled(percentageEnabled); }); chkUseRandomClanPersonnelMarriages = new JCheckBox(resources.getString("chkUseRandomClanPersonnelMarriages.text")); @@ -5693,7 +5655,6 @@ public Component getListCellRendererComponent(final JList list, final Object .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(lblRandomMarriageMethod) .addComponent(comboRandomMarriageMethod, Alignment.LEADING)) - .addComponent(chkUseRandomSameSexMarriages) .addComponent(chkUseRandomClanPersonnelMarriages) .addComponent(chkUseRandomPrisonerMarriages) .addGroup(layout.createParallelGroup(Alignment.BASELINE) @@ -5707,7 +5668,6 @@ public Component getListCellRendererComponent(final JList list, final Object .addGroup(layout.createSequentialGroup() .addComponent(lblRandomMarriageMethod) .addComponent(comboRandomMarriageMethod)) - .addComponent(chkUseRandomSameSexMarriages) .addComponent(chkUseRandomClanPersonnelMarriages) .addComponent(chkUseRandomPrisonerMarriages) .addGroup(layout.createSequentialGroup() @@ -5725,21 +5685,12 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { lblRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"))); lblRandomMarriageOppositeSexDiceSize.setName("lblRandomMarriageOppositeSexDiceSize"); - spnRandomMarriageOppositeSexDiceSize = new JSpinner(new SpinnerNumberModel(542, 0, 100000, 1)); - spnRandomMarriageOppositeSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"))); - spnRandomMarriageOppositeSexDiceSize.setName("spnPercentageRandomMarriageOppositeSexChance"); - - lblRandomMarriageSameSexDiceSize = new JLabel(resources.getString("lblRandomMarriageSameSexDiceSize.text")); - lblRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"))); - lblRandomMarriageSameSexDiceSize.setName("lblRandomMarriageSameSexDiceSize"); - - spnRandomMarriageSameSexDiceSize = new JSpinner(new SpinnerNumberModel(3042, 0, 100000, 1)); - spnRandomMarriageSameSexDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageSameSexDiceSize.toolTipText"))); - spnRandomMarriageSameSexDiceSize.setName("spnRandomMarriageSameSexDiceSize"); + spnRandomMarriageDiceSize = new JSpinner(new SpinnerNumberModel(542, 0, 100000, 1)); + spnRandomMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"))); + spnRandomMarriageDiceSize.setName("spnPercentageRandomMarriageOppositeSexChance"); // Programmatically Assign Accessibility Labels - lblRandomMarriageOppositeSexDiceSize.setLabelFor(spnRandomMarriageOppositeSexDiceSize); - lblRandomMarriageSameSexDiceSize.setLabelFor(spnRandomMarriageSameSexDiceSize); + lblRandomMarriageOppositeSexDiceSize.setLabelFor(spnRandomMarriageDiceSize); // Layout the Panel panel.setBorder(BorderFactory.createTitledBorder(resources.getString("percentageRandomMarriagePanel.title"))); @@ -5754,20 +5705,14 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { layout.createSequentialGroup() .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(lblRandomMarriageOppositeSexDiceSize) - .addComponent(spnRandomMarriageOppositeSexDiceSize, Alignment.LEADING)) - .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblRandomMarriageSameSexDiceSize) - .addComponent(spnRandomMarriageSameSexDiceSize, Alignment.LEADING)) + .addComponent(spnRandomMarriageDiceSize, Alignment.LEADING)) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(lblRandomMarriageOppositeSexDiceSize) - .addComponent(spnRandomMarriageOppositeSexDiceSize)) - .addGroup(layout.createSequentialGroup() - .addComponent(lblRandomMarriageSameSexDiceSize) - .addComponent(spnRandomMarriageSameSexDiceSize)) + .addComponent(spnRandomMarriageDiceSize)) ); } @@ -7266,7 +7211,7 @@ private JPanel createTaxesPanel() { private JPanel createTaxesSubPanel() { boolean isEnabled = campaign.getCampaignOptions().isUseTaxes(); - lblTaxesPercentage = new JLabel(); + JLabel lblTaxesPercentage = new JLabel(); lblTaxesPercentage.setText(resources.getString("lblTaxesPercentage.text")); lblTaxesPercentage.setToolTipText(resources.getString("lblTaxesPercentage.toolTipText")); lblTaxesPercentage.setName("lblTaxesPercentage"); @@ -7309,7 +7254,7 @@ private JPanel createSharesPanel() { sharesSubPanel = createSharesSubPanel(); - sharesPanel = new JDisableablePanel("sharesPanel"); + JPanel sharesPanel = new JDisableablePanel("sharesPanel"); sharesPanel.setBorder(BorderFactory.createTitledBorder(resources.getString("sharesPanel.title"))); final GroupLayout layout = new GroupLayout(sharesPanel); @@ -8174,18 +8119,10 @@ public void setOptions(@Nullable CampaignOptions options, entry.getValue().setValue(options.getMarriageSurnameWeights().get(entry.getKey()) / 10.0); } comboRandomMarriageMethod.setSelectedItem(options.getRandomMarriageMethod()); - if (chkUseRandomSameSexMarriages.isSelected() != options.isUseRandomSameSexMarriages()) { - if (chkUseRandomSameSexMarriages.isEnabled()) { - chkUseRandomSameSexMarriages.doClick(); - } else { - chkUseRandomSameSexMarriages.setSelected(options.isUseRandomSameSexMarriages()); - } - } chkUseRandomClanPersonnelMarriages.setSelected(options.isUseRandomClanPersonnelMarriages()); chkUseRandomPrisonerMarriages.setSelected(options.isUseRandomPrisonerMarriages()); spnRandomMarriageAgeRange.setValue(options.getRandomMarriageAgeRange()); - spnRandomMarriageOppositeSexDiceSize.setValue(options.getRandomMarriageOppositeSexDiceSize()); - spnRandomMarriageSameSexDiceSize.setValue(options.getRandomMarriageSameSexDiceSize()); + spnRandomMarriageDiceSize.setValue(options.getRandomMarriageDiceSize()); // Divorce chkUseManualDivorce.setSelected(options.isUseManualDivorce()); @@ -8868,12 +8805,10 @@ public void updateOptions() { options.getMarriageSurnameWeights().put(entry.getKey(), (int) Math.round((Double) entry.getValue().getValue() * 10.0)); } options.setRandomMarriageMethod(comboRandomMarriageMethod.getSelectedItem()); - options.setUseRandomSameSexMarriages(chkUseRandomSameSexMarriages.isSelected()); options.setUseRandomClanPersonnelMarriages(chkUseRandomClanPersonnelMarriages.isSelected()); options.setUseRandomPrisonerMarriages(chkUseRandomPrisonerMarriages.isSelected()); options.setRandomMarriageAgeRange((Integer) spnRandomMarriageAgeRange.getValue()); - options.setRandomMarriageOppositeSexDiceSize((int) spnRandomMarriageOppositeSexDiceSize.getValue()); - options.setRandomMarriageSameSexDiceSize((int) spnRandomMarriageSameSexDiceSize.getValue()); + options.setRandomMarriageDiceSize((int) spnRandomMarriageDiceSize.getValue()); // Divorce options.setUseManualDivorce(chkUseManualDivorce.isSelected()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java index d348e3f0c0..2fc91b4e01 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -21,7 +21,6 @@ import megamek.common.Compute; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.Person; -import mekhq.campaign.personnel.familyTree.Genealogy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -30,8 +29,6 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.ArrayList; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.when; @@ -59,12 +56,6 @@ public void beforeEach() { public void testRandomDivorce() { final RandomDivorce randomDivorce = new RandomDivorce(mockOptions); - // Create a mock Genealogy - Genealogy mockGenealogy = Mockito.mock(Genealogy.class); - - when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); - when(mockGenealogy.getFormerSpouses()).thenReturn(new ArrayList<>()); - int diceSize = 5; try(MockedStatic compute = Mockito.mockStatic(Compute.class)) { diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java index 94ffad32f8..425bcdf869 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomMarriageMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -81,11 +81,9 @@ public void testGetMethod() { final CampaignOptions mockOptions = mock(CampaignOptions.class); when(mockOptions.isUseClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUsePrisonerMarriages()).thenReturn(false); - when(mockOptions.isUseRandomSameSexMarriages()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUseRandomPrisonerMarriages()).thenReturn(false); - when(mockOptions.getRandomMarriageOppositeSexDiceSize()).thenReturn(5); - when(mockOptions.getRandomMarriageSameSexDiceSize()).thenReturn(5); + when(mockOptions.getRandomMarriageDiceSize()).thenReturn(5); assertInstanceOf(DisabledRandomMarriage.class, RandomMarriageMethod.NONE.getMethod(mockOptions)); assertInstanceOf(RandomMarriage.class, RandomMarriageMethod.DICE_ROLL.getMethod(mockOptions)); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index 4e5b4976ed..7527840a04 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -63,7 +63,6 @@ public void beforeEach() { public void testGettersAndSetters() { when(mockCampaignOptions.isUseClanPersonnelMarriages()).thenReturn(false); when(mockCampaignOptions.isUsePrisonerMarriages()).thenReturn(false); - when(mockCampaignOptions.isUseRandomSameSexMarriages()).thenReturn(false); when(mockCampaignOptions.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockCampaignOptions.isUseRandomPrisonerMarriages()).thenReturn(false); @@ -258,7 +257,7 @@ public void testMarry() { verify(mockMergingSurnameStyle, times(1)).apply(any(), any(), any(), any()); } - //region New Day + //region New Week @Test public void testProcessNewWeek() { doCallRealMethod().when(mockMarriage).processNewWeek(any(), any(), any()); @@ -268,38 +267,17 @@ public void testProcessNewWeek() { when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn("Married"); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(0)).randomOppositeSexMarriage(any()); - verify(mockMarriage, times(0)).randomSameSexMarriage(any()); + verify(mockMarriage, times(0)).randomMarriage(any()); verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean()); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn(null); - when(mockMarriage.randomOppositeSexMarriage(any())).thenReturn(true); + when(mockMarriage.randomMarriage(any())).thenReturn(true); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(1)).randomOppositeSexMarriage(any()); - verify(mockMarriage, times(0)).randomSameSexMarriage(any()); + verify(mockMarriage, times(1)).randomMarriage(any()); verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); - - when(mockMarriage.randomOppositeSexMarriage(any())).thenReturn(false); - when(mockMarriage.isUseRandomSameSexMarriages()).thenReturn(false); - mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(2)).randomOppositeSexMarriage(any()); - verify(mockMarriage, times(0)).randomSameSexMarriage(any()); - verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); - - when(mockMarriage.isUseRandomSameSexMarriages()).thenReturn(true); - when(mockMarriage.randomSameSexMarriage(any())).thenReturn(false); - mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(3)).randomOppositeSexMarriage(any()); - verify(mockMarriage, times(1)).randomSameSexMarriage(any()); - verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); - - when(mockMarriage.randomSameSexMarriage(any())).thenReturn(true); - mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(4)).randomOppositeSexMarriage(any()); - verify(mockMarriage, times(2)).randomSameSexMarriage(any()); - verify(mockMarriage, times(2)).marryRandomSpouse(any(), any(), any(), anyBoolean()); } + //region Random Marriage @Test public void testMarryRandomSpouse() { diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java index e850434185..b3aec99acd 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -41,18 +41,12 @@ public class DisabledRandomMarriageTest { public void beforeEach() { when(mockOptions.isUseClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUsePrisonerMarriages()).thenReturn(false); - when(mockOptions.isUseRandomSameSexMarriages()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUseRandomPrisonerMarriages()).thenReturn(false); } @Test - public void testRandomOppositeSexMarriage() { - assertFalse(new DisabledRandomMarriage(mockOptions).randomOppositeSexMarriage(mockPerson)); - } - - @Test - public void testRandomSameSexMarriage() { - assertFalse(new DisabledRandomMarriage(mockOptions).randomSameSexMarriage(mockPerson)); + public void testRandomMarriage() { + assertFalse(new DisabledRandomMarriage(mockOptions).randomMarriage(mockPerson)); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java index e3e4a9b7cc..245b5b77b3 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * @@ -21,7 +21,6 @@ import megamek.common.Compute; import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.Person; -import mekhq.campaign.personnel.familyTree.Genealogy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -30,11 +29,8 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.Collections; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @ExtendWith(value = MockitoExtension.class) @@ -49,50 +45,22 @@ public class PercentageRandomMarriageTest { public void beforeEach() { when(mockOptions.isUseClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUsePrisonerMarriages()).thenReturn(false); - when(mockOptions.isUseRandomSameSexMarriages()).thenReturn(false); when(mockOptions.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockOptions.isUseRandomPrisonerMarriages()).thenReturn(false); - when(mockOptions.getRandomMarriageOppositeSexDiceSize()).thenReturn(5); - when(mockOptions.getRandomMarriageSameSexDiceSize()).thenReturn(5); - } - - @Test - public void testRandomOppositeSexMarriage() { - final RandomMarriage randomMarriage = new RandomMarriage(mockOptions); - Genealogy mockGenealogy = mock(Genealogy.class); - - when(mockGenealogy.getFormerSpouses()).thenReturn(Collections.emptyList()); - - when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); - - int diceSize = 5; - int multiplier = 1; - - try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(0); - assertTrue(randomMarriage.randomOppositeSexMarriage(mockPerson)); - compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(1); - assertFalse(randomMarriage.randomOppositeSexMarriage(mockPerson)); - } + when(mockOptions.getRandomMarriageDiceSize()).thenReturn(5); } @Test - public void testRandomSameSexMarriage() { + public void testRandomMarriage() { final RandomMarriage randomMarriage = new RandomMarriage(mockOptions); - Genealogy mockGenealogy = mock(Genealogy.class); - - when(mockGenealogy.getFormerSpouses()).thenReturn(Collections.emptyList()); - - when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); int diceSize = 5; - int multiplier = 1; try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(0); - assertTrue(randomMarriage.randomSameSexMarriage(mockPerson)); - compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(1); - assertFalse(randomMarriage.randomSameSexMarriage(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); + assertTrue(randomMarriage.randomMarriage(mockPerson)); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); + assertFalse(randomMarriage.randomMarriage(mockPerson)); } } } From 519004b70771c99b01d71bc7b22228263f1c8e98 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 12:25:49 -0500 Subject: [PATCH 14/41] Update procreation settings and simplify logic Simplified the logic for random procreation by removing the multiplier. Instead, we use check to change desire to conceive during the procreation process. --- MekHQ/resources/mekhq/resources/Personnel.properties | 3 ++- .../personnel/marriage/AbstractMarriage.java | 1 - .../personnel/procreation/AbstractProcreation.java | 5 +++++ .../personnel/procreation/RandomProcreation.java | 3 +-- .../personnel/procreation/RandomProcreationTest.java | 12 ++---------- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index b3bebd9c8b..cb70900ef3 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -1188,10 +1188,11 @@ cannotProcreate.NotTryingForABaby.text=She is not trying for a baby. cannotProcreate.AlreadyPregnant.text=She is already pregnant. cannotProcreate.Inactive.text=She is currently inactive. cannotProcreate.Deployed.text=She is actively deployed. -cannotProcreate.Child.text=She is a child. Those thirteen and under cannot procreate in MekHQ. +cannotProcreate.Child.text=She is a child. Those 18 and under cannot procreate in MekHQ. cannotProcreate.TooOld.text=She is too old to have child. Those fifty-one and over cannot procreate in MekHQ. cannotProcreate.ClanPersonnel.text=She is from a clan, and clan personnel procreation is disabled. cannotProcreate.Prisoner.text=She is a prisoner, and prisoner procreation is disabled. +cannotProcreate.OverAge.text=Due to her age, she is no longer considering having children cannotProcreate.NoSpouse.text=She does not have a spouse and relationshipless random procreation is disabled. cannotProcreate.RandomClanPersonnel.text=She is from a clan, and random clan personnel procreation is disabled. cannotProcreate.RandomPrisoner.text=She is a prisoner, and random prisoner procreation is disabled. diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 6b8fce7521..f30075b509 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -57,7 +57,6 @@ protected AbstractMarriage(final RandomMarriageMethod method, final CampaignOpti this.method = method; setUseClanPersonnelMarriages(options.isUseClanPersonnelMarriages()); setUsePrisonerMarriages(options.isUsePrisonerMarriages()); - setUseRandomSameSexMarriages(options.isUseRandomSameSexMarriages()); setUseRandomClanPersonnelMarriages(options.isUseRandomClanPersonnelMarriages()); setUseRandomPrisonerMarriages(options.isUseRandomPrisonerMarriages()); } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index d88b64d128..1e5691fc33 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -373,6 +373,11 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m mother.performRandomizedLoyaltyChange(campaign, false, true); + // check desire for children + if (Compute.d6(1) <= 2) { + mother.setTryingToConceive(false); + } + // Cleanup Data removePregnancy(mother); } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java index 44f9ebf593..6802339f75 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java @@ -62,8 +62,7 @@ public void setRelationshiplessDieSize(final int relationshiplessDieSize) { @Override protected boolean procreation(final Person person) { int diceSize = person.getGenealogy().hasSpouse() ? relationshipDieSize : relationshiplessDieSize; - int multiplier = Math.max(1, person.getGenealogy().getChildren().size()); - return Compute.randomInt(diceSize * multiplier) == 0; + return Compute.randomInt(diceSize) == 0; } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java index 8e0a178fe3..b54eb39a98 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/RandomProcreationTest.java @@ -30,9 +30,6 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.ArrayList; -import java.util.Collections; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; @@ -63,19 +60,14 @@ public void testProcreation() { Genealogy mockGenealogy = mock(Genealogy.class); when(mockGenealogy.hasSpouse()).thenReturn(true); - when(mockGenealogy.getChildren()).thenReturn(new ArrayList<>(Collections.singleton(mock(Person.class)))); - - // Make sure getGenealogy returns mocked Genealogy when(mockPerson.getGenealogy()).thenReturn(mockGenealogy); - // Assuming diceSize and multiplier are defined... int diceSize = 5; - int multiplier = 1; try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { - compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(0); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); assertTrue(randomProcreation.procreation(mockPerson)); - compute.when(() -> Compute.randomInt(diceSize * multiplier)).thenReturn(1); + compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); assertFalse(randomProcreation.procreation(mockPerson)); } } From e3400fb5e5a24281062547fae7d21e755dbb79b2 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 12:31:17 -0500 Subject: [PATCH 15/41] Remove same-sex marriage setting Removed the `useRandomSameSexMarriages` property and its corresponding getter and setter methods from `AbstractMarriage.java`. --- .../personnel/marriage/AbstractMarriage.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index f30075b509..d2112fbdcd 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -44,7 +44,6 @@ public abstract class AbstractMarriage { private final RandomMarriageMethod method; private boolean useClanPersonnelMarriages; private boolean usePrisonerMarriages; - private boolean useRandomSameSexMarriages; private boolean useRandomClanPersonnelMarriages; private boolean useRandomPrisonerMarriages; @@ -63,46 +62,47 @@ protected AbstractMarriage(final RandomMarriageMethod method, final CampaignOpti //endregion Constructors //region Getters/Setters + @SuppressWarnings(value = "unused") public RandomMarriageMethod getMethod() { return method; } + @SuppressWarnings(value = "unused") public boolean isUseClanPersonnelMarriages() { return useClanPersonnelMarriages; } + @SuppressWarnings(value = "unused") public void setUseClanPersonnelMarriages(final boolean useClanPersonnelMarriages) { this.useClanPersonnelMarriages = useClanPersonnelMarriages; } + @SuppressWarnings(value = "unused") public boolean isUsePrisonerMarriages() { return usePrisonerMarriages; } + @SuppressWarnings(value = "unused") public void setUsePrisonerMarriages(final boolean usePrisonerMarriages) { this.usePrisonerMarriages = usePrisonerMarriages; } - public boolean isUseRandomSameSexMarriages() { - return useRandomSameSexMarriages; - } - - public void setUseRandomSameSexMarriages(final boolean useRandomSameSexMarriages) { - this.useRandomSameSexMarriages = useRandomSameSexMarriages; - } - + @SuppressWarnings(value = "unused") public boolean isUseRandomClanPersonnelMarriages() { return useRandomClanPersonnelMarriages; } + @SuppressWarnings(value = "unused") public void setUseRandomClanPersonnelMarriages(final boolean useRandomClanPersonnelMarriages) { this.useRandomClanPersonnelMarriages = useRandomClanPersonnelMarriages; } + @SuppressWarnings(value = "unused") public boolean isUseRandomPrisonerMarriages() { return useRandomPrisonerMarriages; } + @SuppressWarnings(value = "unused") public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriages) { this.useRandomPrisonerMarriages = useRandomPrisonerMarriages; } @@ -251,7 +251,7 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final * @param campaign the campaign the person is a part of * @param today the current date * @param person the person who is getting randomly married - * @param sameSex whether the marriage is homosexual or heterosexual + * @param sameSex whether the marriage is between same-sex partners */ protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, final Person person, final boolean sameSex) { From fb650612a8cd8c9e04a7b33261b1140023b57aba Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 12:36:20 -0500 Subject: [PATCH 16/41] Remove redundant checks and strings Removed unnecessary checks for same-sex marriages and procreation due to age in unit tests and properties. --- MekHQ/resources/mekhq/resources/Personnel.properties | 1 - .../mekhq/campaign/personnel/marriage/AbstractMarriageTest.java | 1 - 2 files changed, 2 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index cb70900ef3..598d3b1934 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -1192,7 +1192,6 @@ cannotProcreate.Child.text=She is a child. Those 18 and under cannot procreate i cannotProcreate.TooOld.text=She is too old to have child. Those fifty-one and over cannot procreate in MekHQ. cannotProcreate.ClanPersonnel.text=She is from a clan, and clan personnel procreation is disabled. cannotProcreate.Prisoner.text=She is a prisoner, and prisoner procreation is disabled. -cannotProcreate.OverAge.text=Due to her age, she is no longer considering having children cannotProcreate.NoSpouse.text=She does not have a spouse and relationshipless random procreation is disabled. cannotProcreate.RandomClanPersonnel.text=She is from a clan, and random clan personnel procreation is disabled. cannotProcreate.RandomPrisoner.text=She is a prisoner, and random prisoner procreation is disabled. diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index 7527840a04..3b32b2d254 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -71,7 +71,6 @@ public void testGettersAndSetters() { assertEquals(RandomMarriageMethod.NONE, disabledMarriage.getMethod()); assertFalse(disabledMarriage.isUseClanPersonnelMarriages()); assertFalse(disabledMarriage.isUsePrisonerMarriages()); - assertFalse(disabledMarriage.isUseRandomSameSexMarriages()); assertFalse(disabledMarriage.isUseRandomClanPersonnelMarriages()); assertFalse(disabledMarriage.isUseRandomPrisonerMarriages()); } From 20947ec0f396575e82ba85925db38f80807d8e20 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 12:53:33 -0500 Subject: [PATCH 17/41] Add separate dice size for same-sex random marriages Implemented a new option to set the dice size for same-sex random marriages independently of opposite-sex marriages. Also adjusted the logic in related classes to handle the new dice size and updated UI components to reflect this change. --- .../CampaignOptionsDialog.properties | 12 ++++---- MekHQ/src/mekhq/campaign/CampaignOptions.java | 29 +++++++++++++++++-- .../personnel/divorce/RandomDivorce.java | 6 ++++ .../personnel/marriage/RandomMarriage.java | 6 ++++ .../procreation/RandomProcreation.java | 6 ++++ .../mekhq/gui/panes/CampaignOptionsPane.java | 17 +++++++++++ 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 10e63657f2..b4a8413302 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -463,8 +463,6 @@ marriageSurnameWeightsPanel.toolTipText=These are the weights used in dete randomMarriagePanel.title=Random Marriages lblRandomMarriageMethod.text=Random Marriage Method lblRandomMarriageMethod.toolTipText=This is the method used to determine if an eligible person randomly marries. -chkUseRandomSameSexMarriages.text=Use Same-sex Random Marriage -chkUseRandomSameSexMarriages.toolTipText=This enables random marriages between fitting same sex members of your force. chkUseRandomClanPersonnelMarriages.text=Use Random Clan Personnel Marriages chkUseRandomClanPersonnelMarriages.toolTipText=Allow clan-origin personnel to randomly marry other personnel. chkUseRandomPrisonerMarriages.text=Use Random Prisoner Marriages @@ -473,9 +471,9 @@ lblRandomMarriageAgeRange.text=Random Marriage Age Range lblRandomMarriageAgeRange.toolTipText=This plus/minus age forms the possible range of ages for spouses in the forming of a random marriage. percentageRandomMarriagePanel.title=Marriage Dice lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Dice Size -lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 25% chance of a character getting married every 3 years. Set to 0 to disable opposite sex marriages. -lblRandomMarriageSameSexDiceSize.text=Same Sex Dice Size -lblRandomMarriageSameSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. This die size is multiplied by 1 + the number of failed marriages the character has previously experienced. The default values provide a 5% chance of a character getting married every 3 years. The difference between opposite sex and same sex dice chances are based on 2022 US census data. Set to 0 to disable opposite sex marriages. +lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. +lblRandomSameSexMarriageDiceSize.text=Same Sex Dice Size +lblRandomSameSexMarriageDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a marriage is same-sex. Same-sex marriage occurs on a roll of 1. Set this value to 0 to disable same-sex marriages. The default value is based on real world data. For additional information, please see the documentation included in `MekHQ/docs/personnel modules`. # Divorce divorcePanel.title=Divorce (Unofficial) @@ -536,9 +534,9 @@ chkUseRandomPrisonerProcreation.text=Use Random Prisoner Procreation chkUseRandomPrisonerProcreation.toolTipText=Allow prisoners to randomly procreate. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. percentageRandomProcreationPanel.title=Procreation Dice lblRandomProcreationRelationshipDiceSize.text=Relationship Dice Size -lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. Set to 0 to disable procreation within a relationship. +lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Dice Size -lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. Each child after the first will multiply this dice size by the number of children. Set to 0 to disable procreation outside a relationship. +lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. # Death deathPanel.title=Death diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 73bc9a4a65..7fd16be17e 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -342,11 +342,12 @@ public static String getTransitUnitName(final int unit) { private boolean logMarriageNameChanges; private Map marriageSurnameWeights; private RandomMarriageMethod randomMarriageMethod; - private boolean useRandomSameSexMarriages; // legacy, pre-50.0 + private boolean useRandomSameSexMarriages; // legacy, pre-50.01 private boolean useRandomClanPersonnelMarriages; private boolean useRandomPrisonerMarriages; private int randomMarriageAgeRange; private int randomMarriageDiceSize; + private int randomSameSexMarriageDiceSize; // Divorce private boolean useManualDivorce; @@ -854,6 +855,7 @@ public CampaignOptions() { setUseRandomPrisonerMarriages(false); setRandomMarriageAgeRange(10); setRandomMarriageDiceSize(6250); + setRandomSameSexMarriageDiceSize(6250); // Divorce setUseManualDivorce(true); @@ -2411,11 +2413,27 @@ public int getRandomMarriageDiceSize() { /** * Sets the size of the random marriage die. * - * @param randomMarriageDiceSize the size of the random opposite sex marriage die + * @param randomMarriageDiceSize the size of the random marriage die */ public void setRandomMarriageDiceSize(final int randomMarriageDiceSize) { this.randomMarriageDiceSize = randomMarriageDiceSize; } + + /** + * @return the number of sides on the die used to determine random same-sex marriage + */ + public int getRandomSameSexMarriageDiceSize() { + return randomSameSexMarriageDiceSize; + } + + /** + * Sets the size of the random same-sex marriage die. + * + * @param randomSameSexMarriageDiceSize the size of the random same-sex marriage die + */ + public void setRandomSameSexMarriageDiceSize(final int randomSameSexMarriageDiceSize) { + this.randomSameSexMarriageDiceSize = randomSameSexMarriageDiceSize; + } //endregion Marriage //region Divorce @@ -4687,6 +4705,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPrisonerMarriages", isUseRandomPrisonerMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageAgeRange", getRandomMarriageAgeRange()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageDiceSize", getRandomMarriageDiceSize()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomSameSexMarriageDiceSize", getRandomSameSexMarriageDiceSize()); //endregion Marriage //region Divorce @@ -5401,6 +5420,12 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setRandomMarriageAgeRange(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("randomMarriageDiceSize")) { retVal.setRandomMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("randomSameSexMarriageDiceSize")) { + retVal.setRandomSameSexMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("useRandomSameSexMarriages")) { // Legacy, pre-50.01 + if (!Boolean.parseBoolean(wn2.getTextContent().trim())) { + retVal.setRandomSameSexMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + } //endregion Marriage //region Divorce diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index e958fef456..3558bcefbd 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -49,6 +49,12 @@ public void setDivorceDiceSize(final int divorceDiceSize) { @Override protected boolean randomDivorce(final Person person) { + if (divorceDiceSize == 0) { + return false; + } else if (divorceDiceSize == 1) { + return true; + } + return Compute.randomInt(divorceDiceSize) == 0; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index f2fae457a5..ef42e71316 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -50,6 +50,12 @@ public void setMarriageDiceSize(final int marriageDiceSize) { @Override protected boolean randomMarriage(final Person person) { + if (marriageDiceSize == 0) { + return false; + } else if (marriageDiceSize == 1) { + return true; + } + return Compute.randomInt(marriageDiceSize) == 0; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java index 6802339f75..1e78c3142f 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java @@ -63,6 +63,12 @@ public void setRelationshiplessDieSize(final int relationshiplessDieSize) { protected boolean procreation(final Person person) { int diceSize = person.getGenealogy().hasSpouse() ? relationshipDieSize : relationshiplessDieSize; + if (diceSize == 0) { + return false; + } else if (diceSize == 1) { + return true; + } + return Compute.randomInt(diceSize) == 0; } } diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index da24cb4a3d..4b0ab269f8 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -364,6 +364,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseRandomPrisonerMarriages; private JSpinner spnRandomMarriageAgeRange; private JSpinner spnRandomMarriageDiceSize; + private JSpinner spnRandomSameSexMarriageDiceSize; // Divorce private JCheckBox chkUseManualDivorce; @@ -5689,6 +5690,14 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { spnRandomMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomMarriageOppositeSexDiceSize.toolTipText"))); spnRandomMarriageDiceSize.setName("spnPercentageRandomMarriageOppositeSexChance"); + final JLabel lblRandomSameSexMarriageDiceSize = new JLabel(resources.getString("lblRandomSameSexMarriageDiceSize.text")); + lblRandomSameSexMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomSameSexMarriageDiceSize.toolTipText"))); + lblRandomSameSexMarriageDiceSize.setName("lblRandomSameSexMarriageDiceSize"); + + spnRandomSameSexMarriageDiceSize = new JSpinner(new SpinnerNumberModel(542, 0, 100000, 1)); + spnRandomSameSexMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomSameSexMarriageDiceSize.toolTipText"))); + spnRandomSameSexMarriageDiceSize.setName("spnRandomSameSexMarriageDiceSize"); + // Programmatically Assign Accessibility Labels lblRandomMarriageOppositeSexDiceSize.setLabelFor(spnRandomMarriageDiceSize); @@ -5706,6 +5715,9 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(lblRandomMarriageOppositeSexDiceSize) .addComponent(spnRandomMarriageDiceSize, Alignment.LEADING)) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(lblRandomSameSexMarriageDiceSize) + .addComponent(spnRandomSameSexMarriageDiceSize, Alignment.LEADING)) ); layout.setHorizontalGroup( @@ -5713,6 +5725,9 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { .addGroup(layout.createSequentialGroup() .addComponent(lblRandomMarriageOppositeSexDiceSize) .addComponent(spnRandomMarriageDiceSize)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblRandomSameSexMarriageDiceSize) + .addComponent(spnRandomSameSexMarriageDiceSize)) ); } @@ -8123,6 +8138,7 @@ public void setOptions(@Nullable CampaignOptions options, chkUseRandomPrisonerMarriages.setSelected(options.isUseRandomPrisonerMarriages()); spnRandomMarriageAgeRange.setValue(options.getRandomMarriageAgeRange()); spnRandomMarriageDiceSize.setValue(options.getRandomMarriageDiceSize()); + spnRandomSameSexMarriageDiceSize.setValue(options.getRandomSameSexMarriageDiceSize()); // Divorce chkUseManualDivorce.setSelected(options.isUseManualDivorce()); @@ -8809,6 +8825,7 @@ public void updateOptions() { options.setUseRandomPrisonerMarriages(chkUseRandomPrisonerMarriages.isSelected()); options.setRandomMarriageAgeRange((Integer) spnRandomMarriageAgeRange.getValue()); options.setRandomMarriageDiceSize((int) spnRandomMarriageDiceSize.getValue()); + options.setRandomSameSexMarriageDiceSize((int) spnRandomSameSexMarriageDiceSize.getValue()); // Divorce options.setUseManualDivorce(chkUseManualDivorce.isSelected()); From aface4376d16736f24247b311a9ac50bb11e45cf Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 13:54:49 -0500 Subject: [PATCH 18/41] Added support for inter-unit marriages Introduced functionality to determine whether a random marriage is within or outside the campaign unit. Added new configuration options and updated methods to handle inter-unit marriage scenarios. Modified the validation and recruitment processes to accommodate newly generated spouses outside the unit. --- .../CampaignOptionsDialog.properties | 18 ++-- MekHQ/src/mekhq/campaign/Campaign.java | 20 ++-- MekHQ/src/mekhq/campaign/CampaignOptions.java | 21 ++++ .../mekhq/campaign/mission/AtBContract.java | 5 +- .../personnel/marriage/AbstractMarriage.java | 97 ++++++++++++++++--- .../procreation/AbstractProcreation.java | 3 +- .../mekhq/gui/panes/CampaignOptionsPane.java | 17 ++++ .../marriage/AbstractMarriageTest.java | 19 ++-- 8 files changed, 160 insertions(+), 40 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index b4a8413302..4dd5c45629 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -470,10 +470,12 @@ chkUseRandomPrisonerMarriages.toolTipText=Allow prisoners to randomly marry othe lblRandomMarriageAgeRange.text=Random Marriage Age Range lblRandomMarriageAgeRange.toolTipText=This plus/minus age forms the possible range of ages for spouses in the forming of a random marriage. percentageRandomMarriagePanel.title=Marriage Dice -lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Dice Size +lblRandomMarriageOppositeSexDiceSize.text=Opposite Sex Die Size lblRandomMarriageOppositeSexDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a character gets married. Marriage occurs on a roll of 1. -lblRandomSameSexMarriageDiceSize.text=Same Sex Dice Size +lblRandomSameSexMarriageDiceSize.text=Same Sex Die Size lblRandomSameSexMarriageDiceSize.toolTipText=This determines the number of sides on the die rolled to determine whether a marriage is same-sex. Same-sex marriage occurs on a roll of 1. Set this value to 0 to disable same-sex marriages. The default value is based on real world data. For additional information, please see the documentation included in `MekHQ/docs/personnel modules`. +lblRandomNewDependentMarriage.text=Inter-Unit Marriage Die Size +lblRandomNewDependentMarriage.toolTipText=This determines the number of sides on the die rolled to determine whether a marriage is another character in the campaign unit. Inter-unit marriage occurs on a roll of 1. Set this value to 0 to disable inter-unit marriages. # Divorce divorcePanel.title=Divorce (Unofficial) @@ -497,8 +499,8 @@ chkUseRandomClanPersonnelDivorce.toolTipText=Allow clan-origin personnel to rand chkUseRandomPrisonerDivorce.text=Use Random Prisoner Divorce chkUseRandomPrisonerDivorce.toolTipText=Allow random divorce when one or both of the couple are currently prisoners. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. percentageRandomDivorcePanel.title=Divorce Dice -lblRandomDivorceDiceSize.text=Divorce Dice Size -lblRandomDivorceDiceSize.toolTipText=This is the number of sides featured on the weekly die rolled to see whether a marriage ends in divorce. Divorce occurs on a roll of 1. Set to 0 to disable random divorces for all personnel. +lblRandomDivorceDiceSize.text=Divorce Die Size +lblRandomDivorceDiceSize.toolTipText=This is the number of sides featured on the weekly dice rolled to see whether a marriage ends in divorce. Divorce occurs on a roll of 1. Set to 0 to disable random divorces for all personnel. # Procreation procreationPanel.title=Procreation (Unofficial) @@ -533,10 +535,10 @@ chkUseRandomClanPersonnelProcreation.toolTipText=Allow clan-origin personnel to chkUseRandomPrisonerProcreation.text=Use Random Prisoner Procreation chkUseRandomPrisonerProcreation.toolTipText=Allow prisoners to randomly procreate. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. percentageRandomProcreationPanel.title=Procreation Dice -lblRandomProcreationRelationshipDiceSize.text=Relationship Dice Size -lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. -lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Dice Size -lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the die rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. +lblRandomProcreationRelationshipDiceSize.text=Relationship Die Size +lblRandomProcreationRelationshipDiceSize.toolTipText=This is the number of sides on the dice rolled weekly to determine whether a woman in a relationship will fall pregnant. A roll of 1 results in a pregnancy. +lblRandomProcreationRelationshiplessDiceSize.text=Relationshipless Die Size +lblRandomProcreationRelationshiplessDiceSize.toolTipText=This is the number of sides on the dice rolled weekly to determine whether a woman not in a relationship will fall pregnant. A roll of 1 results in a pregnancy. # Death deathPanel.title=Death diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index e3388d555c..f7a52d305f 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -1353,18 +1353,24 @@ public Unit getUnit(UUID id) { //region Personnel //region Person Creation /** - * @return A new {@link Person}, who is a dependent. + * Creates a new {@link Person} instance who is a dependent. + * If {@code baby} is false and the random dependent origin option is enabled, + * the new person will have a random origin. + * + * @param baby a boolean indicating if the person is a baby or not + * @param gender the Gender enum for the person (should normally be Gender.RANDOMIZE) + * @return a new {@link Person} instance who is a dependent */ - public Person newDependent(boolean baby) { + public Person newDependent(boolean baby, Gender gender) { Person person; - if (!baby && getCampaignOptions().getRandomOriginOptions().isRandomizeDependentOrigin()) { - person = newPerson(PersonnelRole.DEPENDENT); - } else { + if ((!baby) && (getCampaignOptions().getRandomOriginOptions().isRandomizeDependentOrigin())) { person = newPerson(PersonnelRole.DEPENDENT, PersonnelRole.NONE, new DefaultFactionSelector(getCampaignOptions().getRandomOriginOptions()), new DefaultPlanetSelector(getCampaignOptions().getRandomOriginOptions()), - Gender.RANDOMIZE); + gender); + } else { + person = newPerson(PersonnelRole.DEPENDENT); } if (person.getAge(getLocalDate()) < 16) { @@ -3377,7 +3383,7 @@ && getCampaignOptions().getRandomDependentMethod().isAgainstTheBot() } else { if (getCampaignOptions().isUseRandomDependentAddition()) { for (int i = 0; i < change; i++) { - final Person person = newDependent(false); + final Person person = newDependent(false, Gender.RANDOMIZE); recruitPerson(person, PrisonerStatus.FREE, true, false); addReport(String.format(resources.getString("dependentJoinsForce.text"), person.getFullTitle())); diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 7fd16be17e..90b38f6f0b 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -348,6 +348,7 @@ public static String getTransitUnitName(final int unit) { private int randomMarriageAgeRange; private int randomMarriageDiceSize; private int randomSameSexMarriageDiceSize; + private int randomNewDependentMarriage; // Divorce private boolean useManualDivorce; @@ -856,6 +857,7 @@ public CampaignOptions() { setRandomMarriageAgeRange(10); setRandomMarriageDiceSize(6250); setRandomSameSexMarriageDiceSize(6250); + setRandomNewDependentMarriage(20); // Divorce setUseManualDivorce(true); @@ -2434,6 +2436,22 @@ public int getRandomSameSexMarriageDiceSize() { public void setRandomSameSexMarriageDiceSize(final int randomSameSexMarriageDiceSize) { this.randomSameSexMarriageDiceSize = randomSameSexMarriageDiceSize; } + + /** + * @return the number of sides on the die used to determine whether marriage occurs outside of current personnel + */ + public int getRandomNewDependentMarriage() { + return randomNewDependentMarriage; + } + + /** + * Sets the size of the die used to determine whether marriage occurs outside of current personnel + * + * @param randomNewDependentMarriage the size of the die used to determine whether marriage occurs outside of current personnel + */ + public void setRandomNewDependentMarriage(final int randomNewDependentMarriage) { + this.randomNewDependentMarriage = randomNewDependentMarriage; + } //endregion Marriage //region Divorce @@ -4706,6 +4724,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageAgeRange", getRandomMarriageAgeRange()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomMarriageDiceSize", getRandomMarriageDiceSize()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomSameSexMarriageDiceSize", getRandomSameSexMarriageDiceSize()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomNewDependentMarriage", getRandomNewDependentMarriage()); //endregion Marriage //region Divorce @@ -5426,6 +5445,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve if (!Boolean.parseBoolean(wn2.getTextContent().trim())) { retVal.setRandomSameSexMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); } + } else if (wn2.getNodeName().equalsIgnoreCase("randomNewDependentMarriage")) { + retVal.setRandomNewDependentMarriage(Integer.parseInt(wn2.getTextContent().trim())); //endregion Marriage //region Divorce diff --git a/MekHQ/src/mekhq/campaign/mission/AtBContract.java b/MekHQ/src/mekhq/campaign/mission/AtBContract.java index 83eac209ce..6c14c7d170 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBContract.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBContract.java @@ -24,6 +24,7 @@ import megamek.client.generator.RandomUnitGenerator; import megamek.client.ui.swing.util.PlayerColour; import megamek.common.*; +import megamek.common.enums.Gender; import megamek.common.enums.SkillLevel; import megamek.common.icons.Camouflage; import megamek.common.loaders.EntityLoadingException; @@ -485,7 +486,7 @@ public void doBonusRoll(Campaign c) { number = Compute.d6(); c.addReport("Bonus: " + number + " dependent" + ((number > 1) ? "s" : "")); for (int i = 0; i < number; i++) { - Person p = c.newDependent(false); + Person p = c.newDependent(false, Gender.RANDOMIZE); c.recruitPerson(p); } } @@ -974,7 +975,7 @@ public void setEmployerCode(String code, int year) { } public String getEmployerName(int year) { - return isMercSubcontract() ? "Mercenary (" + getEmployerFaction().getFullName(year) + ")" + return isMercSubcontract() ? "Mercenary (" + getEmployerFaction().getFullName(year) + ')' : getEmployerFaction().getFullName(year); } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index d2112fbdcd..fa930bb823 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -28,9 +28,11 @@ import mekhq.campaign.log.PersonalLogger; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.MergingSurnameStyle; +import mekhq.campaign.personnel.enums.PrisonerStatus; import mekhq.campaign.personnel.enums.RandomMarriageMethod; import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; import java.util.ResourceBundle; @@ -216,6 +218,11 @@ public void marry(final Campaign campaign, final LocalDate today, final Person o origin.getGenealogy().setOriginSpouse(spouse); spouse.getGenealogy().setOriginSpouse(origin); + // recruit the spouse if they're not already in the unit + if (spouse.getRecruitment() == null) { + campaign.recruitPerson(spouse, PrisonerStatus.FREE, true, true); + } + // And finally, we trigger person changed events MekHQ.triggerEvent(new PersonChangedEvent(origin)); MekHQ.triggerEvent(new PersonChangedEvent(spouse)); @@ -234,7 +241,27 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final } if (randomMarriage(person)) { - marryRandomSpouse(campaign, today, person, false); + boolean isSameSex = false; + + int sameSexDiceSize = campaign.getCampaignOptions().getRandomSameSexMarriageDiceSize(); + + if (sameSexDiceSize == 1) { + isSameSex = true; + } else if ((sameSexDiceSize != 0) && (Compute.randomInt(sameSexDiceSize) == 0)) { + isSameSex = true; + } + + boolean isInterUnit = false; + + int interUnitDiceSize = campaign.getCampaignOptions().getRandomNewDependentMarriage(); + + if (interUnitDiceSize == 1) { + isInterUnit = true; + } else if ((interUnitDiceSize != 0) && (Compute.randomInt(interUnitDiceSize) == 0)) { + isInterUnit = true; + } + + marryRandomSpouse(campaign, today, person, isSameSex, isInterUnit); } } @@ -248,21 +275,67 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final /** * This finds a random spouse and marries them to the provided person. + * + * @param campaign the campaign the person is a part of + * @param today the current date + * @param person the person who is getting randomly married + * @param sameSex whether the marriage is between same-sex partners + * @param isInterUnit whether the marriage is to another character chosen from among potential partners already in the campaign unit. + */ + protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, + final Person person, final boolean sameSex, boolean isInterUnit) { + final Gender gender = sameSex ? person.getGender() + : (person.getGender().isMale() ? Gender.FEMALE : Gender.MALE); + + List potentialSpouses = new ArrayList<>(); + Person spouse = null; + + if (isInterUnit) { + potentialSpouses = campaign.getActivePersonnel().stream() + .filter(potentialSpouse -> isPotentialRandomSpouse(campaign, today, person, potentialSpouse, gender)) + .toList(); + + if (!potentialSpouses.isEmpty()) { + spouse = potentialSpouses.get(Compute.randomInt(potentialSpouses.size())); + } + } + + if ((!isInterUnit) || (potentialSpouses.isEmpty())) { + spouse = createExternalSpouse(campaign, today, person, gender); + } + + marry(campaign, today, person, spouse, MergingSurnameStyle.WEIGHTED); + } + + /** + * Creates a spouse for the given person. + * * @param campaign the campaign the person is a part of * @param today the current date - * @param person the person who is getting randomly married - * @param sameSex whether the marriage is between same-sex partners + * @param person the person for whom the external spouse is being created + * @param gender the gender of the external spouse + * @return the created external spouse */ - protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, - final Person person, final boolean sameSex) { - final Gender gender = sameSex ? person.getGender() : (person.getGender().isMale() ? Gender.FEMALE : Gender.MALE); - final List potentials = campaign.getActivePersonnel().stream() - .filter(potentialSpouse -> isPotentialRandomSpouse(campaign, today, person, potentialSpouse, gender)) - .toList(); - if (!potentials.isEmpty()) { - marry(campaign, today, person, potentials.get(Compute.randomInt(potentials.size())), - MergingSurnameStyle.WEIGHTED); + Person createExternalSpouse(final Campaign campaign, final LocalDate today, final Person person, Gender gender) { + Person externalSpouse = campaign.newDependent(false, gender); + + // Adjust the birthday until it's within the correct age range + int ageDifference = person.getAge(today) - campaign.getCampaignOptions().getRandomMarriageAgeRange(); + + if (externalSpouse.getAge(today) < ageDifference) { + externalSpouse.setBirthday(today.plusYears(ageDifference - externalSpouse.getAge(today) + 1)); + } else { + while ((!externalSpouse.isChild(today)) && (externalSpouse.getAge(today) > ageDifference)) { + externalSpouse.setBirthday(today.minusYears(1)); + } + } + + // Make sure the spouse is not a child + while (externalSpouse.isChild(today)) { + externalSpouse.setBirthday(today.plusYears(1)); } + + return externalSpouse; } /** diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 1e5691fc33..2ab88459a3 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -21,6 +21,7 @@ import megamek.codeUtilities.MathUtility; import megamek.common.Compute; import megamek.common.annotations.Nullable; +import megamek.common.enums.Gender; import mekhq.MHQConstants; import mekhq.MekHQ; import mekhq.campaign.Campaign; @@ -321,7 +322,7 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m // Create Babies for (int i = 0; i < size; i++) { // Create a baby - final Person baby = campaign.newDependent(true); + final Person baby = campaign.newDependent(true, Gender.RANDOMIZE); baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle() .generateBabySurname(mother, father, baby.getGender())); baby.setBirthday(today); diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index 4b0ab269f8..eccf7c6226 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -365,6 +365,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JSpinner spnRandomMarriageAgeRange; private JSpinner spnRandomMarriageDiceSize; private JSpinner spnRandomSameSexMarriageDiceSize; + private JSpinner spnRandomNewDependentMarriage; // Divorce private JCheckBox chkUseManualDivorce; @@ -5698,6 +5699,14 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { spnRandomSameSexMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblRandomSameSexMarriageDiceSize.toolTipText"))); spnRandomSameSexMarriageDiceSize.setName("spnRandomSameSexMarriageDiceSize"); + final JLabel lblRandomNewDependentMarriage = new JLabel(resources.getString("lblRandomNewDependentMarriage.text")); + lblRandomNewDependentMarriage.setToolTipText(wordWrap(resources.getString("lblRandomNewDependentMarriage.toolTipText"))); + lblRandomNewDependentMarriage.setName("lblRandomNewDependentMarriage"); + + spnRandomNewDependentMarriage = new JSpinner(new SpinnerNumberModel(542, 0, 100000, 1)); + spnRandomNewDependentMarriage.setToolTipText(wordWrap(resources.getString("lblRandomNewDependentMarriage.toolTipText"))); + spnRandomNewDependentMarriage.setName("spnRandomNewDependentMarriage"); + // Programmatically Assign Accessibility Labels lblRandomMarriageOppositeSexDiceSize.setLabelFor(spnRandomMarriageDiceSize); @@ -5718,6 +5727,9 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(lblRandomSameSexMarriageDiceSize) .addComponent(spnRandomSameSexMarriageDiceSize, Alignment.LEADING)) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(lblRandomSameSexMarriageDiceSize) + .addComponent(spnRandomNewDependentMarriage, Alignment.LEADING)) ); layout.setHorizontalGroup( @@ -5728,6 +5740,9 @@ private void createPercentageRandomMarriagePanel(final JPanel panel) { .addGroup(layout.createSequentialGroup() .addComponent(lblRandomSameSexMarriageDiceSize) .addComponent(spnRandomSameSexMarriageDiceSize)) + .addGroup(layout.createSequentialGroup() + .addComponent(lblRandomSameSexMarriageDiceSize) + .addComponent(spnRandomNewDependentMarriage)) ); } @@ -8139,6 +8154,7 @@ public void setOptions(@Nullable CampaignOptions options, spnRandomMarriageAgeRange.setValue(options.getRandomMarriageAgeRange()); spnRandomMarriageDiceSize.setValue(options.getRandomMarriageDiceSize()); spnRandomSameSexMarriageDiceSize.setValue(options.getRandomSameSexMarriageDiceSize()); + spnRandomNewDependentMarriage.setValue(options.getRandomNewDependentMarriage()); // Divorce chkUseManualDivorce.setSelected(options.isUseManualDivorce()); @@ -8826,6 +8842,7 @@ public void updateOptions() { options.setRandomMarriageAgeRange((Integer) spnRandomMarriageAgeRange.getValue()); options.setRandomMarriageDiceSize((int) spnRandomMarriageDiceSize.getValue()); options.setRandomSameSexMarriageDiceSize((int) spnRandomSameSexMarriageDiceSize.getValue()); + options.setRandomNewDependentMarriage((int) spnRandomNewDependentMarriage.getValue()); // Divorce options.setUseManualDivorce(chkUseManualDivorce.isSelected()); diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index 3b32b2d254..ecc07bb652 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -260,27 +260,27 @@ public void testMarry() { @Test public void testProcessNewWeek() { doCallRealMethod().when(mockMarriage).processNewWeek(any(), any(), any()); - doNothing().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean()); + doNothing().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean()); final Person mockPerson = mock(Person.class); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn("Married"); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(0)).randomMarriage(any()); - verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean()); + verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(true)); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn(null); when(mockMarriage.randomMarriage(any())).thenReturn(true); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(1)).randomMarriage(any()); - verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean()); + verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(false)); } //region Random Marriage @Test public void testMarryRandomSpouse() { - doCallRealMethod().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean()); + doCallRealMethod().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(true)); final Person mockMale = mock(Person.class); when(mockMale.getGender()).thenReturn(Gender.MALE); @@ -298,8 +298,7 @@ public void testMarryRandomSpouse() { // No Potential Spouses when(mockMarriage.isPotentialRandomSpouse(any(), any(), any(), any(), any())).thenReturn(false); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true); - verify(mockMarriage, times(0)).marry(any(), any(), any(), any(), any()); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true); // Replace AbstractMarriage::isPotentialRandomSpouse with this simple gender comparison doAnswer(invocation -> invocation.getArgument(3, Person.class).getGender() == invocation.getArgument(4)) @@ -311,7 +310,7 @@ public void testMarryRandomSpouse() { assertEquals(spouse, mockFemale); return null; }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true); // Opposite sex, Female: Expect marry to be called with mockMale as the spouse doAnswer(invocation -> { @@ -319,7 +318,7 @@ public void testMarryRandomSpouse() { assertEquals(spouse, mockMale); return null; }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false, true); // Same-sex, Male: Expect marry to be called with mockMale as the spouse when(mockPerson.getGender()).thenReturn(Gender.MALE); @@ -328,7 +327,7 @@ public void testMarryRandomSpouse() { assertEquals(spouse, mockMale); return null; }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true); // Opposite sex, Male: Expect marry to be called with mockFemale as the spouse doAnswer(invocation -> { @@ -336,7 +335,7 @@ public void testMarryRandomSpouse() { assertEquals(spouse, mockFemale); return null; }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false, true); } @Test From b225f3a8bd06a70eeb86b16f0846404e1c9aa8cd Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 14:04:35 -0500 Subject: [PATCH 19/41] Fix age adjustment logic for external spouse creation Corrected the age calculation to ensure external spouses fall within the appropriate age range relative to the person. --- .../campaign/personnel/marriage/AbstractMarriage.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index fa930bb823..5fd9447701 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -320,12 +320,13 @@ Person createExternalSpouse(final Campaign campaign, final LocalDate today, fina Person externalSpouse = campaign.newDependent(false, gender); // Adjust the birthday until it's within the correct age range - int ageDifference = person.getAge(today) - campaign.getCampaignOptions().getRandomMarriageAgeRange(); + int personAge = person.getAge(today); + int ageDifference = campaign.getCampaignOptions().getRandomMarriageAgeRange(); - if (externalSpouse.getAge(today) < ageDifference) { - externalSpouse.setBirthday(today.plusYears(ageDifference - externalSpouse.getAge(today) + 1)); + if (externalSpouse.getAge(today) < (personAge - ageDifference)) { + externalSpouse.setBirthday(today.plusYears(1)); } else { - while ((!externalSpouse.isChild(today)) && (externalSpouse.getAge(today) > ageDifference)) { + while ((!externalSpouse.isChild(today)) && (externalSpouse.getAge(today) < (personAge - ageDifference))) { externalSpouse.setBirthday(today.minusYears(1)); } } From 4378d59fefc277cef3eb3bd1c0efd85f6948354b Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 30 Jul 2024 19:59:09 -0500 Subject: [PATCH 20/41] Add logging and joinedCampaign attribute to Person Added the logger using MMLogger in Person and CampaignXmlParser classes, replacing LogManager. Introduced a new attribute `joinedCampaign` in Person class, along with getter and setter methods. Updated associated methods and serialization to handle this new attribute. Adjusted default values in CampaignOptions to address marriage and procreation dice sizes. --- MekHQ/src/mekhq/campaign/Campaign.java | 139 ++++++++-------- MekHQ/src/mekhq/campaign/CampaignOptions.java | 24 +-- .../mekhq/campaign/io/CampaignXmlParser.java | 149 ++++++++++-------- .../src/mekhq/campaign/personnel/Person.java | 44 ++++-- .../personnel/divorce/AbstractDivorce.java | 39 +++++ .../personnel/marriage/AbstractMarriage.java | 10 +- 6 files changed, 244 insertions(+), 161 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index f7a52d305f..df258c056c 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -43,6 +43,7 @@ import megamek.common.weapons.flamers.FlamerWeapon; import megamek.common.weapons.gaussrifles.GaussWeapon; import megamek.common.weapons.lasers.EnergyWeapon; +import megamek.logging.MMLogger; import mekhq.MHQConstants; import mekhq.MekHQ; import mekhq.Utilities; @@ -126,7 +127,6 @@ import mekhq.service.IAutosaveService; import mekhq.service.mrms.MRMSService; import mekhq.utilities.MHQXMLUtility; -import org.apache.logging.log4j.LogManager; import javax.swing.*; import java.io.PrintWriter; @@ -149,6 +149,8 @@ public class Campaign implements ITechManager { public static final String REPORT_LINEBREAK = "

"; + private static final MMLogger logger = MMLogger.create(Person.class); + private UUID id; // we have three things to track: (1) teams, (2) units, (3) repair tasks @@ -156,14 +158,14 @@ public class Campaign implements ITechManager { // all three // OK now we have more, parts, personnel, forces, missions, and scenarios. // and more still - we're tracking DropShips and WarShips in a separate set so that we can assign units to transports - private Hangar units = new Hangar(); - private Set transportShips = new HashSet<>(); - private Map personnel = new LinkedHashMap<>(); + private final Hangar units = new Hangar(); + private final Set transportShips = new HashSet<>(); + private final Map personnel = new LinkedHashMap<>(); private Warehouse parts = new Warehouse(); - private TreeMap forceIds = new TreeMap<>(); - private TreeMap missions = new TreeMap<>(); - private TreeMap scenarios = new TreeMap<>(); - private Map> kills = new HashMap<>(); + private final TreeMap forceIds = new TreeMap<>(); + private final TreeMap missions = new TreeMap<>(); + private final TreeMap scenarios = new TreeMap<>(); + private final Map> kills = new HashMap<>(); private transient final UnitNameTracker unitNameTracker = new UnitNameTracker(); @@ -179,8 +181,8 @@ public class Campaign implements ITechManager { // I need to put a basic game object in campaign so that I can // assign it to the entities, otherwise some entity methods may get NPE // if they try to call up game options - private Game game; - private Player player; + private final Game game; + private final Player player; private GameOptions gameOptions; @@ -190,14 +192,14 @@ public class Campaign implements ITechManager { // hierarchically structured Force object to define TO&E private Force forces; - private Hashtable lances; // AtB + private final Hashtable lances; // AtB private Faction faction; private int techFactionCode; private String retainerEmployerCode; // AtB private RankSystem rankSystem; - private ArrayList currentReport; + private final ArrayList currentReport; private transient String currentReportHTML; private transient List newReports; @@ -219,11 +221,11 @@ public class Campaign implements ITechManager { private CurrentLocation location; - private News news; + private final News news; - private PartsStore partsStore; + private final PartsStore partsStore; - private List customs; + private final List customs; private CampaignOptions campaignOptions; private RandomSkillPreferences rskillPrefs = new RandomSkillPreferences(); @@ -251,7 +253,7 @@ public class Campaign implements ITechManager { private LocalDate shipSearchExpiration; //AtB private IUnitGenerator unitGenerator; private IUnitRating unitRating; - private CampaignSummary campaignSummary; + private final CampaignSummary campaignSummary; private final Quartermaster quartermaster; private StoryArc storyArc; @@ -527,7 +529,7 @@ public void initUnitGenerator() { try { Thread.sleep(50); } catch (InterruptedException e) { - LogManager.getLogger().error("", e); + logger.error("", e); } } rm.setSelectedRATs(campaignOptions.getRATs()); @@ -669,7 +671,7 @@ private void processShipSearch() { public void purchaseShipSearchResult() { MechSummary ms = MechSummaryCache.getInstance().getMech(getShipSearchResult()); if (ms == null) { - LogManager.getLogger().error("Cannot find entry for {}", getShipSearchResult()); + logger.error("Cannot find entry for {}", getShipSearchResult()); return; } @@ -685,7 +687,7 @@ public void purchaseShipSearchResult() { try { mechFileParser = new MechFileParser(ms.getSourceFile(), ms.getEntryName()); } catch (Exception ex) { - LogManager.getLogger().error("Unable to load unit: {}", ms.getEntryName(), ex); + logger.error("Unable to load unit: {}", ms.getEntryName(), ex); return; } @@ -1150,7 +1152,7 @@ public CurrentLocation getLocation() { public void importUnit(Unit u) { Objects.requireNonNull(u); - LogManager.getLogger().debug("Importing unit: (" + u.getId() + "): " + u.getName()); + logger.debug("Importing unit: ({}): {}", u.getId(), u.getName()); getHangar().addUnit(u); @@ -1175,7 +1177,7 @@ public void importUnit(Unit u) { * @param unit - The ship we want to add to this Set */ public void addTransportShip(Unit unit) { - LogManager.getLogger().debug("Adding DropShip/WarShip: " + unit.getId()); + logger.debug("Adding DropShip/WarShip: {}", unit.getId()); transportShips.add(Objects.requireNonNull(unit)); } @@ -1494,7 +1496,7 @@ public void setFieldKitchenWithinCapacity(final Boolean fieldKitchenWithinCapaci //region Personnel Recruitment /** * @param p the person being added - * @return true if the person is hired successfully, otherwise false + * @return true, if the person is hired successfully, otherwise false */ public boolean recruitPerson(Person p) { return recruitPerson(p, p.getPrisonerStatus(), false, true); @@ -1532,6 +1534,7 @@ public boolean recruitPerson(Person p, PrisonerStatus prisonerStatus, boolean gm if (p == null) { return false; } + // Only pay if option set, they weren't GM added, and they aren't a dependent, prisoner or bondsman if (getCampaignOptions().isPayForRecruitment() && !p.getPrimaryRole().isDependent() && !gmAdd && prisonerStatus.isFree()) { @@ -1544,6 +1547,7 @@ public boolean recruitPerson(Person p, PrisonerStatus prisonerStatus, boolean gm } personnel.put(p.getId(), p); + p.setJoinedCampaign(getLocalDate()); if (log) { String add = !prisonerStatus.isFree() ? (prisonerStatus.isBondsman() ? " as a bondsman" : " as a prisoner") : ""; @@ -2785,7 +2789,7 @@ public void workOnMothballingOrActivation(Unit u) { */ public void mothball(Unit u) { if (u.isMothballed()) { - LogManager.getLogger().warn("Unit is already mothballed, cannot mothball."); + logger.warn("Unit is already mothballed, cannot mothball."); return; } @@ -2832,7 +2836,7 @@ public void mothball(Unit u) { */ public void activate(Unit u) { if (!u.isMothballed()) { - LogManager.getLogger().warn("Unit is already activated, cannot activate."); + logger.warn("Unit is already activated, cannot activate."); return; } @@ -3385,8 +3389,9 @@ && getCampaignOptions().getRandomDependentMethod().isAgainstTheBot() for (int i = 0; i < change; i++) { final Person person = newDependent(false, Gender.RANDOMIZE); recruitPerson(person, PrisonerStatus.FREE, true, false); + addReport(String.format(resources.getString("dependentJoinsForce.text"), - person.getFullTitle())); + person.getHyperlinkedFullTitle())); } } } @@ -3412,26 +3417,26 @@ && getCampaignOptions().getRandomDependentMethod().isAgainstTheBot() 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 - for (Person p : getActivePersonnel()) { + for (Person person : getActivePersonnel()) { // Death - if (getDeath().processNewDay(this, getLocalDate(), p)) { + if (getDeath().processNewDay(this, getLocalDate(), person)) { // The person has died, so don't continue to process the dead continue; } - p.resetMinutesLeft(); + person.resetMinutesLeft(); // Reset acquisitions made to 0 - p.setAcquisition(0); - if (p.needsFixing() && !getCampaignOptions().isUseAdvancedMedical()) { - p.decrementDaysToWaitForHealing(); - Person doctor = getPerson(p.getDoctorId()); + person.setAcquisition(0); + if (person.needsFixing() && !getCampaignOptions().isUseAdvancedMedical()) { + person.decrementDaysToWaitForHealing(); + Person doctor = getPerson(person.getDoctorId()); if ((doctor != null) && doctor.isDoctor()) { - if (p.getDaysToWaitForHealing() <= 0) { - addReport(healPerson(p, doctor)); + if (person.getDaysToWaitForHealing() <= 0) { + addReport(healPerson(person, doctor)); } - } else if (p.checkNaturalHealing(15)) { - addReport(p.getHyperlinkedFullTitle() + " heals naturally!"); - Unit u = p.getUnit(); + } else if (person.checkNaturalHealing(15)) { + addReport(person.getHyperlinkedFullTitle() + " heals naturally!"); + Unit u = person.getUnit(); if (u != null) { u.resetPilotAndEntity(); } @@ -3439,53 +3444,53 @@ public void processNewDayPersonnel() { } // TODO Advanced Medical needs to go away from here later on if (getCampaignOptions().isUseAdvancedMedical()) { - InjuryUtil.resolveDailyHealing(this, p); - Unit u = p.getUnit(); + InjuryUtil.resolveDailyHealing(this, person); + Unit u = person.getUnit(); if (u != null) { u.resetPilotAndEntity(); } } // TODO : Reset this based on hasSupportRole(false) instead of checking for each type - // TODO : p.isEngineer will need to stay, however + // TODO : person.isEngineer will need to stay, however // Reset edge points to the purchased value each week. This should only // apply for support personnel - combat troops reset with each new mm game - if ((p.isAdministrator() || p.isDoctor() || p.isEngineer() || p.isTech()) + if ((person.isAdministrator() || person.isDoctor() || person.isEngineer() || person.isTech()) && (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY)) { - p.resetCurrentEdge(); + person.resetCurrentEdge(); } if ((getCampaignOptions().getIdleXP() > 0) && (getLocalDate().getDayOfMonth() == 1) - && !p.getPrisonerStatus().isCurrentPrisoner()) { // Prisoners can't gain XP, while Bondsmen can gain xp - p.setIdleMonths(p.getIdleMonths() + 1); - if (p.getIdleMonths() >= getCampaignOptions().getMonthsIdleXP()) { + && !person.getPrisonerStatus().isCurrentPrisoner()) { // Prisoners can't gain XP, while Bondsmen can gain xp + person.setIdleMonths(person.getIdleMonths() + 1); + if (person.getIdleMonths() >= getCampaignOptions().getMonthsIdleXP()) { if (Compute.d6(2) >= getCampaignOptions().getTargetIdleXP()) { - p.awardXP(this, getCampaignOptions().getIdleXP()); - addReport(p.getHyperlinkedFullTitle() + " has gained " + person.awardXP(this, getCampaignOptions().getIdleXP()); + addReport(person.getHyperlinkedFullTitle() + " has gained " + getCampaignOptions().getIdleXP() + " XP"); } - p.setIdleMonths(0); + person.setIdleMonths(0); } } // Divorce, Marriage, & Procreation if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { - getDivorce().processNewWeek(this, getLocalDate(), p); - getMarriage().processNewWeek(this, getLocalDate(), p); - getProcreation().processNewWeek(this, getLocalDate(), p); + getDivorce().processNewWeek(this, getLocalDate(), person); + getMarriage().processNewWeek(this, getLocalDate(), person); + getProcreation().processNewWeek(this, getLocalDate(), person); } // Anniversaries - if ((p.getRank().isOfficer()) || (!getCampaignOptions().isAnnounceOfficersOnly())) { - if ((p.getBirthday().isEqual(getLocalDate())) && (campaignOptions.isAnnounceBirthdays())) { + if ((person.getRank().isOfficer()) || (!getCampaignOptions().isAnnounceOfficersOnly())) { + if ((person.getBirthday().isEqual(getLocalDate())) && (campaignOptions.isAnnounceBirthdays())) { addReport(String.format(resources.getString("anniversaryBirthday.text"), - p.getHyperlinkedFullTitle(), - p.getAge(getLocalDate()))); + person.getHyperlinkedFullTitle(), + person.getAge(getLocalDate()))); } - } else if ((p.getAge(getLocalDate()) == 18) && (campaignOptions.isAnnounceChildBirthdays()) ){ - if (p.getBirthday().isEqual(getLocalDate())) { + } else if ((person.getAge(getLocalDate()) == 18) && (campaignOptions.isAnnounceChildBirthdays()) ){ + if (person.getBirthday().isEqual(getLocalDate())) { addReport(String.format(resources.getString("anniversaryBirthday.text"), - p.getHyperlinkedFullTitle(), + person.getHyperlinkedFullTitle(), 18)); } } @@ -3507,7 +3512,7 @@ public void processNewDayUnits() { doMaintenance(u); } catch (Exception e) { - LogManager.getLogger().error(String.format( + logger.error(String.format( "Unable to perform maintenance on %s (%s) due to an error", u.getName(), u.getId().toString()), e); addReport(String.format("ERROR: An error occurred performing maintenance on %s, check the log", @@ -3559,7 +3564,7 @@ public void processNewDayUnits() { try { fixPart(part, tech); } catch (Exception e) { - LogManager.getLogger().error(String.format( + logger.error(String.format( "Could not perform overnight maintenance on %s (%d) due to an error", part.getName(), part.getId()), e); addReport(String.format("ERROR: an error occurred performing overnight maintenance on %s, check the log", @@ -3608,7 +3613,7 @@ public void processNewDayUnits() { try { MRMSService.mrmsAllUnits(this); } catch (Exception ex) { - LogManager.getLogger().error("Could not perform mass repair/salvage on units due to an error", ex); + logger.error("Could not perform mass repair/salvage on units due to an error", ex); addReport("ERROR: an error occurred performing mass repair/salvage on units, check the log"); } } @@ -4659,7 +4664,7 @@ private void writeCustoms(PrintWriter pw1) { try { mechFileParser = new MechFileParser(ms.getSourceFile()); } catch (EntityLoadingException ex) { - LogManager.getLogger().error("", ex); + logger.error("", ex); } if (mechFileParser == null) { continue; @@ -4684,7 +4689,7 @@ private void writeCustoms(PrintWriter pw1) { pw1.println("]]>"); } catch (EntitySavingException e) { - LogManager.getLogger().error("Failed to save custom entity " + en.getDisplayName(), e); + logger.error("Failed to save custom entity " + en.getDisplayName(), e); } } pw1.println("\t"); @@ -5309,7 +5314,7 @@ public TargetRoll getTargetFor(final IPartWork partWork, final Person tech) { final int minutes = Math.min(partWork.getTimeLeft(), techTime); if (minutes <= 0) { - LogManager.getLogger().error("Attempting to get the target number for a part with zero time left."); + logger.error("Attempting to get the target number for a part with zero time left."); return new TargetRoll(TargetRoll.AUTOMATIC_SUCCESS, "No part repair time remaining."); } @@ -5585,7 +5590,7 @@ public void spendBonusPart(IAcquisitionWork targetWork) { } if (contract == null) { - LogManager.getLogger().error("AtB: used bonus part but no contract has bonus parts available."); + logger.error("AtB: used bonus part but no contract has bonus parts available."); } else { addReport(resources.getString("bonusPartLog.text") + ' ' + targetWork.getAcquisitionPart().getPartName()); contract.useBonusPart(); @@ -6779,7 +6784,7 @@ public void doMaintenance(Unit u) { maintenanceReport.append(partReport).append("
"); } } catch (Exception e) { - LogManager.getLogger().error(String.format( + logger.error(String.format( "Could not perform maintenance on part %s (%d) for %s (%s) due to an error", p.getName(), p.getId(), u.getName(), u.getId().toString()), e); addReport(String.format("ERROR: An error occurred performing maintenance on %s for unit %s, check the log", @@ -6803,7 +6808,7 @@ public void doMaintenance(Unit u) { u.setLastMaintenanceReport(maintenanceReport.toString()); if (getCampaignOptions().isLogMaintenance()) { - LogManager.getLogger().info(maintenanceReport.toString()); + logger.info(maintenanceReport.toString()); } int quality = u.getQuality(); diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 90b38f6f0b..cae73e8a1a 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -161,9 +161,9 @@ public static String getTransitUnitName(final int unit) { private boolean noClanPartsFromIS; private int penaltyClanPartsFromIS; private boolean planetAcquisitionVerbose; - private int[] planetTechAcquisitionBonus; - private int[] planetIndustryAcquisitionBonus; - private int[] planetOutputAcquisitionBonus; + private final int[] planetTechAcquisitionBonus; + private final int[] planetIndustryAcquisitionBonus; + private final int[] planetOutputAcquisitionBonus; //endregion Supplies and Acquisition Tab //region Tech Limits Tab @@ -487,7 +487,7 @@ public static String getTransitUnitName(final int unit) { //endregion Special Abilities Tab //region Skill Randomization Tab - private int[] phenotypeProbabilities; + private final int[] phenotypeProbabilities; //endregion Skill Randomization Tab //region Rank System Tab @@ -495,7 +495,7 @@ public static String getTransitUnitName(final int unit) { //region Name and Portrait Generation private boolean useOriginFactionForNames; - private boolean[] usePortraitForRole; + private final boolean[] usePortraitForRole; private boolean assignPortraitOnRoleChange; //endregion Name and Portrait Generation @@ -550,7 +550,7 @@ public static String getTransitUnitName(final int unit) { private int baseStrategyDeployment; private int additionalStrategyDeployment; private boolean adjustPaymentForStrategy; - private int[] atbBattleChance; + private final int[] atbBattleChance; private boolean generateChases; // Scenarios @@ -855,8 +855,8 @@ public CampaignOptions() { setUseRandomClanPersonnelMarriages(false); setUseRandomPrisonerMarriages(false); setRandomMarriageAgeRange(10); - setRandomMarriageDiceSize(6250); - setRandomSameSexMarriageDiceSize(6250); + setRandomMarriageDiceSize(5000); + setRandomSameSexMarriageDiceSize(14); setRandomNewDependentMarriage(20); // Divorce @@ -873,7 +873,7 @@ public CampaignOptions() { setUseRandomSameSexDivorce(true); setUseRandomClanPersonnelDivorce(true); setUseRandomPrisonerDivorce(false); - setRandomDivorceDiceSize(3221); + setRandomDivorceDiceSize(900); // Procreation setUseManualProcreation(true); @@ -890,8 +890,8 @@ public CampaignOptions() { setUseRelationshiplessRandomProcreation(false); setUseRandomClanPersonnelProcreation(false); setUseRandomPrisonerProcreation(true); - setRandomProcreationRelationshipDiceSize(621); - setRandomProcreationRelationshiplessDiceSize(8871); + setRandomProcreationRelationshipDiceSize(500); + setRandomProcreationRelationshiplessDiceSize(2000); // Education setUseEducationModule(false); @@ -5443,7 +5443,7 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setRandomSameSexMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("useRandomSameSexMarriages")) { // Legacy, pre-50.01 if (!Boolean.parseBoolean(wn2.getTextContent().trim())) { - retVal.setRandomSameSexMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + retVal.setRandomSameSexMarriageDiceSize(0); } } else if (wn2.getNodeName().equalsIgnoreCase("randomNewDependentMarriage")) { retVal.setRandomNewDependentMarriage(Integer.parseInt(wn2.getTextContent().trim())); diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java index c210b5b30a..6756ecda81 100644 --- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java +++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java @@ -29,6 +29,7 @@ import megamek.common.icons.AbstractIcon; import megamek.common.icons.Camouflage; import megamek.common.weapons.bayweapons.BayWeapon; +import megamek.logging.MMLogger; import mekhq.MekHQ; import mekhq.NullEntityException; import mekhq.Utilities; @@ -68,7 +69,6 @@ import mekhq.module.atb.AtBEventProcessor; import mekhq.utilities.MHQXMLUtility; import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; @@ -78,8 +78,10 @@ import java.util.Map.Entry; public class CampaignXmlParser { - private InputStream is; - private MekHQ app; + private final InputStream is; + private final MekHQ app; + + private static final MMLogger logger = MMLogger.create(CampaignXmlParser.class); public CampaignXmlParser(InputStream is, MekHQ app) { this.is = is; @@ -98,7 +100,7 @@ public void close() throws IOException { * @throws NullEntityException Thrown when an entity is referenced but cannot be loaded or found */ public Campaign parse() throws CampaignXmlParseException, NullEntityException { - LogManager.getLogger().info("Starting load of campaign file from XML..."); + logger.info("Starting load of campaign file from XML..."); // Initialize variables. Campaign retVal = new Campaign(); retVal.setApp(app); @@ -112,7 +114,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { // Parse using builder to get DOM representation of the XML file xmlDoc = db.parse(is); } catch (Exception ex) { - LogManager.getLogger().error("", ex); + logger.error("", ex); throw new CampaignXmlParseException(ex); } @@ -357,19 +359,19 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { for (Force f : retVal.getAllForces()) { if (!f.getUnits().isEmpty() && (null == lances.get(f.getId()))) { lances.put(f.getId(), new Lance(f.getId(), retVal)); - LogManager.getLogger().warn(String.format("Added missing Lance %s to AtB list", f.getName())); + logger.warn(String.format("Added missing Lance %s to AtB list", f.getName())); } } } - LogManager.getLogger().info(String.format("[Campaign Load] Force IDs set in %dms", + logger.info(String.format("[Campaign Load] Force IDs set in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); // Process parts... postProcessParts(retVal, version); - LogManager.getLogger().info(String.format("[Campaign Load] Parts processed in %dms", + logger.info(String.format("[Campaign Load] Parts processed in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -378,7 +380,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { psn.resetSkillTypes(); } - LogManager.getLogger().info(String.format("[Campaign Load] Rank references fixed in %dms", + logger.info(String.format("[Campaign Load] Rank references fixed in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -414,7 +416,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { final EquipmentUnscrambler unscrambler = EquipmentUnscrambler.create(unit); final EquipmentUnscramblerResult result = unscrambler.unscramble(); if (!result.succeeded()) { - LogManager.getLogger().warn(result.getMessage()); + logger.warn(result.getMessage()); } // some units might need to be assigned to scenarios @@ -428,7 +430,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { } }); - LogManager.getLogger().info(String.format("[Campaign Load] Pilot references fixed in %dms", + logger.info(String.format("[Campaign Load] Pilot references fixed in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -443,7 +445,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { }); retVal.refreshNetworks(); - LogManager.getLogger().info(String.format("[Campaign Load] C3 networks refreshed in %dms", + logger.info(String.format("[Campaign Load] C3 networks refreshed in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -470,7 +472,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { retVal.removeUnit(unit.getId()); } - LogManager.getLogger().info(String.format("[Campaign Load] Units initialized in %dms", + logger.info(String.format("[Campaign Load] Units initialized in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -478,13 +480,13 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { person.fixReferences(retVal); } - LogManager.getLogger().info(String.format("[Campaign Load] Personnel initialized in %dms", + logger.info(String.format("[Campaign Load] Personnel initialized in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); retVal.reloadNews(); - LogManager.getLogger().info(String.format("[Campaign Load] News loaded in %dms", + logger.info(String.format("[Campaign Load] News loaded in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -529,7 +531,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { bin.unload(); } - LogManager.getLogger().info(String.format("[Campaign Load] Ammo bins cleared in %dms", + logger.info(String.format("[Campaign Load] Ammo bins cleared in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -545,7 +547,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { } } - LogManager.getLogger().info(String.format("[Campaign Load] Reserved refit parts fixed in %dms", + logger.info(String.format("[Campaign Load] Reserved refit parts fixed in %dms", System.currentTimeMillis() - timestamp)); timestamp = System.currentTimeMillis(); @@ -558,12 +560,27 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { // This will have aggregated all of the possible spare parts together retVal.setWarehouse(warehouse); - LogManager.getLogger().info(String.format("[Campaign Load] Warehouse cleaned up in %dms", + logger.info(String.format("[Campaign Load] Warehouse cleaned up in %dms", System.currentTimeMillis() - timestamp)); retVal.setUnitRating(null); - LogManager.getLogger().info("Load of campaign file complete!"); + // this is used to handle characters from pre-50.01 campaigns + retVal.getPersonnel().stream() + .filter(person -> person.getJoinedCampaign() == null) + .forEach(person -> { + if (person.getRecruitment() != null) { + person.setJoinedCampaign(person.getRecruitment()); + logger.info("{} doesn't have a date recorded showing when they joined the campaign. Using recruitment date.", + person.getFullTitle()); + } else { + person.setJoinedCampaign(retVal.getLocalDate()); + logger.info("{} doesn't have a date recorded showing when they joined the campaign. Using current date.", + person.getFullTitle()); + } + }); + + logger.info("Load of campaign file complete!"); return retVal; } @@ -591,7 +608,7 @@ private void fixupUnitTechProblems(Campaign retVal) { tech.removeTechUnit(u); } if (null != reason) { - LogManager.getLogger().warn(String.format("Tech %s %s %s (fixed)", tech.getFullName(), reason, unitDesc)); + logger.warn(String.format("Tech %s %s %s (fixed)", tech.getFullName(), reason, unitDesc)); } } } @@ -738,7 +755,7 @@ private static void processInfoNode(Campaign retVal, Node wni, Version version) retVal.setId(UUID.fromString(wn.getTextContent().trim())); } } catch (Exception e) { - LogManager.getLogger().error("", e); + logger.error("", e); } } @@ -774,7 +791,7 @@ private static void processLanceNodes(Campaign retVal, Node wn) { if (!wn2.getNodeName().equalsIgnoreCase("lance")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().error("Unknown node type not loaded in Lance nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Lance nodes: " + wn2.getNodeName()); continue; } @@ -803,13 +820,13 @@ private static void cleanupGhostKills(Campaign retVal) { } private static void processFinances(Campaign retVal, Node wn) { - LogManager.getLogger().info("Loading Finances from XML..."); + logger.info("Loading Finances from XML..."); retVal.setFinances(Finances.generateInstanceFromXML(wn)); - LogManager.getLogger().info("Load of Finances complete!"); + logger.info("Load of Finances complete!"); } private static void processForces(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Force Organization from XML..."); + logger.info("Loading Force Organization from XML..."); NodeList wList = wn.getChildNodes(); @@ -826,7 +843,7 @@ private static void processForces(Campaign retVal, Node wn, Version version) { if (!wn2.getNodeName().equalsIgnoreCase("force")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().error("Unknown node type not loaded in Forces nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Forces nodes: " + wn2.getNodeName()); continue; } @@ -838,15 +855,15 @@ private static void processForces(Campaign retVal, Node wn, Version version) { foundForceAlready = true; } } else { - LogManager.getLogger().error("More than one type-level force found"); + logger.error("More than one type-level force found"); } } - LogManager.getLogger().info("Load of Force Organization complete!"); + logger.info("Load of Force Organization complete!"); } private static void processPersonnelNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Personnel Nodes from XML..."); + logger.info("Loading Personnel Nodes from XML..."); NodeList wList = wn.getChildNodes(); @@ -862,7 +879,7 @@ private static void processPersonnelNodes(Campaign retVal, Node wn, Version vers if (!wn2.getNodeName().equalsIgnoreCase("person")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().error("Unknown node type not loaded in Personnel nodes: {}", wn2.getNodeName()); + logger.error("Unknown node type not loaded in Personnel nodes: {}", wn2.getNodeName()); continue; } @@ -893,11 +910,11 @@ private static void processPersonnelNodes(Campaign retVal, Node wn, Version vers throw new NullPointerException(missingList.toString()); } - LogManager.getLogger().info("Load Personnel Nodes Complete!"); + logger.info("Load Personnel Nodes Complete!"); } private static void processSkillTypeNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Skill Type Nodes from XML..."); + logger.info("Loading Skill Type Nodes from XML..."); NodeList wList = wn.getChildNodes(); @@ -915,7 +932,7 @@ private static void processSkillTypeNodes(Campaign retVal, Node wn, Version vers } else if (!wn2.getNodeName().equalsIgnoreCase("skillType")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().error("Unknown node type not loaded in Skill Type nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Skill Type nodes: " + wn2.getNodeName()); continue; } @@ -923,11 +940,11 @@ private static void processSkillTypeNodes(Campaign retVal, Node wn, Version vers SkillType.generateInstanceFromXML(wn2, version); } - LogManager.getLogger().info("Load Skill Type Nodes Complete!"); + logger.info("Load Skill Type Nodes Complete!"); } private static void processStoryArcNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Story Arc Nodes from XML..."); + logger.info("Loading Story Arc Nodes from XML..."); StoryArc storyArc = StoryArc.parseFromXML(wn.getChildNodes(), retVal, version); MekHQ.registerHandler(storyArc); @@ -935,7 +952,7 @@ private static void processStoryArcNodes(Campaign retVal, Node wn, Version versi } private static void processSpecialAbilityNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Special Ability Nodes from XML..."); + logger.info("Loading Special Ability Nodes from XML..."); PersonnelOptions options = new PersonnelOptions(); @@ -956,17 +973,17 @@ private static void processSpecialAbilityNodes(Campaign retVal, Node wn, Version if (!wn2.getNodeName().equalsIgnoreCase("ability")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().error("Unknown node type not loaded in Special Ability nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Special Ability nodes: " + wn2.getNodeName()); continue; } SpecialAbility.generateInstanceFromXML(wn2, options, version); } - LogManager.getLogger().info("Load Special Ability Nodes Complete!"); + logger.info("Load Special Ability Nodes Complete!"); } private static void processKillNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Kill Nodes from XML..."); + logger.info("Loading Kill Nodes from XML..."); NodeList wList = wn.getChildNodes(); @@ -980,7 +997,7 @@ private static void processKillNodes(Campaign retVal, Node wn, Version version) } else if (!wn2.getNodeName().equalsIgnoreCase("kill")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().error("Unknown node type not loaded in Kill nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Kill nodes: " + wn2.getNodeName()); continue; } @@ -990,7 +1007,7 @@ private static void processKillNodes(Campaign retVal, Node wn, Version version) } } - LogManager.getLogger().info("Load Kill Nodes Complete!"); + logger.info("Load Kill Nodes Complete!"); } /** @@ -1007,14 +1024,14 @@ private static boolean processCustom(Campaign retVal, Node wn) { File customsDir = new File(sCustomsDir); if (!customsDir.exists()) { if (!customsDir.mkdir()) { - LogManager.getLogger().error("Failed to create directory " + sCustomsDir + ", and therefore cannot save the unit."); + logger.error("Failed to create directory " + sCustomsDir + ", and therefore cannot save the unit."); return false; } } File customsDirCampaign = new File(sCustomsDirCampaign); if (!customsDirCampaign.exists()) { if (!customsDirCampaign.mkdir()) { - LogManager.getLogger().error("Failed to create directory " + sCustomsDirCampaign + ", and therefore cannot save the unit."); + logger.error("Failed to create directory " + sCustomsDirCampaign + ", and therefore cannot save the unit."); return false; } } @@ -1077,24 +1094,24 @@ private static boolean processCustom(Campaign retVal, Node wn) { } private static boolean tryWriteCustomToFile(String fileName, String contents) { - LogManager.getLogger().info("Writing custom unit from inline data to " + fileName); + logger.info("Writing custom unit from inline data to " + fileName); try (OutputStream out = new FileOutputStream(fileName); PrintStream p = new PrintStream(out)) { p.println(contents); - LogManager.getLogger().info("Wrote custom unit from inline data to: " + fileName); + logger.info("Wrote custom unit from inline data to: " + fileName); return true; } catch (Exception ex) { - LogManager.getLogger().error("Error writing custom unit from inline data to: " + fileName, ex); + logger.error("Error writing custom unit from inline data to: " + fileName, ex); return false; } } private static void processMissionNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Mission Nodes from XML..."); + logger.info("Loading Mission Nodes from XML..."); NodeList wList = wn.getChildNodes(); @@ -1110,7 +1127,7 @@ private static void processMissionNodes(Campaign retVal, Node wn, Version versio if (!wn2.getNodeName().equalsIgnoreCase("mission")) { // Error condition of sorts! // Errr, what should we do here? - LogManager.getLogger().warn("Unknown node type not loaded in Mission nodes: " + wn2.getNodeName()); + logger.warn("Unknown node type not loaded in Mission nodes: " + wn2.getNodeName()); continue; } @@ -1126,11 +1143,11 @@ private static void processMissionNodes(Campaign retVal, Node wn, Version versio contract.restore(retVal); } - LogManager.getLogger().info("Load Mission Nodes Complete!"); + logger.info("Load Mission Nodes Complete!"); } private static @Nullable String checkUnits(final Node wn) { - LogManager.getLogger().info("Checking for missing entities..."); + logger.info("Checking for missing entities..."); List unitList = new ArrayList<>(); NodeList wList = wn.getChildNodes(); @@ -1162,12 +1179,12 @@ private static void processMissionNodes(Campaign retVal, Node wn, Version versio } } } catch (Exception ex) { - LogManager.getLogger().error("Could not read entity from XML", ex); + logger.error("Could not read entity from XML", ex); } } } } - LogManager.getLogger().info("Finished checking for missing entities!"); + logger.info("Finished checking for missing entities!"); if (unitList.isEmpty()) { return null; @@ -1176,13 +1193,13 @@ private static void processMissionNodes(Campaign retVal, Node wn, Version versio for (String s : unitList) { unitListString.append('\n').append(s); } - LogManager.getLogger().error(String.format("Could not load the following units: %s", unitListString)); + logger.error(String.format("Could not load the following units: %s", unitListString)); return unitListString.toString(); } } private static void processUnitNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Unit Nodes from XML..."); + logger.info("Loading Unit Nodes from XML..."); NodeList wList = wn.getChildNodes(); @@ -1196,7 +1213,7 @@ private static void processUnitNodes(Campaign retVal, Node wn, Version version) } if (!wn2.getNodeName().equalsIgnoreCase("unit")) { - LogManager.getLogger().error("Unknown node type not loaded in Unit nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Unit nodes: " + wn2.getNodeName()); continue; } @@ -1207,11 +1224,11 @@ private static void processUnitNodes(Campaign retVal, Node wn, Version version) } } - LogManager.getLogger().info("Load Unit Nodes Complete!"); + logger.info("Load Unit Nodes Complete!"); } private static void processPartNodes(Campaign retVal, Node wn, Version version) { - LogManager.getLogger().info("Loading Part Nodes from XML..."); + logger.info("Loading Part Nodes from XML..."); NodeList wList = wn.getChildNodes(); @@ -1226,7 +1243,7 @@ private static void processPartNodes(Campaign retVal, Node wn, Version version) } if (!wn2.getNodeName().equalsIgnoreCase("part")) { - LogManager.getLogger().error("Unknown node type not loaded in Part nodes: " + wn2.getNodeName()); + logger.error("Unknown node type not loaded in Part nodes: " + wn2.getNodeName()); continue; } @@ -1239,7 +1256,7 @@ private static void processPartNodes(Campaign retVal, Node wn, Version version) retVal.importParts(parts); - LogManager.getLogger().info("Load Part Nodes Complete!"); + logger.info("Load Part Nodes Complete!"); } private static void postProcessParts(Campaign retVal, Version version) { @@ -1251,7 +1268,7 @@ private static void postProcessParts(Campaign retVal, Version version) { // Remove fundamentally broken equipment parts if (((prt instanceof EquipmentPart) && ((EquipmentPart) prt).getType() == null) || ((prt instanceof MissingEquipmentPart) && ((MissingEquipmentPart) prt).getType() == null)) { - LogManager.getLogger().warn("Could not find matching EquipmentType for part " + prt.getName()); + logger.warn("Could not find matching EquipmentType for part " + prt.getName()); removeParts.add(prt); continue; } @@ -1474,7 +1491,7 @@ private static void postProcessParts(Campaign retVal, Version version) { } } for (Part prt : removeParts) { - LogManager.getLogger().debug("Removing part #" + prt.getId() + ' ' + prt.getName()); + logger.debug("Removing part #" + prt.getId() + ' ' + prt.getName()); retVal.getWarehouse().removePart(prt); } } @@ -1605,7 +1622,7 @@ private static void updatePlanetaryEventsFromXML(Node wn) { //region Migration Methods //region Ancestry Migration - private static Map> ancestryMigrationMap = new HashMap<>(); + private static final Map> ancestryMigrationMap = new HashMap<>(); /** * This method is used to add people to the ancestry migration map that is used to migrate @@ -1663,21 +1680,21 @@ private static void migrateAncestorNodes(Campaign campaign, Node wn) { people.remove(); if (father == null) { - LogManager.getLogger().warn("Unknown father does not exist, skipping adding Genealogy for them."); + logger.warn("Unknown father does not exist, skipping adding Genealogy for them."); } else if (father.getId() != null) { person.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, father); father.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, person); } else { - LogManager.getLogger().warn("Person with id " + father.getId() + "does not exist, skipping adding Genealogy for them."); + logger.warn("Person with id " + father.getId() + "does not exist, skipping adding Genealogy for them."); } if (mother == null) { - LogManager.getLogger().warn("Unknown mother does not exist, skipping adding Genealogy for them."); + logger.warn("Unknown mother does not exist, skipping adding Genealogy for them."); } else if (mother.getId() != null) { person.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, mother); mother.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, person); } else { - LogManager.getLogger().warn("Person with id " + mother.getId() + " does not exist, skipping adding Genealogy for them."); + logger.warn("Person with id " + mother.getId() + " does not exist, skipping adding Genealogy for them."); } } } diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java index 5c91cfa89e..42021cb2d7 100644 --- a/MekHQ/src/mekhq/campaign/personnel/Person.java +++ b/MekHQ/src/mekhq/campaign/personnel/Person.java @@ -30,6 +30,7 @@ import megamek.common.options.IOption; import megamek.common.options.IOptionGroup; import megamek.common.options.OptionsConstants; +import megamek.logging.MMLogger; import mekhq.MekHQ; import mekhq.Utilities; import mekhq.campaign.Campaign; @@ -65,7 +66,6 @@ import mekhq.io.migration.FactionMigrator; import mekhq.io.migration.PersonMigrator; import mekhq.utilities.MHQXMLUtility; -import org.apache.logging.log4j.LogManager; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -122,6 +122,7 @@ public class Person { private String biography; private LocalDate birthday; + private LocalDate joinedCampaign; private LocalDate recruitment; private LocalDate lastRankChangeDate; private LocalDate dateOfDeath; @@ -240,6 +241,8 @@ public class Person { private final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); + private static final MMLogger logger = MMLogger.create(Person.class); + // initializes the AtB ransom values static { MECHWARRIOR_AERO_RANSOM_VALUES = new HashMap<>(); @@ -343,6 +346,7 @@ public Person(final String preNominal, final String givenName, final String surn resetMinutesLeft(); // this assigns minutesLeft and overtimeLeft dateOfDeath = null; recruitment = null; + joinedCampaign = null; lastRankChangeDate = null; retirement = null; loyalty = 9; @@ -1266,6 +1270,14 @@ public int getAge(LocalDate today) { return Math.toIntExact(ChronoUnit.YEARS.between(getBirthday(), today)); } + public @Nullable LocalDate getJoinedCampaign() { + return joinedCampaign; + } + + public void setJoinedCampaign(final @Nullable LocalDate joinedCampaign) { + this.joinedCampaign = joinedCampaign; + } + public @Nullable LocalDate getRecruitment() { return recruitment; } @@ -1888,6 +1900,8 @@ public void writeToXML(final PrintWriter pw, int indent, final Campaign campaign MHQXMLUtility.writeSimpleXMLTag(pw, indent, "birthday", getBirthday()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "deathday", getDateOfDeath()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "recruitment", getRecruitment()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "joinedCampaign", getJoinedCampaign()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "lastRankChangeDate", getLastRankChangeDate()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "retirement", getRetirement()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "loyalty", getLoyalty()); @@ -2072,7 +2086,7 @@ public void writeToXML(final PrintWriter pw, int indent, final Campaign campaign extraData.writeToXml(pw); } } catch (Exception ex) { - LogManager.getLogger().error("Failed to write " + getFullName() + " to the XML File", ex); + logger.error("Failed to write " + getFullName() + " to the XML File", ex); throw ex; // we want to rethrow to ensure that the save fails } @@ -2127,7 +2141,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } retVal.originPlanet = p; } catch (NullPointerException e) { - LogManager.getLogger().error("Error loading originPlanet for {}, {}", systemId, planetId, e); + logger.error("Error loading originPlanet for {}, {}", systemId, planetId, e); } } else if (wn2.getNodeName().equalsIgnoreCase("phenotype")) { retVal.phenotype = Phenotype.parseFromString(wn2.getTextContent().trim()); @@ -2222,6 +2236,8 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio retVal.dateOfDeath = MHQXMLUtility.parseDate(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("recruitment")) { retVal.recruitment = MHQXMLUtility.parseDate(wn2.getTextContent().trim()); + } else if (wn2.getNodeName().equalsIgnoreCase("joinedCampaign")) { + retVal.joinedCampaign = MHQXMLUtility.parseDate(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("lastRankChangeDate")) { retVal.lastRankChangeDate = MHQXMLUtility.parseDate(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("retirement")) { @@ -2259,7 +2275,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("id")) { - LogManager.getLogger().error("Unknown node type not loaded in techUnitIds nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in techUnitIds nodes: " + wn3.getNodeName()); continue; } retVal.addTechUnit(new PersonUnitRef(UUID.fromString(wn3.getTextContent()))); @@ -2274,7 +2290,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("logEntry")) { - LogManager.getLogger().error("Unknown node type not loaded in personnel log nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in personnel log nodes: " + wn3.getNodeName()); continue; } @@ -2294,7 +2310,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("logEntry")) { - LogManager.getLogger().error("Unknown node type not loaded in scenario log nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in scenario log nodes: " + wn3.getNodeName()); continue; } @@ -2313,7 +2329,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("award")) { - LogManager.getLogger().error("Unknown node type not loaded in personnel log nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in personnel log nodes: " + wn3.getNodeName()); continue; } @@ -2330,7 +2346,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("injury")) { - LogManager.getLogger().error("Unknown node type not loaded in injury nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in injury nodes: " + wn3.getNodeName()); continue; } retVal.injuries.add(Injury.generateInstanceFromXML(wn3)); @@ -2443,7 +2459,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio try { retVal.getOptions().getOption(advName).setValue(value); } catch (Exception e) { - LogManager.getLogger().error("Error restoring advantage: {}", adv); + logger.error("Error restoring advantage: {}", adv); } } } @@ -2458,7 +2474,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio try { retVal.getOptions().getOption(advName).setValue(value); } catch (Exception e) { - LogManager.getLogger().error("Error restoring edge: {}", adv); + logger.error("Error restoring edge: {}", adv); } } } @@ -2473,7 +2489,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio try { retVal.getOptions().getOption(advName).setValue(value); } catch (Exception e) { - LogManager.getLogger().error("Error restoring implants: {}", adv); + logger.error("Error restoring implants: {}", adv); } } } @@ -2489,7 +2505,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio retVal.setRecruitment(c.getLocalDate()); } } catch (Exception e) { - LogManager.getLogger().error("Failed to read person {} from file", retVal.getFullName(), e); + logger.error("Failed to read person {} from file", retVal.getFullName(), e); retVal = null; } @@ -3994,7 +4010,7 @@ public void fixReferences(final Campaign campaign) { final UUID id = unit.getId(); unit = campaign.getUnit(id); if (unit == null) { - LogManager.getLogger().error(String.format("Person %s ('%s') references missing unit %s", + logger.error(String.format("Person %s ('%s') references missing unit %s", getId(), getFullName(), id)); } } @@ -4006,7 +4022,7 @@ public void fixReferences(final Campaign campaign) { if (realUnit != null) { techUnits.set(ii, realUnit); } else { - LogManager.getLogger().error(String.format("Person %s ('%s') techs missing unit %s", + logger.error(String.format("Person %s ('%s') techs missing unit %s", getId(), getFullName(), techUnit.getId())); techUnits.remove(ii); } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 6827c7ed37..d93fd8a612 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -27,11 +27,14 @@ import mekhq.campaign.log.PersonalLogger; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.FormerSpouseReason; +import mekhq.campaign.personnel.enums.PersonnelStatus; import mekhq.campaign.personnel.enums.RandomDivorceMethod; import mekhq.campaign.personnel.enums.SplittingSurnameStyle; import mekhq.campaign.personnel.familyTree.FormerSpouse; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; import java.util.ResourceBundle; /** @@ -256,6 +259,42 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person spouse.setMarriageable(false); } + List departingPartners = new ArrayList<>(); + + if (origin.getPrimaryRole().isDependent()) { + departingPartners.add(origin); + } + + if (spouse.getPrimaryRole().isDependent()) { + departingPartners.add(origin); + } + + if (!departingPartners.isEmpty()) { + for (Person departingPartner : departingPartners) { + departingPartner.changeStatus(campaign, today, PersonnelStatus.LEFT); + + for (Person child : departingPartner.getGenealogy().getChildren()) { + int remainingParents = child.getGenealogy().getParents().size(); + + if ((remainingParents == 0) || (Compute.randomInt(2) == 0)) { + child.changeStatus(campaign, today, PersonnelStatus.LEFT); + } + } + } + } + + // Process any relevant loyalty changes + if (campaign.getCampaignOptions().isUseLoyaltyModifiers()) { + if (origin.getStatus().isLeft() && !spouse.getStatus().isLeft()) { + spouse.performRandomizedLoyaltyChange(campaign, false, true); + } else if (!origin.getStatus().isLeft() && spouse.getStatus().isLeft()) { + origin.performRandomizedLoyaltyChange(campaign, false, true); + } else if (origin.getStatus().isLeft() && spouse.getStatus().isLeft()) { + origin.performForcedDirectionLoyaltyChange(campaign, false, false, true); + spouse.performForcedDirectionLoyaltyChange(campaign, false, false, true); + } + } + // trigger person changed events MekHQ.triggerEvent(new PersonChangedEvent(spouse)); MekHQ.triggerEvent(new PersonChangedEvent(origin)); diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 5fd9447701..ea1c856d01 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -219,8 +219,14 @@ public void marry(final Campaign campaign, final LocalDate today, final Person o spouse.getGenealogy().setOriginSpouse(origin); // recruit the spouse if they're not already in the unit - if (spouse.getRecruitment() == null) { - campaign.recruitPerson(spouse, PrisonerStatus.FREE, true, true); + if (spouse.getJoinedCampaign() == null) { + campaign.recruitPerson(spouse, PrisonerStatus.FREE, true, false); + + ResourceBundle recruitmentResources = ResourceBundle.getBundle("mekhq.resources.Campaign", + MekHQ.getMHQOptions().getLocale()); + + campaign.addReport(String.format(recruitmentResources.getString("dependentJoinsForce.text"), + spouse.getHyperlinkedFullTitle())); } // And finally, we trigger person changed events From 08c3c8388d48663db9e37fee8a17d1f28109441d Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Fri, 2 Aug 2024 15:20:29 -0500 Subject: [PATCH 21/41] Refactor logging system references Replaced LogManager.getLogger() with logger. Renamed variables from 'p' to 'person' in the auto award support points section. --- MekHQ/src/mekhq/campaign/Campaign.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index f82c335517..1e9c7db2a9 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -1158,7 +1158,7 @@ public CurrentLocation getLocation() { public void importUnit(Unit u) { Objects.requireNonNull(u); - LogManager.getLogger().debug("Importing unit: ({}): {}", u.getId(), u.getName()); + logger.debug("Importing unit: ({}): {}", u.getId(), u.getName()); getHangar().addUnit(u); @@ -1183,7 +1183,7 @@ public void importUnit(Unit u) { * @param unit - The ship we want to add to this Set */ public void addTransportShip(Unit unit) { - LogManager.getLogger().debug("Adding DropShip/WarShip: {}", unit.getId()); + logger.debug("Adding DropShip/WarShip: {}", unit.getId()); transportShips.add(Objects.requireNonNull(unit)); } @@ -3511,8 +3511,8 @@ public void processNewDayPersonnel() { int score = 0; - if (p.getPrimaryRole().isSupport(true)) { - int dice = p.getExperienceLevel(this, false); + if (person.getPrimaryRole().isSupport(true)) { + int dice = person.getExperienceLevel(this, false); if (dice > 0) { score = Compute.d6(dice); @@ -3521,19 +3521,19 @@ public void processNewDayPersonnel() { multiplier += 0.5; } - if (p.getSecondaryRole().isSupport(true)) { - int dice = p.getExperienceLevel(this, true); + if (person.getSecondaryRole().isSupport(true)) { + int dice = person.getExperienceLevel(this, true); if (dice > 0) { score += Compute.d6(dice); } multiplier += 0.5; - } else if (p.getSecondaryRole().isNone()) { + } else if (person.getSecondaryRole().isNone()) { multiplier += 0.5; } - p.changeAutoAwardSupportPoints((int) (score * multiplier)); + person.changeAutoAwardSupportPoints((int) (score * multiplier)); } } } @@ -4746,7 +4746,7 @@ private void writeCustoms(PrintWriter pw1) { pw1.println("]]>"); } catch (EntitySavingException e) { - LogManager.getLogger().error("Failed to save custom entity {}", en.getDisplayName(), e); + logger.error("Failed to save custom entity {}", en.getDisplayName(), e); } } pw1.println("\t"); From 50c62fb79d24bdded59ce3e3614a75b2d6e58747 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Fri, 2 Aug 2024 23:46:20 -0500 Subject: [PATCH 22/41] Refactor and streamline personnel generation logic Refactored personnel generation and procreation processes, ensuring proper handling of skills, loyalty, and education based on age. Enhanced marriage and procreation logic to include additional parameters and detailed checks. Updated unit tests to reflect these changes. --- MekHQ/src/mekhq/campaign/Campaign.java | 201 +++++++----------- MekHQ/src/mekhq/campaign/CampaignOptions.java | 2 - .../generator/AbstractPersonnelGenerator.java | 10 +- .../generator/DefaultPersonnelGenerator.java | 52 ++++- .../generator/DefaultSkillGenerator.java | 10 +- .../personnel/marriage/AbstractMarriage.java | 74 +++++-- .../procreation/AbstractProcreation.java | 57 ++--- .../AbstractCompanyGenerator.java | 3 - .../adapter/PersonnelTableMouseAdapter.java | 2 +- .../gui/dialog/HireBulkPersonnelDialog.java | 54 +++-- .../marriage/AbstractMarriageTest.java | 35 +-- 11 files changed, 270 insertions(+), 230 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 9b75a5f9cc..aa786f51b2 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -26,6 +26,7 @@ import megamek.client.generator.RandomUnitGenerator; import megamek.client.ui.swing.util.PlayerColour; import megamek.codeUtilities.MathUtility; +import megamek.codeUtilities.ObjectUtility; import megamek.common.*; import megamek.common.AmmoType.Munitions; import megamek.common.annotations.Nullable; @@ -83,15 +84,11 @@ import mekhq.campaign.personnel.education.Academy; import mekhq.campaign.personnel.education.EducationController; import mekhq.campaign.personnel.enums.*; -import mekhq.campaign.personnel.enums.education.EducationLevel; -import mekhq.campaign.personnel.generator.AbstractPersonnelGenerator; -import mekhq.campaign.personnel.generator.DefaultPersonnelGenerator; -import mekhq.campaign.personnel.generator.RandomPortraitGenerator; +import mekhq.campaign.personnel.generator.*; import mekhq.campaign.personnel.marriage.AbstractMarriage; import mekhq.campaign.personnel.marriage.DisabledRandomMarriage; import mekhq.campaign.personnel.procreation.AbstractProcreation; import mekhq.campaign.personnel.procreation.DisabledRandomProcreation; -import mekhq.campaign.personnel.randomEvents.PersonalityController; import mekhq.campaign.personnel.ranks.RankSystem; import mekhq.campaign.personnel.ranks.RankValidator; import mekhq.campaign.personnel.ranks.Ranks; @@ -1380,14 +1377,6 @@ public Person newDependent(boolean baby, Gender gender) { person = newPerson(PersonnelRole.DEPENDENT); } - if (person.getAge(getLocalDate()) < 16) { - person.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); - } else { - person.setEduHighestEducation(EducationLevel.HIGH_SCHOOL); - } - - PersonalityController.generatePersonality(person); - return person; } @@ -1479,13 +1468,6 @@ public Person newPerson(final PersonnelRole primaryRole, final PersonnelRole sec assignRandomPortraitFor(person); } - // TODO remove this once we have the Personnel Histories module - if (person.getAge(getLocalDate()) >= 16) { - person.setEduHighestEducation(EducationLevel.HIGH_SCHOOL); - } - - PersonalityController.generatePersonality(person); - return person; } @@ -1581,147 +1563,118 @@ public boolean recruitPerson(Person p, PrisonerStatus prisonerStatus, boolean gm private void simulateRelationshipHistory(Person person) { // how many weeks should the simulation run? - // we use weeks as we can get similar results to days for 1/7 of the processing debt LocalDate localDate = getLocalDate(); long weeksBetween = ChronoUnit.WEEKS.between(person.getBirthday().plusYears(18), localDate); - LogManager.getLogger().info(weeksBetween); - // this means there is nothing to simulate if (weeksBetween == 0) { return; } - // get all the variables needed for the simulation - - // procreation chances - double childChanceRelationship = getCampaignOptions().getRandomProcreationMethod().isPercentage() ? - getCampaignOptions().getPercentageRandomProcreationRelationshipChance() * 7 : 0; - - double childChanceRelationshipless = getCampaignOptions().getRandomProcreationMethod().isPercentage() ? - getCampaignOptions().getPercentageRandomProcreationRelationshiplessChance() * 7 : 0; - - // marriage chances & age range - double relationshipChanceOppositeSex = getCampaignOptions().getRandomMarriageMethod().isPercentage() ? - getCampaignOptions().getPercentageRandomMarriageOppositeSexChance() * 7 : 0; - - double relationshipChanceSameSex = (getCampaignOptions().isUseRandomSameSexMarriages() && getCampaignOptions().getRandomMarriageMethod().isPercentage()) ? - getCampaignOptions().getPercentageRandomMarriageSameSexChance() * 7 : 0; - - int relationshipAgeRange = getCampaignOptions().getRandomMarriageAgeRange(); - - double relationshipChance = Math.max(relationshipChanceOppositeSex, relationshipChanceSameSex); - - // divorce chances - double divorceChanceOppositeSex = getCampaignOptions().getRandomDivorceMethod().isPercentage() ? - getCampaignOptions().getPercentageRandomDivorceOppositeSexChance() * 7 : 0; - - double divorceChanceSameSex = (getCampaignOptions().isUseRandomSameSexDivorce() && getCampaignOptions().getRandomDivorceMethod().isPercentage()) ? - getCampaignOptions().getPercentageRandomDivorceSameSexChance() * 7 : 0; - - double divorceChance = Math.max(divorceChanceOppositeSex, divorceChanceSameSex); - List children = new ArrayList<>(); Person currentSpouse = null; - Gender spouseGender = Gender.FEMALE; - - if (getCampaignOptions().isUseRandomSameSexMarriages()) { - spouseGender = Gender.RANDOMIZE; - } else if (person.getGender().isFemale()) { - spouseGender = Gender.MALE; - } - // run the simulation for (long weeksRemaining = weeksBetween; weeksRemaining >= 0; weeksRemaining--) { - if (currentSpouse == null) { - // first, we check for out-of-relationship children - if (person.getGender().isFemale()) { - if (Compute.randomFloat() <= childChanceRelationshipless) { - // if the person was not old enough at potential conception, we skip - if (person.getAge(localDate.minusWeeks(weeksRemaining + 40)) < 18) { - continue; - } + LocalDate currentDate = getLocalDate().plusWeeks(weeksRemaining); - getProcreation().addPregnancy(this, localDate.minusWeeks(weeksRemaining + 40), person, true); - children.addAll(getProcreation().birthHistoric(this, localDate.minusWeeks(weeksRemaining), person, null)); - } - } + logger.info(weeksRemaining); - // then, we check for new relationships - if (Compute.randomFloat() <= relationshipChance) { - currentSpouse = newDependent(false, spouseGender); + // first, we check for old relationships ending and new relationships beginning + if (currentSpouse != null) { + logger.info("relationship ending roll"); + getDivorce().processNewWeek(this, currentDate, person); - currentSpouse.setOriginFaction(person.getOriginFaction()); - currentSpouse.setOriginPlanet(person.getOriginPlanet()); + List toRemove = new ArrayList<>(); + // there is a chance a departing spouse might take some of their children with them + for (Person child : children) { + if (child.getGenealogy().getParents().contains(currentSpouse)) { + if (Compute.randomInt(2) == 0) { + toRemove.add(child); + } + } + } - // this needs to be 19, not 18, due to rounding errors making it possible to have 17-year-old spouses if we put 18 - currentSpouse.setBirthday(localDate.minusYears(Math.max(19, person.getAge(localDate) - Compute.randomInt(relationshipAgeRange)))); + children.removeAll(toRemove); - AbstractMarriage.performMarriageChanges(this, localDate.minusWeeks(weeksRemaining), person, currentSpouse, MergingSurnameStyle.WEIGHTED); - } + currentSpouse = null; } else { - // add age appropriate female personnel to a list - List potentialMothers = new ArrayList<>(); - - if ((person.getGender().isFemale()) && (person.getAge(localDate.minusWeeks(weeksRemaining + 40)) >= 18)) { - potentialMothers.add(person); - } + logger.info("relationship starting roll"); + getMarriage().processBackgroundMarriageRolls(this, currentDate, person); - if ((currentSpouse.getGender().isFemale()) && (person.getAge(localDate.minusWeeks(weeksRemaining + 40)) >= 18)) { - potentialMothers.add(currentSpouse); + if (person.getGenealogy().hasSpouse()) { + currentSpouse = person.getGenealogy().getSpouse(); } + } - if (!potentialMothers.isEmpty()) { - Collections.shuffle(potentialMothers); - - // pick mother and father, if there are no males in the relationship father remains null - Person potentialMother = potentialMothers.get(0); - Person potentialFather = null; - - if (person.equals(potentialMother)) { - if (currentSpouse.getGender().isMale()) { - potentialFather = currentSpouse; - } - } else { - if (person.getGender().isMale()) { - potentialFather = person; - } - } + logger.info(currentSpouse); - // next we check for out-of-relationship children - if (Compute.randomFloat() <= childChanceRelationship) { - getProcreation().addPregnancy(this, localDate.minusWeeks(weeksRemaining + 40), potentialMother, true); - children.addAll(getProcreation().birthHistoric(this, localDate.minusWeeks(weeksRemaining), potentialMother, potentialFather)); - } + // then we check for children + if (person.getGender().isFemale()) { + logger.info("rolling for Person pregnancy"); + getProcreation().processRandomProcreationCheck(this, localDate.minusWeeks(weeksRemaining), person, true); - // here, we check for relationships ending - if (Compute.randomFloat() <= divorceChance) { - getDivorce().divorceHistoric(this, localDate.minusWeeks(weeksRemaining), person); + if (person.isPregnant()) { + children.addAll(getProcreation().birthHistoric(this, person.getDueDate(), person, null)); + } + } - // there is a chance the departing spouse will take some children with them - children.removeIf(child -> (Compute.randomInt(1) == 0)); + if ((currentSpouse != null) && (currentSpouse.getGender().isFemale())) { + logger.info("rolling for Spouse pregnancy"); + getProcreation().processRandomProcreationCheck(this, localDate.minusWeeks(weeksRemaining), person, true); - currentSpouse = null; - } + if (person.isPregnant()) { + getProcreation().birthHistoric(this, person.getDueDate(), person, null); } } } - // finally, we add the current spouse (if any) and any remaining children to the unit - if (currentSpouse != null) { + logger.info("simulation has ended for {}", person.getFullTitle()); + // with the simulation concluded, we add the current spouse (if any) and any remaining children to the unit + if (currentSpouse != null) { recruitPerson(currentSpouse, PrisonerStatus.FREE, true, true); } - if (!children.isEmpty()) { - for (Person child : children) { - child.setOriginFaction(person.getOriginFaction()); - child.setOriginPlanet(person.getOriginPlanet()); + for (Person child : children) { + child.setOriginFaction(person.getOriginFaction()); + child.setOriginPlanet(person.getOriginPlanet()); - recruitPerson(child, PrisonerStatus.FREE, true, true); + int age = child.getAge(localDate); + + // Limit skills by age for children and adolescents + if (age < 16) { + child.removeAllSkills(); + } else if (age < 18) { + child.limitSkills(0); } + + // re-roll SPAs to include in any age and skill adjustments + Enumeration options = new PersonnelOptions().getOptions(PersonnelOptions.LVL3_ADVANTAGES); + + for (IOption option : Collections.list(options)) { + child.getOptions().getOption(option.getName()).clearValue(); + } + + int experienceLevel = child.getExperienceLevel(this, false); + + // set loyalty + if (experienceLevel <= 0) { + person.setLoyalty(Compute.d6(3) + 2); + } else if (experienceLevel == 1) { + person.setLoyalty(Compute.d6(3) + 1); + } else { + person.setLoyalty(Compute.d6(3)); + } + + if (experienceLevel >= 0) { + AbstractSpecialAbilityGenerator specialAbilityGenerator = new DefaultSpecialAbilityGenerator(); + specialAbilityGenerator.setSkillPreferences(new RandomSkillPreferences()); + specialAbilityGenerator.generateSpecialAbilities(this, child, experienceLevel); + } + + recruitPerson(child, PrisonerStatus.FREE, true, true); } } //endregion Personnel Recruitment diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index c666c1f3fb..d2cc6a6367 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -369,8 +369,6 @@ public static String getTransitUnitName(final int unit) { //region Turnover and Retention private boolean useRandomRetirement; - private TurnoverTargetNumberMethod turnoverTargetNumberMethod; - private SkillLevel turnoverDifficulty; private int turnoverFixedTargetNumber; private boolean aeroRecruitsHaveUnits; private boolean trackOriginalUnit; diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java index 4908f2dfa8..7507976883 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java @@ -18,11 +18,8 @@ */ package mekhq.campaign.personnel.generator; -import java.time.LocalDate; -import java.util.Objects; - -import megamek.client.generator.RandomNameGenerator; import megamek.client.generator.RandomGenderGenerator; +import megamek.client.generator.RandomNameGenerator; import megamek.common.Compute; import megamek.common.enums.Gender; import mekhq.Utilities; @@ -33,6 +30,9 @@ import mekhq.campaign.personnel.enums.PersonnelRole; import mekhq.campaign.personnel.enums.Phenotype; +import java.time.LocalDate; +import java.util.Objects; + /** * Represents a class which can generate new {@link Person} objects * for a {@link Campaign}. @@ -99,7 +99,7 @@ protected Person createPerson(Campaign campaign) { * @param person The {@link Person} being generated. * @return An integer value between {@link SkillType#EXP_ULTRA_GREEN} and {@link SkillType#EXP_ELITE}. */ - protected int generateExperienceLevel(Campaign campaign, Person person) { + public int generateExperienceLevel(Campaign campaign, Person person) { int bonus = getSkillPreferences().getOverallRecruitBonus() + getSkillPreferences().getRecruitBonus(person.getPrimaryRole()); diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java index 11305abcc2..b07a39400c 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java @@ -21,9 +21,12 @@ import megamek.common.Compute; import megamek.common.enums.Gender; import mekhq.campaign.Campaign; +import mekhq.campaign.RandomSkillPreferences; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.backgrounds.BackgroundsController; import mekhq.campaign.personnel.enums.PersonnelRole; +import mekhq.campaign.personnel.enums.education.EducationLevel; +import mekhq.campaign.personnel.randomEvents.PersonalityController; import mekhq.campaign.universe.Faction; import mekhq.campaign.universe.Planet; import mekhq.campaign.universe.selectors.factionSelectors.AbstractFactionSelector; @@ -82,20 +85,28 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo generateBirthday(campaign, person, expLvl, person.isClanPersonnel() && !person.getPhenotype().isNone()); - if (expLvl == 0) { - person.setLoyalty(Compute.d6(3) + 2); - } else if (expLvl == 1) { - person.setLoyalty(Compute.d6(3) + 1); - } else { - person.setLoyalty(Compute.d6(3)); - } - AbstractSkillGenerator skillGenerator = new DefaultSkillGenerator(getSkillPreferences()); skillGenerator.generateSkills(campaign, person, expLvl); - AbstractSpecialAbilityGenerator specialAbilityGenerator = new DefaultSpecialAbilityGenerator(); - specialAbilityGenerator.setSkillPreferences(getSkillPreferences()); - specialAbilityGenerator.generateSpecialAbilities(campaign, person, expLvl); + // Limit skills by age for children and adolescents + int age = person.getAge(campaign.getLocalDate()); + + if (age < 16) { + person.removeAllSkills(); + // regenerate expLvl to factor in skill changes from age + expLvl = generateExperienceLevel(campaign, person); + } else if (age < 18) { + person.limitSkills(1); + + expLvl = generateExperienceLevel(campaign, person); + } + + // set SPAs + if (expLvl >= 0) { + AbstractSpecialAbilityGenerator specialAbilityGenerator = new DefaultSpecialAbilityGenerator(); + specialAbilityGenerator.setSkillPreferences(new RandomSkillPreferences()); + specialAbilityGenerator.generateSpecialAbilities(campaign, person, expLvl); + } // Do naming at the end, to ensure the keys are set generateName(campaign, person, gender); @@ -105,6 +116,25 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo person.setDaysToWaitForHealing(campaign.getCampaignOptions().getNaturalHealingWaitingPeriod()); + // set loyalty + if (expLvl <= 0) { + person.setLoyalty(Compute.d6(3) + 2); + } else if (expLvl == 1) { + person.setLoyalty(Compute.d6(3) + 1); + } else { + person.setLoyalty(Compute.d6(3)); + } + + // set education based on age + if (age < 16) { + person.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); + } else { + person.setEduHighestEducation(EducationLevel.HIGH_SCHOOL); + } + + // generate personality + PersonalityController.generatePersonality(person); + // generate background BackgroundsController.generateBackground(campaign, person); diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java index 22abbda1db..2a5c8fd715 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java @@ -28,7 +28,6 @@ import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; public class DefaultSkillGenerator extends AbstractSkillGenerator { //region Constructors @@ -62,8 +61,13 @@ public void generateSkills(final Campaign campaign, final Person person, final i // roll small arms skill if (!person.getSkills().hasSkill(SkillType.S_SMALL_ARMS)) { int sarmsLvl = Utilities.generateExpLevel( - (primaryRole.isSupport() || secondaryRole.isSupport(true)) + (primaryRole.isSupport(true) || secondaryRole.isSupport(true)) ? rskillPrefs.getSupportSmallArmsBonus() : rskillPrefs.getCombatSmallArmsBonus()); + + if (primaryRole.isCivilian()) { + sarmsLvl = 0; + } + if (sarmsLvl > SkillType.EXP_ULTRA_GREEN) { addSkill(person, SkillType.S_SMALL_ARMS, sarmsLvl, rskillPrefs.randomizeSkill(), bonus); } @@ -100,7 +104,7 @@ public void generateSkills(final Campaign campaign, final Person person, final i if (Utilities.rollProbability(rskillPrefs.getSecondSkillProb())) { final List possibleSkills = Arrays.stream(SkillType.skillList) .filter(stype -> !person.getSkills().hasSkill(stype)) - .collect(Collectors.toList()); + .toList(); String selSkill = possibleSkills.get(Compute.randomInt(possibleSkills.size())); int secondLvl = Utilities.generateExpLevel(rskillPrefs.getSecondSkillBonus()); addSkill(person, selSkill, secondLvl, rskillPrefs.randomizeSkill(), bonus); diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index ab59275b2c..aa3f525f92 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -183,25 +183,18 @@ public boolean safeSpouse(final Campaign campaign, final LocalDate today, final * @param origin the origin person being married * @param spouse the person's spouse, which can be null if no marriage is to occur * @param surnameStyle the style for how the two people's surnames will change as part of the marriage + * @param isBackground whether the marriage occurred as part of a character's background */ public void marry(final Campaign campaign, final LocalDate today, final Person origin, - final @Nullable Person spouse, final MergingSurnameStyle surnameStyle) { + final @Nullable Person spouse, final MergingSurnameStyle surnameStyle, + boolean isBackground) { if (spouse == null) { return; } - performMarriageChanges(campaign, today, origin, spouse, surnameStyle); + performMarriageChanges(campaign, today, origin, spouse, surnameStyle, isBackground); - campaign.addReport(String.format(resources.getString("marriage.report"), origin.getHyperlinkedName(), - spouse.getHyperlinkedName())); - - // Process the loyalty change - if (campaign.getCampaignOptions().isUseLoyaltyModifiers()) { - origin.performRandomizedLoyaltyChange(campaign, false, true); - spouse.performRandomizedLoyaltyChange(campaign, false, true); - } - - // And finally we trigger person changed events + // And finally, we trigger person changed events MekHQ.triggerEvent(new PersonChangedEvent(origin)); MekHQ.triggerEvent(new PersonChangedEvent(spouse)); } @@ -214,8 +207,11 @@ public void marry(final Campaign campaign, final LocalDate today, final Person o * @param origin the first person getting married * @param spouse the second person getting married * @param surnameStyle the style of surname changes to be applied + * @param isBackground whether the marriage occurred as part of a character's background */ - public static void performMarriageChanges(Campaign campaign, LocalDate today, Person origin, Person spouse, MergingSurnameStyle surnameStyle) { + public static void performMarriageChanges(Campaign campaign, LocalDate today, Person origin, + Person spouse, MergingSurnameStyle surnameStyle, + boolean isBackground) { // Immediately set both Maiden Names, to avoid any divorce bugs (as the default is now an empty string) origin.setMaidenName(origin.getSurname()); spouse.setMaidenName(spouse.getSurname()); @@ -231,13 +227,16 @@ public static void performMarriageChanges(Campaign campaign, LocalDate today, Pe PersonalLogger.marriage(origin, spouse, today); PersonalLogger.marriage(spouse, origin, today); - campaign.addReport(String.format(resources.getString("marriage.report"), origin.getHyperlinkedName(), - spouse.getHyperlinkedName())); + if (!isBackground) { + campaign.addReport(String.format(resources.getString("marriage.report"), + origin.getHyperlinkedName(), + spouse.getHyperlinkedName())); - // Process the loyalty change - if (campaign.getCampaignOptions().isUseLoyaltyModifiers()) { - origin.performRandomizedLoyaltyChange(campaign, false, true); - spouse.performRandomizedLoyaltyChange(campaign, false, true); + // Process the loyalty change + if (campaign.getCampaignOptions().isUseLoyaltyModifiers()) { + origin.performRandomizedLoyaltyChange(campaign, false, true); + spouse.performRandomizedLoyaltyChange(campaign, false, true); + } } // log the origin spouse for both partners @@ -245,7 +244,7 @@ public static void performMarriageChanges(Campaign campaign, LocalDate today, Pe spouse.getGenealogy().setOriginSpouse(origin); // recruit the spouse if they're not already in the unit - if (spouse.getJoinedCampaign() == null) { + if ((!isBackground) && (spouse.getJoinedCampaign() == null)) { campaign.recruitPerson(spouse, PrisonerStatus.FREE, true, false); ResourceBundle recruitmentResources = ResourceBundle.getBundle("mekhq.resources.Campaign", @@ -293,7 +292,34 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final isInterUnit = true; } - marryRandomSpouse(campaign, today, person, isSameSex, isInterUnit); + marryRandomSpouse(campaign, today, person, isSameSex, isInterUnit, true); + } + } + + /** + * This method is used to check for marriages that occurred in a character's background + * + * @param campaign the campaign for which to process the marriage rolls + * @param today the current date + * @param person the person for whom to process the marriage rolls + */ + public void processBackgroundMarriageRolls(final Campaign campaign, final LocalDate today, final Person person) { + if (canMarry(campaign, today, person, true) != null) { + return; + } + + if (randomMarriage(person)) { + boolean isSameSex = false; + + int sameSexDiceSize = campaign.getCampaignOptions().getRandomSameSexMarriageDiceSize(); + + if (sameSexDiceSize == 1) { + isSameSex = true; + } else if ((sameSexDiceSize != 0) && (Compute.randomInt(sameSexDiceSize) == 0)) { + isSameSex = true; + } + + marryRandomSpouse(campaign, today, person, isSameSex, false, false); } } @@ -313,9 +339,11 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final * @param person the person who is getting randomly married * @param sameSex whether the marriage is between same-sex partners * @param isInterUnit whether the marriage is to another character chosen from among potential partners already in the campaign unit. + * @param isBackground whether the marriage occurred in a character's background */ protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, - final Person person, final boolean sameSex, boolean isInterUnit) { + final Person person, final boolean sameSex, + boolean isInterUnit, boolean isBackground) { final Gender gender = sameSex ? person.getGender() : (person.getGender().isMale() ? Gender.FEMALE : Gender.MALE); @@ -336,7 +364,7 @@ protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, spouse = createExternalSpouse(campaign, today, person, gender); } - marry(campaign, today, person, spouse, MergingSurnameStyle.WEIGHTED); + marry(campaign, today, person, spouse, MergingSurnameStyle.WEIGHTED, isBackground); } /** diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 0b1cc2da3b..2b7a43ad42 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -22,6 +22,7 @@ import megamek.common.Compute; import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; +import megamek.common.options.IOption; import mekhq.MHQConstants; import mekhq.MekHQ; import mekhq.campaign.Campaign; @@ -31,19 +32,16 @@ import mekhq.campaign.log.MedicalLogger; import mekhq.campaign.log.PersonalLogger; import mekhq.campaign.personnel.Person; +import mekhq.campaign.personnel.PersonnelOptions; import mekhq.campaign.personnel.enums.FamilialRelationshipType; import mekhq.campaign.personnel.enums.GenderDescriptors; import mekhq.campaign.personnel.enums.PrisonerStatus; import mekhq.campaign.personnel.enums.RandomProcreationMethod; import mekhq.campaign.personnel.enums.education.EducationLevel; -import mekhq.campaign.personnel.randomEvents.PersonalityController; import java.time.LocalDate; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.List; -import java.util.ResourceBundle; -import java.util.UUID; +import java.util.*; /** * AbstractProcreation is the baseline class for procreation and birth in MekHQ. It holds all the @@ -359,15 +357,6 @@ public void birth(final Campaign campaign, final LocalDate today, final Person m baby.setFounder(baby.getGenealogy().getParents().stream().anyMatch(Person::isFounder)); } - // set education - baby.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); - - // set loyalty - baby.setLoyalty(Compute.d6(4, 3)); - - // set baby's personality - PersonalityController.generatePersonality(baby); - // Recruit the baby campaign.recruitPerson(baby, prisonerStatus, true, true); } @@ -408,6 +397,7 @@ private static void logAndUpdateFamily(Campaign campaign, LocalDate today, Perso // Create genealogy information baby.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, mother); mother.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, baby); + if (father != null) { baby.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, father); father.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, baby); @@ -438,19 +428,24 @@ public List birthHistoric(final Campaign campaign, final LocalDate today baby.setSurname(campaign.getCampaignOptions().getBabySurnameStyle() .generateBabySurname(mother, father, baby.getGender())); - baby.setBirthday(today); + baby.setBirthday(today);// Limit skills by age for children and adolescents - // Create reports and log the birth - logAndUpdateFamily(campaign, today, mother, baby, father); + baby.removeAllSkills(); - // set education - baby.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); + // re-roll SPAs to include in any age and skill adjustments + Enumeration options = new PersonnelOptions().getOptions(PersonnelOptions.LVL3_ADVANTAGES); + + for (IOption option : Collections.list(options)) { + baby.getOptions().getOption(option.getName()).clearValue(); + } + + baby.setLoyalty(Compute.d6(3) + 2); - // set loyalty - baby.setLoyalty(Compute.d6(4, 3)); + // set education based on age + baby.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); - // set baby's personality - PersonalityController.generatePersonality(baby); + // Create reports and log the birth + logAndUpdateFamily(campaign, today, mother, baby, father); // add to the list of babies babies.add(baby); @@ -536,8 +531,22 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final } // Make the required checks for random procreation + processRandomProcreationCheck(campaign, today, person, false); + } + + /** + * Checks if a person randomly procreates on the given day in the campaign. + * If the person does procreate, add a pregnancy to the campaign for the person. + * + * @param campaign The campaign to check procreation for. + * @param today The current date. + * @param person The person to check for procreation. + * @param isNoReport true, if the player shouldn't be informed, otherwise false + */ + public void processRandomProcreationCheck(final Campaign campaign, final LocalDate today, + final Person person, boolean isNoReport) { if (randomlyProcreates(today, person)) { - addPregnancy(campaign, today, person, false); + addPregnancy(campaign, today, person, isNoReport); } } diff --git a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java index 660f8da477..6131020336 100644 --- a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java +++ b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java @@ -46,7 +46,6 @@ import mekhq.campaign.personnel.enums.PersonnelRole; import mekhq.campaign.personnel.enums.education.EducationLevel; import mekhq.campaign.personnel.generator.AbstractPersonnelGenerator; -import mekhq.campaign.personnel.randomEvents.PersonalityController; import mekhq.campaign.personnel.ranks.Rank; import mekhq.campaign.unit.Unit; import mekhq.campaign.universe.Faction; @@ -610,8 +609,6 @@ private void finalizePersonnel(final Campaign campaign, } else { tracker.getPerson().setEduHighestEducation(EducationLevel.HIGH_SCHOOL); } - - PersonalityController.generatePersonality(tracker.getPerson()); } if (getOptions().isRunStartingSimulation()) { diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java index 7d3ccd9b79..67dbf8fc38 100644 --- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java @@ -358,7 +358,7 @@ public void actionPerformed(ActionEvent action) { gui.getCampaign().getMarriage().marry(gui.getCampaign(), gui.getCampaign().getLocalDate(), selectedPerson, gui.getCampaign().getPerson(UUID.fromString(data[1])), - MergingSurnameStyle.valueOf(data[2])); + MergingSurnameStyle.valueOf(data[2]), false); break; } case CMD_ADD_AWARD: { diff --git a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java index 287dfb363c..0c569d0242 100644 --- a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java @@ -23,13 +23,16 @@ import megamek.client.ui.preferences.PreferencesNode; import megamek.common.Compute; import megamek.common.enums.SkillLevel; +import megamek.common.options.IOption; import mekhq.MekHQ; import mekhq.campaign.Campaign; +import mekhq.campaign.RandomSkillPreferences; import mekhq.campaign.personnel.Person; +import mekhq.campaign.personnel.PersonnelOptions; import mekhq.campaign.personnel.enums.PersonnelRole; import mekhq.campaign.personnel.enums.Profession; -import mekhq.campaign.personnel.enums.education.EducationLevel; -import mekhq.campaign.personnel.randomEvents.PersonalityController; +import mekhq.campaign.personnel.generator.AbstractSpecialAbilityGenerator; +import mekhq.campaign.personnel.generator.DefaultSpecialAbilityGenerator; import mekhq.gui.CampaignGUI; import mekhq.gui.displayWrappers.RankDisplay; import org.apache.logging.log4j.LogManager; @@ -42,6 +45,8 @@ import java.awt.event.KeyListener; import java.time.LocalDate; import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.Enumeration; import java.util.Objects; import java.util.ResourceBundle; @@ -52,7 +57,7 @@ public class HireBulkPersonnelDialog extends JDialog { private static final Insets ZERO_INSETS = new Insets(0, 0, 0, 0); private static final Insets DEFAULT_INSETS = new Insets(5, 5, 5, 5); - private Campaign campaign; + private final Campaign campaign; private JComboBox choiceType; private JComboBox choiceRanks; @@ -350,25 +355,38 @@ private void hire(boolean isGmHire) { person.setBirthday(birthDay); age = person.getAge(today); } - } - // Limit skills by age for children and adolescents - if (age < 12) { - person.removeAllSkills(); - } else if (age < 14) { - person.limitSkills(0); - } else if (age < 18) { - person.limitSkills(age - 13); - } + // Limit skills by age for children and adolescents + if (age < 16) { + person.removeAllSkills(); + } else if (age < 18) { + person.limitSkills(0); + } - // set education based on age - if (age < 16) { - person.setEduHighestEducation(EducationLevel.EARLY_CHILDHOOD); - } else { - person.setEduHighestEducation(EducationLevel.HIGH_SCHOOL); + // re-roll SPAs to include in any age and skill adjustments + Enumeration options = new PersonnelOptions().getOptions(PersonnelOptions.LVL3_ADVANTAGES); + + for (IOption option : Collections.list(options)) { + person.getOptions().getOption(option.getName()).clearValue(); + } + + int experienceLevel = person.getExperienceLevel(campaign, false); + + if (experienceLevel <= 0) { + person.setLoyalty(Compute.d6(3) + 2); + } else if (experienceLevel == 1) { + person.setLoyalty(Compute.d6(3) + 1); + } else { + person.setLoyalty(Compute.d6(3)); + } + + if (experienceLevel > 0) { + AbstractSpecialAbilityGenerator specialAbilityGenerator = new DefaultSpecialAbilityGenerator(); + specialAbilityGenerator.setSkillPreferences(new RandomSkillPreferences()); + specialAbilityGenerator.generateSpecialAbilities(campaign, person, experienceLevel); + } } - PersonalityController.generatePersonality(person); if (!campaign.recruitPerson(person, isGmHire)) { number = 0; diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index ecc07bb652..d2b5b8a25f 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -233,22 +233,25 @@ public void testSafeSpouse() { @Test public void testMarry() { - doCallRealMethod().when(mockMarriage).marry(any(), any(), any(), any(), any()); + doCallRealMethod().when(mockMarriage).marry(any(), any(), any(), any(), any(), anyBoolean()); when(mockCampaign.getRankSystem()).thenReturn(mock(RankSystem.class)); doNothing().when(mockCampaign).addReport(any()); final Person origin = new Person("Origin", "Origin", mockCampaign); + origin.setJoinedCampaign(LocalDate.ofYearDay(3025, 1)); + final Person spouse = new Person("Spouse", "Spouse", mockCampaign); + spouse.setJoinedCampaign(LocalDate.ofYearDay(3025, 1)); final MergingSurnameStyle mockMergingSurnameStyle = mock(MergingSurnameStyle.class); doNothing().when(mockMergingSurnameStyle).apply(any(), any(), any(), any()); - mockMarriage.marry(mockCampaign, LocalDate.ofYearDay(3025, 1), origin, null, mockMergingSurnameStyle); + mockMarriage.marry(mockCampaign, LocalDate.ofYearDay(3025, 1), origin, null, mockMergingSurnameStyle, false); assertNull(origin.getMaidenName()); assertFalse(origin.getGenealogy().hasSpouse()); - mockMarriage.marry(mockCampaign, LocalDate.ofYearDay(3025, 1), origin, spouse, mockMergingSurnameStyle); + mockMarriage.marry(mockCampaign, LocalDate.ofYearDay(3025, 1), origin, spouse, mockMergingSurnameStyle, false); assertEquals("Origin", origin.getMaidenName()); assertEquals("Spouse", spouse.getMaidenName()); assertEquals(origin, spouse.getGenealogy().getSpouse()); @@ -260,27 +263,27 @@ public void testMarry() { @Test public void testProcessNewWeek() { doCallRealMethod().when(mockMarriage).processNewWeek(any(), any(), any()); - doNothing().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean()); + doNothing().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean(), eq(true)); final Person mockPerson = mock(Person.class); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn("Married"); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(0)).randomMarriage(any()); - verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(true)); + verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn(null); when(mockMarriage.randomMarriage(any())).thenReturn(true); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(1)).randomMarriage(any()); - verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(false)); + verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); } //region Random Marriage @Test public void testMarryRandomSpouse() { - doCallRealMethod().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(true)); + doCallRealMethod().when(mockMarriage).marryRandomSpouse(any(), any(), any(), anyBoolean(), eq(true), eq(true)); final Person mockMale = mock(Person.class); when(mockMale.getGender()).thenReturn(Gender.MALE); @@ -298,7 +301,7 @@ public void testMarryRandomSpouse() { // No Potential Spouses when(mockMarriage.isPotentialRandomSpouse(any(), any(), any(), any(), any())).thenReturn(false); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true, true); // Replace AbstractMarriage::isPotentialRandomSpouse with this simple gender comparison doAnswer(invocation -> invocation.getArgument(3, Person.class).getGender() == invocation.getArgument(4)) @@ -309,16 +312,16 @@ public void testMarryRandomSpouse() { final Person spouse = invocation.getArgument(3); assertEquals(spouse, mockFemale); return null; - }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true); + }).when(mockMarriage).marry(any(), any(), any(), any(), any(), anyBoolean()); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true, true); // Opposite sex, Female: Expect marry to be called with mockMale as the spouse doAnswer(invocation -> { final Person spouse = invocation.getArgument(3); assertEquals(spouse, mockMale); return null; - }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false, true); + }).when(mockMarriage).marry(any(), any(), any(), any(), any(), anyBoolean()); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false, true, true); // Same-sex, Male: Expect marry to be called with mockMale as the spouse when(mockPerson.getGender()).thenReturn(Gender.MALE); @@ -326,16 +329,16 @@ public void testMarryRandomSpouse() { final Person spouse = invocation.getArgument(3); assertEquals(spouse, mockMale); return null; - }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true); + }).when(mockMarriage).marry(any(), any(), any(), any(), any(), anyBoolean()); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true, true, true); // Opposite sex, Male: Expect marry to be called with mockFemale as the spouse doAnswer(invocation -> { final Person spouse = invocation.getArgument(3); assertEquals(spouse, mockFemale); return null; - }).when(mockMarriage).marry(any(), any(), any(), any(), any()); - mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false, true); + }).when(mockMarriage).marry(any(), any(), any(), any(), any(), anyBoolean()); + mockMarriage.marryRandomSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false, true, true); } @Test From 5413a64c6da19e1c5154b4c1192da5fac7b4ca3a Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 15:09:39 -0500 Subject: [PATCH 23/41] Refactored personnel generation and dialog code. Converted button variables to local scope in HireBulkPersonnelDialog to reduce class field clutter. Removed unnecessary campaign parameter from generateExperienceLevel to streamline the function signature in personnel generators. --- .../generator/AbstractPersonnelGenerator.java | 3 +-- .../generator/DefaultPersonnelGenerator.java | 6 +++--- .../mekhq/gui/dialog/HireBulkPersonnelDialog.java | 13 ++++--------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java index 7507976883..0c2b4d85ce 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java @@ -95,11 +95,10 @@ protected Person createPerson(Campaign campaign) { /** * Generates an experience level for a {@link Person}. - * @param campaign The {@link Campaign} which tracks the person. * @param person The {@link Person} being generated. * @return An integer value between {@link SkillType#EXP_ULTRA_GREEN} and {@link SkillType#EXP_ELITE}. */ - public int generateExperienceLevel(Campaign campaign, Person person) { + public int generateExperienceLevel(Person person) { int bonus = getSkillPreferences().getOverallRecruitBonus() + getSkillPreferences().getRecruitBonus(person.getPrimaryRole()); diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java index b07a39400c..83dffd4110 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java @@ -77,7 +77,7 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo person.setPrimaryRoleDirect(primaryRole); person.setSecondaryRoleDirect(secondaryRole); - int expLvl = generateExperienceLevel(campaign, person); + int expLvl = generateExperienceLevel(person); generateXp(campaign, person); @@ -94,11 +94,11 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo if (age < 16) { person.removeAllSkills(); // regenerate expLvl to factor in skill changes from age - expLvl = generateExperienceLevel(campaign, person); + expLvl = generateExperienceLevel(person); } else if (age < 18) { person.limitSkills(1); - expLvl = generateExperienceLevel(campaign, person); + expLvl = generateExperienceLevel(person); } // set SPAs diff --git a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java index 0c569d0242..5a8c24eec0 100644 --- a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java @@ -65,11 +65,6 @@ public class HireBulkPersonnelDialog extends JDialog { private JSpinner spnNumber; private JTextField jtf; - private JButton btnHire; - private JButton btnGmHire; - private JButton btnClose; - private JPanel panButtons; - private JSpinner minAge; private JSpinner maxAge; @@ -110,10 +105,10 @@ private void initComponents() { choiceType = new JComboBox<>(); choiceRanks = new JComboBox<>(); - btnHire = new JButton(resourceMap.getString("btnHire.text")); - btnGmHire = new JButton(resourceMap.getString("btnGmHire.text")); - btnClose = new JButton(resourceMap.getString("btnClose.text")); - panButtons = new JPanel(new GridBagLayout()); + JButton btnHire = new JButton(resourceMap.getString("btnHire.text")); + JButton btnGmHire = new JButton(resourceMap.getString("btnGmHire.text")); + JButton btnClose = new JButton(resourceMap.getString("btnClose.text")); + JPanel panButtons = new JPanel(new GridBagLayout()); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setName("Form"); From 76b2986641872679e8282d6d0304cfb05b75930f Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 15:10:57 -0500 Subject: [PATCH 24/41] Remove redundant test verifications for processNewWeek Eliminated unnecessary mock verifications for the `processNewWeek` method, which involved redundant calls to `randomlyProcreates` and `addPregnancy`. This cleanup simplifies the test and focuses on essential method behaviors. --- .../procreation/AbstractProcreationTest.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java index 852e05e12b..e4973151b3 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java @@ -450,7 +450,6 @@ public void testProcessPregnancyComplications() { public void testProcessNewWeek() { doCallRealMethod().when(mockProcreation).processNewWeek(any(), any(), any()); doNothing().when(mockProcreation).birth(any(), any(), any()); - doNothing().when(mockProcreation).addPregnancy(any(), any(), any(), eq(false)); final Person mockPerson = mock(Person.class); @@ -470,18 +469,6 @@ public void testProcessNewWeek() { mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockProcreation, times(1)).birth(any(), any(), any()); verify(mockProcreation, never()).randomlyProcreates(any(), any()); - - when(mockPerson.isPregnant()).thenReturn(false); - - when(mockProcreation.randomlyProcreates(any(), any())).thenReturn(false); - mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockProcreation, times(1)).birth(any(), any(), any()); - verify(mockProcreation, times(1)).randomlyProcreates(any(), any()); - - when(mockProcreation.randomlyProcreates(any(), any())).thenReturn(true); - mockProcreation.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockProcreation, times(2)).randomlyProcreates(any(), any()); - verify(mockProcreation, times(1)).addPregnancy(any(), any(), any(), eq(false)); } //region Random Procreation From b8c9a11d756ace2f19f6085f0374a4497f4917a6 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 21:43:41 -0500 Subject: [PATCH 25/41] Refactor role checking and marriage & divorce processes Added checks to prevent role assignment to children and updated multiple methods and logs to handle new conditions for marriage and divorce processing. Improved genealogical logging and fixed person recruitment reports. --- .../mekhq/resources/Campaign.properties | 3 + MekHQ/src/mekhq/campaign/Campaign.java | 74 ++++++++++++------- .../src/mekhq/campaign/personnel/Person.java | 22 +++--- .../personnel/divorce/AbstractDivorce.java | 39 ++++++---- .../personnel/marriage/AbstractMarriage.java | 29 ++++---- .../adapter/PersonnelTableMouseAdapter.java | 14 +++- MekHQ/src/mekhq/gui/view/PersonViewPanel.java | 45 +++++++++-- 7 files changed, 150 insertions(+), 76 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/Campaign.properties b/MekHQ/resources/mekhq/resources/Campaign.properties index 4f99d2dde7..e48ef36fce 100644 --- a/MekHQ/resources/mekhq/resources/Campaign.properties +++ b/MekHQ/resources/mekhq/resources/Campaign.properties @@ -75,6 +75,9 @@ divorce.text=%s has divorced %s. #### Unsorted Campaign Resources dependentLeavesForce.text=%s is no longer travelling with the force, and is thus no longer dependent on it. dependentJoinsForce.text=%s has started traveling with the force, and is now dependent on it. +relativeJoinsForce.text=%s, %s's %s, has started traveling with the force, and is now dependent on it. +relativeJoinsForceSpouse.text=spouse +relativeJoinsForceChild.text=child bonusPartLog.text=Bonus part used to acquire 1x newAtBScenario.format=New scenario "{0}" will occur on {1}. atbScenarioToday.format=Scenario "{0}" is today, deploy a force from your TOE! diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index aa786f51b2..2d2c691469 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -1576,31 +1576,29 @@ private void simulateRelationshipHistory(Person person) { // run the simulation for (long weeksRemaining = weeksBetween; weeksRemaining >= 0; weeksRemaining--) { - LocalDate currentDate = getLocalDate().plusWeeks(weeksRemaining); - - logger.info(weeksRemaining); + LocalDate currentDate = getLocalDate().minusWeeks(weeksRemaining); // first, we check for old relationships ending and new relationships beginning if (currentSpouse != null) { - logger.info("relationship ending roll"); - getDivorce().processNewWeek(this, currentDate, person); + getDivorce().processNewWeek(this, currentDate, person, true); - List toRemove = new ArrayList<>(); + if (!person.getGenealogy().hasSpouse()) { + List toRemove = new ArrayList<>(); - // there is a chance a departing spouse might take some of their children with them - for (Person child : children) { - if (child.getGenealogy().getParents().contains(currentSpouse)) { - if (Compute.randomInt(2) == 0) { - toRemove.add(child); + // there is a chance a departing spouse might take some of their children with them + for (Person child : children) { + if (child.getGenealogy().getParents().contains(currentSpouse)) { + if (Compute.randomInt(2) == 0) { + toRemove.add(child); + } } } - } - children.removeAll(toRemove); + children.removeAll(toRemove); - currentSpouse = null; + currentSpouse = null; + } } else { - logger.info("relationship starting roll"); getMarriage().processBackgroundMarriageRolls(this, currentDate, person); if (person.getGenealogy().hasSpouse()) { @@ -1608,33 +1606,48 @@ private void simulateRelationshipHistory(Person person) { } } - logger.info(currentSpouse); - // then we check for children if (person.getGender().isFemale()) { - logger.info("rolling for Person pregnancy"); getProcreation().processRandomProcreationCheck(this, localDate.minusWeeks(weeksRemaining), person, true); if (person.isPregnant()) { - children.addAll(getProcreation().birthHistoric(this, person.getDueDate(), person, null)); + + Person father = null; + + if ((currentSpouse != null) && (currentSpouse.getGender().isMale())) { + father = currentSpouse; + } + + children.addAll(getProcreation().birthHistoric(this, person.getDueDate(), person, father)); } } if ((currentSpouse != null) && (currentSpouse.getGender().isFemale())) { - logger.info("rolling for Spouse pregnancy"); getProcreation().processRandomProcreationCheck(this, localDate.minusWeeks(weeksRemaining), person, true); if (person.isPregnant()) { - getProcreation().birthHistoric(this, person.getDueDate(), person, null); + + Person father = null; + + if (person.getGender().isMale()) { + father = currentSpouse; + } + + getProcreation().birthHistoric(this, person.getDueDate(), person, father); } } } - logger.info("simulation has ended for {}", person.getFullTitle()); - // with the simulation concluded, we add the current spouse (if any) and any remaining children to the unit if (currentSpouse != null) { - recruitPerson(currentSpouse, PrisonerStatus.FREE, true, true); + recruitPerson(currentSpouse, PrisonerStatus.FREE, true, false); + + addReport(String.format(resources.getString("relativeJoinsForce.text"), + currentSpouse.getHyperlinkedFullTitle(), + person.getHyperlinkedFullTitle(), + resources.getString("relativeJoinsForceSpouse.text"))); + + MekHQ.triggerEvent(new PersonChangedEvent(currentSpouse)); } for (Person child : children) { @@ -1674,8 +1687,17 @@ private void simulateRelationshipHistory(Person person) { specialAbilityGenerator.generateSpecialAbilities(this, child, experienceLevel); } - recruitPerson(child, PrisonerStatus.FREE, true, true); + recruitPerson(child, PrisonerStatus.FREE, true, false); + + addReport(String.format(resources.getString("relativeJoinsForce.text"), + child.getHyperlinkedFullTitle(), + person.getHyperlinkedFullTitle(), + resources.getString("relativeJoinsForceChild.text"))); + + MekHQ.triggerEvent(new PersonChangedEvent(child)); } + + MekHQ.triggerEvent(new PersonChangedEvent(person)); } //endregion Personnel Recruitment @@ -3600,7 +3622,7 @@ public void processNewDayPersonnel() { // Divorce, Marriage, & Procreation if (getLocalDate().getDayOfWeek() == DayOfWeek.MONDAY) { - getDivorce().processNewWeek(this, getLocalDate(), person); + getDivorce().processNewWeek(this, getLocalDate(), person, false); getMarriage().processNewWeek(this, getLocalDate(), person); getProcreation().processNewWeek(this, getLocalDate(), person); } diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java index 1b67289316..5a1cb12120 100644 --- a/MekHQ/src/mekhq/campaign/personnel/Person.java +++ b/MekHQ/src/mekhq/campaign/personnel/Person.java @@ -860,7 +860,7 @@ public String getSecondaryRoleDesc() { return getSecondaryRole().getName(isClanPersonnel()); } - public boolean canPerformRole(final PersonnelRole role, final boolean primary) { + public boolean canPerformRole(LocalDate today, Person person, final PersonnelRole role, final boolean primary) { if (primary) { // Primary Role: // We only do a few here, as it is better on the UX-side to correct the issues when @@ -895,6 +895,10 @@ public boolean canPerformRole(final PersonnelRole role, final boolean primary) { } } + if (person.isChild(today)) { + return false; + } + return switch (role) { case MECHWARRIOR -> hasSkill(SkillType.S_GUN_MECH) && hasSkill(SkillType.S_PILOT_MECH); case LAM_PILOT -> @@ -2126,7 +2130,7 @@ public void writeToXML(final PrintWriter pw, int indent, final Campaign campaign extraData.writeToXml(pw); } } catch (Exception ex) { - logger.error("Failed to write " + getFullName() + " to the XML File", ex); + logger.error("Failed to write {} to the XML File", getFullName(), ex); throw ex; // we want to rethrow to ensure that the save fails } @@ -2317,7 +2321,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("id")) { - logger.error("Unknown node type not loaded in techUnitIds nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in techUnitIds nodes: {}", wn3.getNodeName()); continue; } retVal.addTechUnit(new PersonUnitRef(UUID.fromString(wn3.getTextContent()))); @@ -2332,7 +2336,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("logEntry")) { - logger.error("Unknown node type not loaded in personnel log nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in personnel log nodes: {}", wn3.getNodeName()); continue; } @@ -2352,7 +2356,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("logEntry")) { - logger.error("Unknown node type not loaded in scenario log nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in scenario log nodes: {}", wn3.getNodeName()); continue; } @@ -2371,7 +2375,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("award")) { - logger.error("Unknown node type not loaded in personnel log nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in personnel log nodes: {}", wn3.getNodeName()); continue; } @@ -2388,7 +2392,7 @@ public static Person generateInstanceFromXML(Node wn, Campaign c, Version versio } if (!wn3.getNodeName().equalsIgnoreCase("injury")) { - logger.error("Unknown node type not loaded in injury nodes: " + wn3.getNodeName()); + logger.error("Unknown node type not loaded in injury nodes: {}", wn3.getNodeName()); continue; } retVal.injuries.add(Injury.generateInstanceFromXML(wn3)); @@ -2933,7 +2937,7 @@ public int getExperienceLevel(final Campaign campaign, final boolean secondary) return SkillType.EXP_NONE; } } - case VEHICLE_CREW: + case VEHICLE_CREW, MECHANIC: return hasSkill(SkillType.S_TECH_MECHANIC) ? getSkill(SkillType.S_TECH_MECHANIC).getExperienceLevel() : SkillType.EXP_NONE; case AEROSPACE_PILOT: if (hasSkill(SkillType.S_GUN_AERO) && hasSkill(SkillType.S_PILOT_AERO)) { @@ -3000,8 +3004,6 @@ public int getExperienceLevel(final Campaign campaign, final boolean secondary) return hasSkill(SkillType.S_NAV) ? getSkill(SkillType.S_NAV).getExperienceLevel() : SkillType.EXP_NONE; case MECH_TECH: return hasSkill(SkillType.S_TECH_MECH) ? getSkill(SkillType.S_TECH_MECH).getExperienceLevel() : SkillType.EXP_NONE; - case MECHANIC: - return hasSkill(SkillType.S_TECH_MECHANIC) ? getSkill(SkillType.S_TECH_MECHANIC).getExperienceLevel() : SkillType.EXP_NONE; case AERO_TECH: return hasSkill(SkillType.S_TECH_AERO) ? getSkill(SkillType.S_TECH_AERO).getExperienceLevel() : SkillType.EXP_NONE; case BA_TECH: diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 3be0170165..92211d3ef0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -300,19 +300,13 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person MekHQ.triggerEvent(new PersonChangedEvent(origin)); } - /** - * This divorces two married people. - * This version is meant to be used to log historic divorces that occur during a characters' random background. - * It is a watered down version of divorce() - * - * @param campaign the campaign the two people are a part of - * @param today the current date - * @param origin the origin person being divorced - */ - public void divorceHistoric(final Campaign campaign, final LocalDate today, final Person origin) { + public void backgroundDivorce(final Campaign campaign, final LocalDate today, final Person origin, + final SplittingSurnameStyle style) { final Person spouse = origin.getGenealogy().getSpouse(); - SplittingSurnameStyle.WEIGHTED.apply(campaign, origin, spouse); + style.apply(campaign, origin, spouse); + + final FormerSpouseReason reason = FormerSpouseReason.DIVORCE; PersonalLogger.divorcedFrom(origin, spouse, today); PersonalLogger.divorcedFrom(spouse, origin, today); @@ -323,8 +317,18 @@ public void divorceHistoric(final Campaign campaign, final LocalDate today, fina spouse.getGenealogy().setSpouse(null); origin.getGenealogy().setSpouse(null); - spouse.getGenealogy().addFormerSpouse(new FormerSpouse(origin, today, FormerSpouseReason.DIVORCE)); - origin.getGenealogy().addFormerSpouse(new FormerSpouse(spouse, today, FormerSpouseReason.DIVORCE)); + // Add to the former spouse list + spouse.getGenealogy().addFormerSpouse(new FormerSpouse(origin, today, reason)); + origin.getGenealogy().addFormerSpouse(new FormerSpouse(spouse, today, reason)); + + // Clear origin spouses + origin.getGenealogy().setOriginSpouse(null); + spouse.getGenealogy().setOriginSpouse(null); + + // roll for removal of marriageable flag + if (Compute.d6(1) <= 2) { + origin.setMarriageable(false); + } } //region New Day @@ -333,14 +337,19 @@ public void divorceHistoric(final Campaign campaign, final LocalDate today, fina * @param campaign the campaign to process * @param today the current day * @param person the person to process + * @param isBackground whether the divorce occurred during a character's backstory */ - public void processNewWeek(final Campaign campaign, final LocalDate today, final Person person) { + public void processNewWeek(final Campaign campaign, final LocalDate today, final Person person, boolean isBackground) { if (canDivorce(person, true) != null) { return; } if (randomDivorce(person)) { - divorce(campaign, today, person, SplittingSurnameStyle.WEIGHTED); + if (isBackground) { + backgroundDivorce(campaign, today, person, SplittingSurnameStyle.WEIGHTED); + } else { + divorce(campaign, today, person, SplittingSurnameStyle.WEIGHTED); + } } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index aa3f525f92..e8a5e3dbfe 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -240,7 +240,7 @@ public static void performMarriageChanges(Campaign campaign, LocalDate today, Pe } // log the origin spouse for both partners - origin.getGenealogy().setOriginSpouse(spouse); + origin.getGenealogy().setOriginSpouse(origin); spouse.getGenealogy().setOriginSpouse(origin); // recruit the spouse if they're not already in the unit @@ -319,7 +319,7 @@ public void processBackgroundMarriageRolls(final Campaign campaign, final LocalD isSameSex = true; } - marryRandomSpouse(campaign, today, person, isSameSex, false, false); + marryRandomSpouse(campaign, today, person, isSameSex, false, true); } } @@ -379,21 +379,22 @@ protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, Person createExternalSpouse(final Campaign campaign, final LocalDate today, final Person person, Gender gender) { Person externalSpouse = campaign.newDependent(false, gender); - // Adjust the birthday until it's within the correct age range + + // Calculate person's age and the maximum and minimum allowable spouse ages int personAge = person.getAge(today); - int ageDifference = campaign.getCampaignOptions().getRandomMarriageAgeRange(); + int externalSpouseAge = externalSpouse.getAge(today); + int maximumAgeDifference = campaign.getCampaignOptions().getRandomMarriageAgeRange(); + int externalSpouseMinAge = Math.max (18, personAge - maximumAgeDifference); + int externalSpouseMaxAge = personAge + maximumAgeDifference; - if (externalSpouse.getAge(today) < (personAge - ageDifference)) { - externalSpouse.setBirthday(today.plusYears(1)); - } else { - while ((!externalSpouse.isChild(today)) && (externalSpouse.getAge(today) < (personAge - ageDifference))) { - externalSpouse.setBirthday(today.minusYears(1)); - } - } + if (externalSpouseAge < externalSpouseMinAge) { + int difference = externalSpouseMinAge - externalSpouseAge; + + externalSpouse.setBirthday(externalSpouse.getBirthday().minusYears(difference)); + } else if (externalSpouseAge > externalSpouseMaxAge) { + int difference = externalSpouseMaxAge - externalSpouseAge; - // Make sure the spouse is not a child - while (externalSpouse.isChild(today)) { - externalSpouse.setBirthday(today.plusYears(1)); + externalSpouse.setBirthday(externalSpouse.getBirthday().plusYears(difference)); } return externalSpouse; diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java index 67dbf8fc38..2b7b4e8ea0 100644 --- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java @@ -353,6 +353,7 @@ public void actionPerformed(ActionEvent action) { .forEach(person -> gui.getCampaign().getDivorce().divorce(gui.getCampaign(), gui.getCampaign().getLocalDate(), person, SplittingSurnameStyle.valueOf(data[1]))); + break; } case CMD_ADD_SPOUSE: { gui.getCampaign().getMarriage().marry(gui.getCampaign(), @@ -1400,8 +1401,9 @@ protected Optional createPopupMenu() { final PersonnelRole[] roles = PersonnelRole.values(); menu = new JMenu(resources.getString("changePrimaryRole.text")); + for (final PersonnelRole role : roles) { - if (person.canPerformRole(role, true)) { + if (person.canPerformRole(gui.getCampaign().getLocalDate(), person, role, true)) { cbMenuItem = new JCheckBoxMenuItem(role.getName(person.isClanPersonnel())); cbMenuItem.setActionCommand(makeCommand(CMD_PRIMARY_ROLE, role.name())); cbMenuItem.setSelected(person.getPrimaryRole() == role); @@ -1413,7 +1415,7 @@ protected Optional createPopupMenu() { menu = new JMenu(resources.getString("changeSecondaryRole.text")); for (final PersonnelRole role : roles) { - if (person.canPerformRole(role, false)) { + if (person.canPerformRole(gui.getCampaign().getLocalDate(), person, role, false)) { cbMenuItem = new JCheckBoxMenuItem(role.getName(person.isClanPersonnel())); cbMenuItem.setActionCommand(makeCommand(CMD_SECONDARY_ROLE, role.name())); cbMenuItem.setSelected(person.getSecondaryRole() == role); @@ -1441,6 +1443,9 @@ protected Optional createPopupMenu() { JMenuHelpers.addMenuIfNonEmpty(popup, new AssignPersonToUnitMenu(gui.getCampaign(), selected)); + LogManager.getLogger().info(gui.getCampaign().getMarriage().canMarry(gui.getCampaign(), + gui.getCampaign().getLocalDate(), person, false)); + if (oneSelected && person.getStatus().isActive()) { if (gui.getCampaign().getCampaignOptions().isUseManualMarriages() && (gui.getCampaign().getMarriage().canMarry(gui.getCampaign(), @@ -1496,7 +1501,10 @@ protected Optional createPopupMenu() { } } - if (gui.getCampaign().getCampaignOptions().isUseManualDivorce() && Stream.of(selected).anyMatch(p -> gui.getCampaign().getDivorce().canDivorce(person, false) == null)) { + if (gui.getCampaign().getCampaignOptions().isUseManualDivorce() && (Stream.of(selected) + .anyMatch(p -> gui.getCampaign() + .getDivorce() + .canDivorce(person, false) == null))) { menu = new JMenu(resources.getString("removeSpouse.text")); for (final SplittingSurnameStyle style : SplittingSurnameStyle.values()) { diff --git a/MekHQ/src/mekhq/gui/view/PersonViewPanel.java b/MekHQ/src/mekhq/gui/view/PersonViewPanel.java index 4adaa66ee3..734f6043bc 100644 --- a/MekHQ/src/mekhq/gui/view/PersonViewPanel.java +++ b/MekHQ/src/mekhq/gui/view/PersonViewPanel.java @@ -954,7 +954,7 @@ private JPanel fillFamily() { lblSpouse2.setName("lblSpouse2"); lblSpouse1.setLabelFor(lblSpouse2); - lblSpouse2.setText(String.format("%s", spouse.getHyperlinkedName())); + lblSpouse2.setText(String.format("%s", spouse.getHyperlinkedFullTitle())); lblSpouse2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); lblSpouse2.addMouseListener(new MouseAdapter() { @Override @@ -986,6 +986,8 @@ public void mouseClicked(MouseEvent e) { for (FormerSpouse formerSpouse : person.getGenealogy().getFormerSpouses()) { Person ex = formerSpouse.getFormerSpouse(); + String name = getRelativeName(ex); + gridBagConstraints.gridy = firsty; lblFormerSpouses2 = new JLabel(); lblFormerSpouses2.setName("lblFormerSpouses2"); @@ -994,7 +996,7 @@ public void mouseClicked(MouseEvent e) { ); lblFormerSpouses2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); lblFormerSpouses2.setText(String.format("%s, %s, %s", - ex.getFullName(), formerSpouse.getReason(), + name, formerSpouse.getReason(), MekHQ.getMHQOptions().getDisplayFormattedDate(formerSpouse.getDate()))); lblFormerSpouses2.addMouseListener(new MouseAdapter() { @Override @@ -1024,6 +1026,8 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.insets = new Insets(0, 10, 0, 0); for (Person child : children) { + String name = getRelativeName(child); + gridBagConstraints.gridy = firsty; lblChildren2 = new JLabel(); lblChildren2.setName("lblChildren2"); @@ -1031,7 +1035,7 @@ public void mouseClicked(MouseEvent e) { new AccessibleRelation(AccessibleRelation.LABELED_BY, lblChildren1) ); lblChildren2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - lblChildren2.setText(String.format("%s", child.getFullName())); + lblChildren2.setText(String.format("%s", name)); lblChildren2.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -1062,6 +1066,8 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; for (Person grandchild : grandchildren) { + String name = getRelativeName(grandchild); + gridBagConstraints.gridy = firsty; lblGrandchildren2 = new JLabel(); lblGrandchildren2.setName("lblGrandchildren2"); @@ -1069,7 +1075,7 @@ public void mouseClicked(MouseEvent e) { new AccessibleRelation(AccessibleRelation.LABELED_BY, lblGrandchildren1) ); lblGrandchildren2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - lblGrandchildren2.setText(String.format("%s", grandchild.getFullName())); + lblGrandchildren2.setText(String.format("%s", name)); lblGrandchildren2.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -1128,8 +1134,10 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; for (Person sibling : siblings) { + String name = getRelativeName(sibling); + gridBagConstraints.gridy = firsty; - lblSiblings2 = new JLabel(String.format("%s", sibling.getHyperlinkedName())); + lblSiblings2 = new JLabel(String.format("%s", name)); lblSiblings2.setName("lblSiblings2"); lblSiblings2.getAccessibleContext().getAccessibleRelationSet().add( new AccessibleRelation(AccessibleRelation.LABELED_BY, lblSiblings1)); @@ -1165,9 +1173,11 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; for (Person grandparent : grandparents) { + String name = getRelativeName(grandparent); + gridBagConstraints.gridy = firsty; lblGrandparents2 = new JLabel(String.format("%s", - grandparent.getHyperlinkedName())); + name)); lblGrandparents2.setName("lblGrandparents2"); lblGrandparents2.getAccessibleContext().getAccessibleRelationSet().add( new AccessibleRelation(AccessibleRelation.LABELED_BY, lblGrandparents1)); @@ -1202,9 +1212,11 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; for (Person auntOrUncle : auntsAndUncles) { + String name = getRelativeName(auntOrUncle); + gridBagConstraints.gridy = firsty; lblAuntsOrUncles2 = new JLabel(String.format("%s", - auntOrUncle.getHyperlinkedName())); + name)); lblAuntsOrUncles2.setName("lblAuntsOrUncles2"); lblAuntsOrUncles2.getAccessibleContext().getAccessibleRelationSet().add( new AccessibleRelation(AccessibleRelation.LABELED_BY, lblAuntsOrUncles1)); @@ -1240,13 +1252,15 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; for (Person cousin : cousins) { + String name = getRelativeName(cousin); + gridBagConstraints.gridy = firsty; lblCousins2 = new JLabel(); lblCousins2.setName("lblCousins2"); lblCousins2.getAccessibleContext().getAccessibleRelationSet().add( new AccessibleRelation(AccessibleRelation.LABELED_BY, lblCousins1)); lblCousins2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - lblCousins2.setText(String.format("%s", cousin.getHyperlinkedName())); + lblCousins2.setText(String.format("%s", name)); lblCousins2.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -1262,6 +1276,21 @@ public void mouseClicked(MouseEvent e) { return pnlFamily; } + /** + * If the relative has joined the campaign, the hyperlinked full title is returned. + * Otherwise, the full name of the relative is returned. + * + * @param relative The relative. + * @return The relative's name. + */ + private static String getRelativeName(Person relative) { + if (relative.getJoinedCampaign() == null) { + return relative.getFirstName() + " (Absent)"; + } else { + return relative.getHyperlinkedFullTitle(); + } + } + private JPanel fillSkills() { // skill panel JPanel pnlSkills = new JPanel(new GridBagLayout()); From 6999be049dfbb0a29f81325f91519e1dc3fa9489 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 22:02:12 -0500 Subject: [PATCH 26/41] Remove minimum marriage age option and update marriage checks Removed the configuration option for setting a minimum marriage age from the campaign settings, and updated the marriage eligibility checks to use a fixed age limit instead. This simplification reduces complexity in multiple areas of the codebase, making marriage-related logic more consistent and maintainable. --- .../resources/mekhq/resources/GUI.properties | 2 +- MekHQ/src/mekhq/campaign/CampaignOptions.java | 71 +++++++------------ .../personnel/marriage/AbstractMarriage.java | 11 ++- .../adapter/PersonnelTableMouseAdapter.java | 10 ++- .../mekhq/gui/panes/CampaignOptionsPane.java | 56 +++++---------- .../marriage/AbstractMarriageTest.java | 54 +++++++------- 6 files changed, 82 insertions(+), 122 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties index 1acfbbfa52..863f0d5446 100644 --- a/MekHQ/resources/mekhq/resources/GUI.properties +++ b/MekHQ/resources/mekhq/resources/GUI.properties @@ -206,7 +206,7 @@ miFounder.toolTipText=If this is selected, then the person is a founding member miImmortal.text=Immortal miImmortal.toolTipText=If this is selected, then the person will not be processed during random death \n(standard checks still apply) miMarriageable.text=Marriageable -miMarriageable.toolTipText=If this is selected, then the person will be included as a potential spouse for marriages (married personnel will not be included even if this flag is selected, nor will characters under %s years old) +miMarriageable.toolTipText=If this is selected, then the person will be included as a potential spouse for marriages (married personnel will not be included even if this flag is selected, nor will characters under 18 years old) miTryingToConceive.text=Trying to Conceive miTryingToConceive.toolTipText=If this is selected, the person has a chance to have children created through random procreation (this flag is ignored for personnel under 18 years old). diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index d2cc6a6367..7e4203353f 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -57,7 +57,7 @@ public class CampaignOptions { public static final int TECH_ADVANCED = 2; public static final int TECH_EXPERIMENTAL = 3; public static final int TECH_UNOFFICIAL = 4; - // This must always be the highest tech level in order to hide parts + // This must always be the highest tech level to hide parts // that haven't been invented yet, or that are completely extinct public static final int TECH_UNKNOWN = 5; @@ -292,7 +292,6 @@ public static String getTransitUnitName(final int unit) { private boolean useManualMarriages; private boolean useClanPersonnelMarriages; private boolean usePrisonerMarriages; - private int minimumMarriageAge; private int checkMutualAncestorsDepth; private boolean logMarriageNameChanges; private Map marriageSurnameWeights; @@ -849,7 +848,6 @@ public CampaignOptions() { setUseManualMarriages(true); setUseClanPersonnelMarriages(false); setUsePrisonerMarriages(true); - setMinimumMarriageAge(16); setCheckMutualAncestorsDepth(4); setLogMarriageNameChanges(false); setMarriageSurnameWeights(new HashMap<>()); @@ -894,7 +892,7 @@ public CampaignOptions() { setUseManualProcreation(true); setUseClanPersonnelProcreation(false); setUsePrisonerProcreation(true); - setMultiplePregnancyOccurrences(50); // Hellin's Law is 89, but we make it more common so it shows up more + setMultiplePregnancyOccurrences(50); // Hellin's Law is 89, but we make it more common, so it shows up more setBabySurnameStyle(BabySurnameStyle.MOTHERS); setAssignNonPrisonerBabiesFounderTag(false); setAssignChildrenOfFoundersFounderTag(false); @@ -1600,7 +1598,7 @@ public void setFatigueLeaveThreshold(final Integer fatigueLeaveThreshold) { //region Expanded Personnel Information /** - * @return whether or not to use time in service + * @return whether to use time in service */ public boolean isUseTimeInService() { return useTimeInService; @@ -1628,14 +1626,14 @@ public void setTimeInServiceDisplayFormat(final TimeInDisplayFormat timeInServic } /** - * @return whether or not to use time in rank + * @return whether to use time in rank */ public boolean isUseTimeInRank() { return useTimeInRank; } /** - * @param useTimeInRank the new value for whether or not to use time in rank + * @param useTimeInRank the new value for whether to use time in rank */ public void setUseTimeInRank(final boolean useTimeInRank) { this.useTimeInRank = useTimeInRank; @@ -1656,28 +1654,28 @@ public void setTimeInRankDisplayFormat(final TimeInDisplayFormat timeInRankDispl } /** - * @return whether or not to track the total earnings of personnel + * @return whether to track the total earnings of personnel */ public boolean isTrackTotalEarnings() { return trackTotalEarnings; } /** - * @param trackTotalEarnings the new value for whether or not to track total earnings for personnel + * @param trackTotalEarnings the new value for whether to track total earnings for personnel */ public void setTrackTotalEarnings(final boolean trackTotalEarnings) { this.trackTotalEarnings = trackTotalEarnings; } /** - * @return whether or not to track the total experience earnings of personnel + * @return whether to track the total experience earnings of personnel */ public boolean isTrackTotalXPEarnings() { return trackTotalXPEarnings; } /** - * @param trackTotalXPEarnings the new value for whether or not to track total experience + * @param trackTotalXPEarnings the new value for whether to track total experience * earnings for personnel */ public void setTrackTotalXPEarnings(final boolean trackTotalXPEarnings) { @@ -1685,7 +1683,7 @@ public void setTrackTotalXPEarnings(final boolean trackTotalXPEarnings) { } /** - * Gets a value indicating whether or not to show a person's origin faction when displaying + * Gets a value indicating whether to show a person's origin faction when displaying * their details. */ public boolean isShowOriginFaction() { @@ -1693,7 +1691,7 @@ public boolean isShowOriginFaction() { } /** - * Sets a value indicating whether or not to show a person's origin faction when displaying + * Sets a value indicating whether to show a person's origin faction when displaying * their details. */ public void setShowOriginFaction(final boolean showOriginFaction) { @@ -2281,14 +2279,14 @@ public void setRoleBaseSalary(final PersonnelRole role, final Money baseSalary) //region Marriage /** - * @return whether or not to use manual marriages + * @return whether to use manual marriages */ public boolean isUseManualMarriages() { return useManualMarriages; } /** - * @param useManualMarriages whether or not to use manual marriages + * @param useManualMarriages whether to use manual marriages */ public void setUseManualMarriages(final boolean useManualMarriages) { this.useManualMarriages = useManualMarriages; @@ -2310,20 +2308,6 @@ public void setUsePrisonerMarriages(final boolean usePrisonerMarriages) { this.usePrisonerMarriages = usePrisonerMarriages; } - /** - * @return the minimum age a person can get married at - */ - public int getMinimumMarriageAge() { - return minimumMarriageAge; - } - - /** - * @param minimumMarriageAge the minimum age a person can get married at - */ - public void setMinimumMarriageAge(final int minimumMarriageAge) { - this.minimumMarriageAge = minimumMarriageAge; - } - /** * This gets the number of recursions to use when checking mutual ancestors between two personnel * @return the number of recursions to use @@ -2341,7 +2325,7 @@ public void setCheckMutualAncestorsDepth(final int checkMutualAncestorsDepth) { } /** - * @return whether or not to log a name change in a marriage + * @return whether to log a name change in a marriage */ public boolean isLogMarriageNameChanges() { return logMarriageNameChanges; @@ -2377,7 +2361,7 @@ public void setRandomMarriageMethod(final RandomMarriageMethod randomMarriageMet } /** - * @return whether or not to use random same-sex marriages + * @return whether to use random same-sex marriages */ @Deprecated public boolean isUseRandomSameSexMarriages() { @@ -2385,7 +2369,7 @@ public boolean isUseRandomSameSexMarriages() { } /** - * @param useRandomSameSexMarriages whether or not to use random same-sex marriages + * @param useRandomSameSexMarriages whether to use random same-sex marriages */ @Deprecated public void setUseRandomSameSexMarriages(final boolean useRandomSameSexMarriages) { @@ -2581,7 +2565,7 @@ public void setUsePrisonerProcreation(final boolean usePrisonerProcreation) { } /** - * @return the X occurrences for there to be a single multiple child occurrence (i.e. 1 in X) + * @return the X occurrences for there to be a single multiple child occurrence (i.e., 1 in X) */ public int getMultiplePregnancyOccurrences() { return multiplePregnancyOccurrences; @@ -2589,7 +2573,7 @@ public int getMultiplePregnancyOccurrences() { /** * @param multiplePregnancyOccurrences the number of occurrences for there to be a single - * occurrence of a multiple child pregnancy (i.e. 1 in X) + * occurrence of a multiple child pregnancy (i.e., 1 in X) */ public void setMultiplePregnancyOccurrences(final int multiplePregnancyOccurrences) { this.multiplePregnancyOccurrences = multiplePregnancyOccurrences; @@ -2626,14 +2610,14 @@ public void setAssignChildrenOfFoundersFounderTag(final boolean assignChildrenOf } /** - * @return whether or not to determine the father at birth instead of at conception + * @return whether to determine the father at birth instead of at conception */ public boolean isDetermineFatherAtBirth() { return determineFatherAtBirth; } /** - * @param determineFatherAtBirth whether or not to determine the father at birth instead of at conception + * @param determineFatherAtBirth whether to determine the father at birth instead of at conception */ public void setDetermineFatherAtBirth(final boolean determineFatherAtBirth) { this.determineFatherAtBirth = determineFatherAtBirth; @@ -2676,14 +2660,14 @@ public void setRandomProcreationMethod(final RandomProcreationMethod randomProcr } /** - * @return whether or not to use random procreation for personnel without a spouse + * @return whether to use random procreation for personnel without a spouse */ public boolean isUseRelationshiplessRandomProcreation() { return useRelationshiplessRandomProcreation; } /** - * @param useRelationshiplessRandomProcreation whether or not to use random procreation without a spouse + * @param useRelationshiplessRandomProcreation whether to use random procreation without a spouse */ public void setUseRelationshiplessRandomProcreation(final boolean useRelationshiplessRandomProcreation) { this.useRelationshiplessRandomProcreation = useRelationshiplessRandomProcreation; @@ -3259,14 +3243,14 @@ public void setFinancialYearDuration(final FinancialYearDuration financialYearDu } /** - * @return whether or not to export finances to CSV at the end of a financial year + * @return whether to export finances to CSV at the end of a financial year */ public boolean isNewFinancialYearFinancesToCSVExport() { return newFinancialYearFinancesToCSVExport; } /** - * @param newFinancialYearFinancesToCSVExport whether or not to export finances to CSV at the end of a financial year + * @param newFinancialYearFinancesToCSVExport whether to export finances to CSV at the end of a financial year */ public void setNewFinancialYearFinancesToCSVExport(final boolean newFinancialYearFinancesToCSVExport) { this.newFinancialYearFinancesToCSVExport = newFinancialYearFinancesToCSVExport; @@ -4777,7 +4761,6 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useManualMarriages", isUseManualMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useClanPersonnelMarriages", isUseClanPersonnelMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "usePrisonerMarriages", isUsePrisonerMarriages()); - MHQXMLUtility.writeSimpleXMLTag(pw, indent, "minimumMarriageAge", getMinimumMarriageAge()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "checkMutualAncestorsDepth", getCheckMutualAncestorsDepth()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "logMarriageNameChanges", isLogMarriageNameChanges()); MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "marriageSurnameWeights"); @@ -5335,7 +5318,7 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve } else if (wn2.getNodeName().equalsIgnoreCase("prisonerCaptureStyle")) { retVal.setPrisonerCaptureStyle(PrisonerCaptureStyle.valueOf(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("defaultPrisonerStatus")) { - // Most of this is legacy - 0.47.X Removal + // Most of this is legacy handlers - 0.47.X Removal String prisonerStatus = wn2.getTextContent().trim(); try { @@ -5490,8 +5473,6 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUseClanPersonnelMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("usePrisonerMarriages")) { retVal.setUsePrisonerMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); - } else if (wn2.getNodeName().equalsIgnoreCase("minimumMarriageAge")) { - retVal.setMinimumMarriageAge(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("checkMutualAncestorsDepth")) { retVal.setCheckMutualAncestorsDepth(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("logMarriageNameChanges")) { @@ -6199,7 +6180,7 @@ public void migrateMarriageSurnameWeights47(final String... values) { } } - // Now we need to test to figure out the weights have changed. If not, we will keep the + // Now we need to test it to figure out the weights have changed. If not, we will keep the // new default values. If they have, we save their changes and add the new surname weights if ( (weights[0] != getMarriageSurnameWeights().get(MergingSurnameStyle.NO_CHANGE)) diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index e8a5e3dbfe..d7df2c46a0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -118,8 +118,7 @@ public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriag * @param randomMarriage if this is for random marriage or manual marriage * @return null if they can, otherwise the reason why they cannot */ - public @Nullable String canMarry(final Campaign campaign, final LocalDate today, - final Person person, final boolean randomMarriage) { + public @Nullable String canMarry(final LocalDate today, final Person person, final boolean randomMarriage) { if (!person.isMarriageable()) { return resources.getString("cannotMarry.NotMarriageable.text"); } else if (person.getGenealogy().hasSpouse()) { @@ -128,7 +127,7 @@ public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriag return resources.getString("cannotMarry.Inactive.text"); } else if (person.isDeployed()) { return resources.getString("cannotMarry.Deployed.text"); - } else if (person.getAge(today) < campaign.getCampaignOptions().getMinimumMarriageAge()) { + } else if (person.isChild(today)) { return resources.getString("cannotMarry.TooYoung.text"); } else if (!isUseClanPersonnelMarriages() && person.isClanPersonnel()) { return resources.getString("cannotMarry.ClanPersonnel.text"); @@ -165,7 +164,7 @@ public boolean safeSpouse(final Campaign campaign, final LocalDate today, final // marriages. if (person.equals(potentialSpouse) - || (canMarry(campaign, today, potentialSpouse, randomMarriage) != null) + || (canMarry(today, potentialSpouse, randomMarriage) != null) || person.getGenealogy().checkMutualAncestors(potentialSpouse, campaign.getCampaignOptions().getCheckMutualAncestorsDepth())) { return false; @@ -267,7 +266,7 @@ public static void performMarriageChanges(Campaign campaign, LocalDate today, Pe * @param person the person to process */ public void processNewWeek(final Campaign campaign, final LocalDate today, final Person person) { - if (canMarry(campaign, today, person, true) != null) { + if (canMarry(today, person, true) != null) { return; } @@ -304,7 +303,7 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final * @param person the person for whom to process the marriage rolls */ public void processBackgroundMarriageRolls(final Campaign campaign, final LocalDate today, final Person person) { - if (canMarry(campaign, today, person, true) != null) { + if (canMarry(today, person, true) != null) { return; } diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java index 2b7b4e8ea0..280a547a36 100644 --- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java @@ -78,6 +78,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static megamek.client.ui.WrapLayout.wordWrap; import static mekhq.campaign.personnel.education.Academy.skillParser; import static mekhq.campaign.personnel.education.EducationController.getAcademy; @@ -1443,13 +1444,11 @@ protected Optional createPopupMenu() { JMenuHelpers.addMenuIfNonEmpty(popup, new AssignPersonToUnitMenu(gui.getCampaign(), selected)); - LogManager.getLogger().info(gui.getCampaign().getMarriage().canMarry(gui.getCampaign(), - gui.getCampaign().getLocalDate(), person, false)); + LogManager.getLogger().info(gui.getCampaign().getMarriage().canMarry(gui.getCampaign().getLocalDate(), person, false)); if (oneSelected && person.getStatus().isActive()) { if (gui.getCampaign().getCampaignOptions().isUseManualMarriages() - && (gui.getCampaign().getMarriage().canMarry(gui.getCampaign(), - gui.getCampaign().getLocalDate(), person, false) == null)) { + && (gui.getCampaign().getMarriage().canMarry(gui.getCampaign().getLocalDate(), person, false) == null)) { menu = new JMenu(resources.getString("chooseSpouse.text")); JMenu maleMenu = new JMenu(resources.getString("spouseMenuMale.text")); JMenu femaleMenu = new JMenu(resources.getString("spouseMenuFemale.text")); @@ -2575,8 +2574,7 @@ protected Optional createPopupMenu() { || !gui.getCampaign().getCampaignOptions().getRandomMarriageMethod().isNone()) && Stream.of(selected).allMatch(p -> p.isMarriageable() == person.isMarriageable())) { cbMenuItem = new JCheckBoxMenuItem(resources.getString("miMarriageable.text")); - cbMenuItem.setToolTipText(MultiLineTooltip.splitToolTip(String.format(resources.getString("miMarriageable.toolTipText"), - gui.getCampaign().getCampaignOptions().getMinimumMarriageAge()), 100)); + cbMenuItem.setToolTipText(wordWrap(resources.getString("miMarriageable.toolTipText"))); cbMenuItem.setName("miMarriageable"); cbMenuItem.setSelected(person.isMarriageable()); cbMenuItem.addActionListener(evt -> { diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index d828143ce9..54b9a7efa4 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -109,13 +109,13 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private RandomSkillPreferences rSkillPrefs; private LocalDate date; private Camouflage camouflage; - private PlayerColour colour; + private final PlayerColour colour; private StandardForceIcon unitIcon; - private Hashtable hashSkillTargets; - private Hashtable hashGreenSkill; - private Hashtable hashRegSkill; - private Hashtable hashVetSkill; - private Hashtable hashEliteSkill; + private final Hashtable hashSkillTargets; + private final Hashtable hashGreenSkill; + private final Hashtable hashRegSkill; + private final Hashtable hashVetSkill; + private final Hashtable hashEliteSkill; //endregion General Variables (ones not relating to a specific tab) //region General Tab @@ -225,7 +225,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkShowOriginFaction; // Admin - private JPanel administratorsPanel = new JPanel(); + private final JPanel administratorsPanel = new JPanel(); private JCheckBox chkAdminsHaveNegotiation; private JCheckBox chkAdminsHaveScrounge; private JCheckBox chkAdminExperienceLevelIncludeNegotiation; @@ -272,7 +272,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseRandomRetirement; // Settings - private JPanel turnoverAndRetentionSettingsPanel = new JPanel(); + private final JPanel turnoverAndRetentionSettingsPanel = new JPanel(); private JLabel lblTurnoverFixedTargetNumber; private JSpinner spnTurnoverFixedTargetNumber; private MMComboBox comboTurnoverFrequency; @@ -289,7 +289,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JSpinner spnPayBonusDefaultThreshold; // Modifiers - private JPanel turnoverAndRetentionModifiersPanel = new JPanel(); + private final JPanel turnoverAndRetentionModifiersPanel = new JPanel(); private JCheckBox chkUseCustomRetirementModifiers; private JCheckBox chkUseFatigueModifiers; private JCheckBox chkUseSkillModifiers; @@ -301,41 +301,41 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseFamilyModifiers; private JCheckBox chkUseLoyaltyModifiers; - private JPanel loyaltySubPanel = new JPanel(); + private final JPanel loyaltySubPanel = new JPanel(); private JCheckBox chkUseHideLoyalty; // Payout - private JPanel turnoverAndRetentionPayoutPanel = new JPanel(); + private final JPanel turnoverAndRetentionPayoutPanel = new JPanel(); private JSpinner spnPayoutRateOfficer; private JSpinner spnPayoutRateEnlisted; private JSpinner spnPayoutRetirementMultiplier; private JCheckBox chkUsePayoutServiceBonus; - private JPanel payoutServiceBonusSubPanel = new JPanel(); + private final JPanel payoutServiceBonusSubPanel = new JPanel(); private JLabel lblPayoutServiceBonusRate; private JSpinner spnPayoutServiceBonusRate; // Unit Cohesion - private JPanel turnoverAndRetentionUnitCohesionPanel = new JPanel(); + private final JPanel turnoverAndRetentionUnitCohesionPanel = new JPanel(); private JCheckBox chkUseAdministrativeStrain; private JCheckBox chkUseManagementSkill; - private JPanel administrativeStrainSubPanel = new JPanel(); + private final JPanel administrativeStrainSubPanel = new JPanel(); private JLabel lblAdministrativeCapacity; private JSpinner spnAdministrativeCapacity; private JLabel lblMultiCrewStrainDivider; private JSpinner spnMultiCrewStrainDivider; - private JPanel managementSkillSubPanel = new JPanel(); + private final JPanel managementSkillSubPanel = new JPanel(); private JCheckBox chkUseCommanderLeadershipOnly; private JLabel lblManagementSkillPenalty; private JSpinner spnManagementSkillPenalty; // Fatigue - private JPanel turnoverAndRetentionFatiguePanel = new JPanel(); + private final JPanel turnoverAndRetentionFatiguePanel = new JPanel(); private JCheckBox chkUseFatigue; - private JPanel fatigueSubPanel = new JPanel(); + private final JPanel fatigueSubPanel = new JPanel(); private JSpinner spnFatigueRate; private JCheckBox chkUseInjuryFatigue; private JSpinner spnFieldKitchenCapacity; @@ -356,7 +356,6 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseManualMarriages; private JCheckBox chkUseClanPersonnelMarriages; private JCheckBox chkUsePrisonerMarriages; - private JSpinner spnMinimumMarriageAge; private JSpinner spnCheckMutualAncestorsDepth; private JCheckBox chkLogMarriageNameChanges; private Map spnMarriageSurnameWeights; @@ -439,7 +438,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private MMComboBox comboFamilyDisplayLevel; // Anniversaries - private JPanel anniversaryPanel = new JPanel(); + private final JPanel anniversaryPanel = new JPanel(); private JCheckBox chkAnnounceBirthdays; private JCheckBox chkAnnounceOfficersOnly; private JCheckBox chkAnnounceChildBirthdays; @@ -5567,14 +5566,6 @@ private JPanel createMarriagePanel() { chkUseRandomPrisonerMarriages.setEnabled(!method.isNone() && chkUsePrisonerMarriages.isSelected()); }); - final JLabel lblMinimumMarriageAge = new JLabel(resources.getString("lblMinimumMarriageAge.text")); - lblMinimumMarriageAge.setToolTipText(resources.getString("lblMinimumMarriageAge.toolTipText")); - lblMinimumMarriageAge.setName("lblMinimumMarriageAge"); - - spnMinimumMarriageAge = new JSpinner(new SpinnerNumberModel(16, 14, null, 1)); - spnMinimumMarriageAge.setToolTipText(resources.getString("lblMinimumMarriageAge.toolTipText")); - spnMinimumMarriageAge.setName("spnMinimumMarriageAge"); - final JLabel lblCheckMutualAncestorsDepth = new JLabel(resources.getString("lblCheckMutualAncestorsDepth.text")); lblCheckMutualAncestorsDepth.setToolTipText(resources.getString("lblCheckMutualAncestorsDepth.toolTipText")); lblCheckMutualAncestorsDepth.setName("lblCheckMutualAncestorsDepth"); @@ -5592,7 +5583,6 @@ private JPanel createMarriagePanel() { final JPanel randomMarriagePanel = createRandomMarriagePanel(); // Programmatically Assign Accessibility Labels - lblMinimumMarriageAge.setLabelFor(spnMinimumMarriageAge); lblCheckMutualAncestorsDepth.setLabelFor(spnCheckMutualAncestorsDepth); // Layout the Panel @@ -5610,9 +5600,6 @@ private JPanel createMarriagePanel() { .addComponent(chkUseManualMarriages) .addComponent(chkUseClanPersonnelMarriages) .addComponent(chkUsePrisonerMarriages) - .addGroup(layout.createParallelGroup(Alignment.BASELINE) - .addComponent(lblMinimumMarriageAge) - .addComponent(spnMinimumMarriageAge, Alignment.LEADING)) .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(lblCheckMutualAncestorsDepth) .addComponent(spnCheckMutualAncestorsDepth, Alignment.LEADING)) @@ -5626,9 +5613,6 @@ private JPanel createMarriagePanel() { .addComponent(chkUseManualMarriages) .addComponent(chkUseClanPersonnelMarriages) .addComponent(chkUsePrisonerMarriages) - .addGroup(layout.createSequentialGroup() - .addComponent(lblMinimumMarriageAge) - .addComponent(spnMinimumMarriageAge)) .addGroup(layout.createSequentialGroup() .addComponent(lblCheckMutualAncestorsDepth) .addComponent(spnCheckMutualAncestorsDepth)) @@ -8231,7 +8215,6 @@ public void setOptions(@Nullable CampaignOptions options, chkUseManualMarriages.setSelected(options.isUseManualMarriages()); chkUseClanPersonnelMarriages.setSelected(options.isUseClanPersonnelMarriages()); chkUsePrisonerMarriages.setSelected(options.isUsePrisonerMarriages()); - spnMinimumMarriageAge.setValue(options.getMinimumMarriageAge()); spnCheckMutualAncestorsDepth.setValue(options.getCheckMutualAncestorsDepth()); chkLogMarriageNameChanges.setSelected(options.isLogMarriageNameChanges()); for (final Entry entry : spnMarriageSurnameWeights.entrySet()) { @@ -8930,7 +8913,6 @@ public void updateOptions() { options.setUseManualMarriages(chkUseManualMarriages.isSelected()); options.setUseClanPersonnelMarriages(chkUseClanPersonnelMarriages.isSelected()); options.setUsePrisonerMarriages(chkUsePrisonerMarriages.isSelected()); - options.setMinimumMarriageAge((Integer) spnMinimumMarriageAge.getValue()); options.setCheckMutualAncestorsDepth((Integer) spnCheckMutualAncestorsDepth.getValue()); options.setLogMarriageNameChanges(chkLogMarriageNameChanges.isSelected()); for (final Entry entry : spnMarriageSurnameWeights.entrySet()) { @@ -9533,7 +9515,7 @@ public void stateChanged(ChangeEvent e) { * contains the main table. */ public static class RowNamesTable extends JTable implements ChangeListener, PropertyChangeListener { - private JTable main; + private final JTable main; public RowNamesTable(JTable table) { main = table; diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index d2b5b8a25f..77c3b7c28f 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -78,9 +78,7 @@ public void testGettersAndSetters() { @Test public void testCanMarry() { - doCallRealMethod().when(mockMarriage).canMarry(any(), any(), any(), anyBoolean()); - - when(mockCampaignOptions.getMinimumMarriageAge()).thenReturn(16); + doCallRealMethod().when(mockMarriage).canMarry(any(), any(), anyBoolean()); final Genealogy mockGenealogy = mock(Genealogy.class); @@ -89,77 +87,79 @@ public void testCanMarry() { // Have to be marriageable when(mockPerson.isMarriageable()).thenReturn(false); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); - // Can't be married already + // Can't be married when(mockPerson.isMarriageable()).thenReturn(true); when(mockGenealogy.hasSpouse()).thenReturn(true); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Must be active when(mockGenealogy.hasSpouse()).thenReturn(false); when(mockPerson.getStatus()).thenReturn(PersonnelStatus.KIA); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can't be deployed when(mockPerson.getStatus()).thenReturn(PersonnelStatus.ACTIVE); when(mockPerson.isDeployed()).thenReturn(true); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can't be younger than the minimum marriage age when(mockPerson.isDeployed()).thenReturn(false); - when(mockPerson.getAge(any())).thenReturn(15); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + when(mockPerson.isChild(any())).thenReturn(true); + when(mockPerson.isChild(any())).thenReturn(true); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can't be Clan Personnel with Clan Marriage Disabled - when(mockPerson.getAge(any())).thenReturn(16); + when(mockPerson.isChild(any())).thenReturn(false); when(mockPerson.isClanPersonnel()).thenReturn(true); - when(mockMarriage.isUseClanPersonnelMarriages()).thenReturn(false); - when(mockMarriage.isUsePrisonerMarriages()).thenReturn(true); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + lenient().when(mockMarriage.isUseClanPersonnelMarriages()).thenReturn(false); + lenient().when(mockMarriage.isUsePrisonerMarriages()).thenReturn(true); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can be Non-Clan Personnel with Clan Marriage Disabled when(mockPerson.isClanPersonnel()).thenReturn(false); - assertNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + when(mockPerson.isChild(any())).thenReturn(false); + assertNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can be a Non-Prisoner with Prisoner Marriage Disabled when(mockPerson.getPrisonerStatus()).thenReturn(PrisonerStatus.FREE); when(mockMarriage.isUsePrisonerMarriages()).thenReturn(false); - assertNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can't be a Prisoner with Prisoner Marriage Disabled when(mockPerson.getPrisonerStatus()).thenReturn(PrisonerStatus.PRISONER); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can be a Non-Random Clan Prisoner with Clan and Prisoner Marriage Enabled and Random Marriage Disabled when(mockPerson.isClanPersonnel()).thenReturn(true); when(mockMarriage.isUseClanPersonnelMarriages()).thenReturn(true); when(mockMarriage.isUsePrisonerMarriages()).thenReturn(true); - assertNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, false)); + assertNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, false)); // Can't be Clan Personnel with Random Clan Marriage Disabled when(mockMarriage.isUseRandomClanPersonnelMarriages()).thenReturn(false); when(mockMarriage.isUseRandomPrisonerMarriages()).thenReturn(true); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, true)); // Can be Non-Clan Personnel with Random Clan Marriage Disabled when(mockPerson.isClanPersonnel()).thenReturn(false); - assertNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true)); + assertNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, true)); // Can be a Non-Prisoner with Random Prisoner Marriage Disabled when(mockPerson.getPrisonerStatus()).thenReturn(PrisonerStatus.FREE); when(mockMarriage.isUseRandomPrisonerMarriages()).thenReturn(false); - assertNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true)); + assertNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, true)); // Can't be a Prisoner with Random Prisoner Marriage Disabled when(mockPerson.getPrisonerStatus()).thenReturn(PrisonerStatus.PRISONER); - assertNotNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true)); + assertNotNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, true)); // Can be a Clan Prisoner with Random Clan and Random Prisoner Marriage Enabled lenient().when(mockPerson.isClanPersonnel()).thenReturn(true); when(mockMarriage.isUseRandomClanPersonnelMarriages()).thenReturn(true); when(mockMarriage.isUseRandomPrisonerMarriages()).thenReturn(true); - assertNull(mockMarriage.canMarry(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, true)); + assertNull(mockMarriage.canMarry(LocalDate.ofYearDay(3025, 1), mockPerson, true)); } @Test @@ -177,11 +177,11 @@ public void testSafeSpouse() { assertFalse(mockMarriage.safeSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, mockPerson, false)); // Need to be able to marry - when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn("Married"); + when(mockMarriage.canMarry(any(), any(), anyBoolean())).thenReturn("Married"); assertFalse(mockMarriage.safeSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, mockSpouse, false)); // Can't be closely related - when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn(null); + when(mockMarriage.canMarry(any(), any(), anyBoolean())).thenReturn(null); when(mockGenealogy.checkMutualAncestors(any(), anyInt())).thenReturn(true); assertFalse(mockMarriage.safeSpouse(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson, mockSpouse, false)); @@ -267,12 +267,12 @@ public void testProcessNewWeek() { final Person mockPerson = mock(Person.class); - when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn("Married"); + when(mockMarriage.canMarry(any(), any(), anyBoolean())).thenReturn("Married"); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(0)).randomMarriage(any()); verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); - when(mockMarriage.canMarry(any(), any(), any(), anyBoolean())).thenReturn(null); + when(mockMarriage.canMarry(any(), any(), anyBoolean())).thenReturn(null); when(mockMarriage.randomMarriage(any())).thenReturn(true); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); verify(mockMarriage, times(1)).randomMarriage(any()); From 793a5385749a1a839b67140d624f878b849586cc Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 22:08:11 -0500 Subject: [PATCH 27/41] Refactor PersonViewPanel display behavior Reversed the order of former spouses and updated the text formatting to remove unnecessary HTML hyperlinks. Additionally, improved the `getRelativeName` method for better readability and made sure it only adds hyperlinks where necessary. --- MekHQ/src/mekhq/gui/view/PersonViewPanel.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/MekHQ/src/mekhq/gui/view/PersonViewPanel.java b/MekHQ/src/mekhq/gui/view/PersonViewPanel.java index 734f6043bc..354272aeb3 100644 --- a/MekHQ/src/mekhq/gui/view/PersonViewPanel.java +++ b/MekHQ/src/mekhq/gui/view/PersonViewPanel.java @@ -984,7 +984,10 @@ public void mouseClicked(MouseEvent e) { gridBagConstraints.weightx = 1.0; gridBagConstraints.insets = new Insets(0, 10, 0, 0); - for (FormerSpouse formerSpouse : person.getGenealogy().getFormerSpouses()) { + List formerSpouses = person.getGenealogy().getFormerSpouses(); + Collections.reverse(person.getGenealogy().getFormerSpouses()); + + for (FormerSpouse formerSpouse : formerSpouses) { Person ex = formerSpouse.getFormerSpouse(); String name = getRelativeName(ex); @@ -995,7 +998,7 @@ public void mouseClicked(MouseEvent e) { new AccessibleRelation(AccessibleRelation.LABELED_BY, lblFormerSpouses1) ); lblFormerSpouses2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - lblFormerSpouses2.setText(String.format("%s, %s, %s", + lblFormerSpouses2.setText(String.format("%s, %s, %s", name, formerSpouse.getReason(), MekHQ.getMHQOptions().getDisplayFormattedDate(formerSpouse.getDate()))); lblFormerSpouses2.addMouseListener(new MouseAdapter() { @@ -1035,7 +1038,7 @@ public void mouseClicked(MouseEvent e) { new AccessibleRelation(AccessibleRelation.LABELED_BY, lblChildren1) ); lblChildren2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - lblChildren2.setText(String.format("%s", name)); + lblChildren2.setText(String.format("%s", name)); lblChildren2.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -1075,7 +1078,7 @@ public void mouseClicked(MouseEvent e) { new AccessibleRelation(AccessibleRelation.LABELED_BY, lblGrandchildren1) ); lblGrandchildren2.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - lblGrandchildren2.setText(String.format("%s", name)); + lblGrandchildren2.setText(String.format("%s", name)); lblGrandchildren2.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -1285,9 +1288,9 @@ public void mouseClicked(MouseEvent e) { */ private static String getRelativeName(Person relative) { if (relative.getJoinedCampaign() == null) { - return relative.getFirstName() + " (Absent)"; + return relative.getFirstName(); } else { - return relative.getHyperlinkedFullTitle(); + return "" + relative.getHyperlinkedFullTitle() + ""; } } From 2337bbd1da1fdd6d31cf195008c21cafcf21862c Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 22:45:56 -0500 Subject: [PATCH 28/41] Add maternity leave support Implemented new maternity leave status and its handling in personnel management. Added UI options for enabling maternity leave and adjusted related personnel filters and processing logic. --- .../CampaignOptionsDialog.properties | 2 + .../mekhq/resources/Personnel.properties | 4 + MekHQ/src/mekhq/campaign/Campaign.java | 22 ++ MekHQ/src/mekhq/campaign/CampaignOptions.java | 13 + .../src/mekhq/campaign/personnel/Person.java | 2 +- .../personnel/enums/PersonnelStatus.java | 11 +- .../src/mekhq/gui/enums/PersonnelFilter.java | 274 ++++++++---------- .../mekhq/gui/panes/CampaignOptionsPane.java | 9 + 8 files changed, 187 insertions(+), 150 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 9de237c702..51c26b9226 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -536,6 +536,8 @@ chkDetermineFatherAtBirth.text=Determine Father at Birth instead of Conception chkDetermineFatherAtBirth.toolTipText=The father of a child will be determined based on the spouse at the birth of the child, followed by the spouse at time of conception, followed by nobody.
This is opposed to just using the spouse, if any, at the time of conception. chkDisplayTrueDueDate.text=Display True Due Date chkDisplayTrueDueDate.toolTipText=This displays the actual date the baby will be delivered on the mother's personnel sheet instead of an estimated due date. +chkUseMaternityLeave.text=Use Automatic Maternity Leave +chkUseMaternityLeave.toolTipText=If enabled, pregnant personnel will be placed on maternity leave 20 weeks before they give birth and will not return to active duty until 6 after they have given birth. chkLogProcreation.text=Log Conception and Birth in Personnel and Medical Logs chkLogProcreation.toolTipText=This enables logging the date of conception and birth in a person's logs. randomProcreationPanel.title=Random Procreation diff --git a/MekHQ/resources/mekhq/resources/Personnel.properties b/MekHQ/resources/mekhq/resources/Personnel.properties index deab866e59..3226216d55 100644 --- a/MekHQ/resources/mekhq/resources/Personnel.properties +++ b/MekHQ/resources/mekhq/resources/Personnel.properties @@ -355,6 +355,10 @@ PersonnelStatus.ON_LEAVE.text=On Leave PersonnelStatus.ON_LEAVE.toolTipText=They are currently on leave from the force. PersonnelStatus.ON_LEAVE.reportText=%s has gone on leave from the force PersonnelStatus.ON_LEAVE.logText=Went on leave +PersonnelStatus.ON_MATERNITY_LEAVE.text=On Maternity Leave +PersonnelStatus.ON_MATERNITY_LEAVE.toolTipText=They are currently on maternity leave. +PersonnelStatus.ON_MATERNITY_LEAVE.reportText=%s has gone on maternity leave +PersonnelStatus.ON_MATERNITY_LEAVE.logText=Went on maternity leave PersonnelStatus.AWOL.text=AWOL PersonnelStatus.AWOL.toolTipText=They have abandoned their post. PersonnelStatus.AWOL.reportText=%s has abandoned their post. diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 2d2c691469..0ed610cf64 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -3625,6 +3625,28 @@ public void processNewDayPersonnel() { getDivorce().processNewWeek(this, getLocalDate(), person, false); getMarriage().processNewWeek(this, getLocalDate(), person); getProcreation().processNewWeek(this, getLocalDate(), person); + + if (person.getGender().isFemale()) { + if (campaignOptions.isUseMaternityLeave()) { + if ((person.isPregnant()) + && (person.getStatus().isActive()) + && (person.getDueDate().minusWeeks(20).isEqual(getLocalDate()))) { + + person.changeStatus(this, getLocalDate(), PersonnelStatus.ON_MATERNITY_LEAVE); + } + + List children = person.getGenealogy().getChildren(); + + if ((person.getStatus().isOnMaternityLeave()) && (!children.isEmpty())) { + + children.sort(Comparator.comparing(Person::getBirthday).reversed()); + + if (getLocalDate().isAfter(children.get(0).getBirthday().plusDays(41))) { + person.changeStatus(this, getLocalDate(), PersonnelStatus.ACTIVE); + } + } + } + } } // Anniversaries diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 7e4203353f..33612d77ab 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -324,6 +324,7 @@ public static String getTransitUnitName(final int unit) { private BabySurnameStyle babySurnameStyle; private boolean assignNonPrisonerBabiesFounderTag; private boolean assignChildrenOfFoundersFounderTag; + private boolean useMaternityLeave; private boolean determineFatherAtBirth; private boolean displayTrueDueDate; private boolean logProcreation; @@ -896,6 +897,7 @@ public CampaignOptions() { setBabySurnameStyle(BabySurnameStyle.MOTHERS); setAssignNonPrisonerBabiesFounderTag(false); setAssignChildrenOfFoundersFounderTag(false); + setUseMaternityLeave(true); setDetermineFatherAtBirth(false); setDisplayTrueDueDate(false); setLogProcreation(false); @@ -2609,6 +2611,14 @@ public void setAssignChildrenOfFoundersFounderTag(final boolean assignChildrenOf this.assignChildrenOfFoundersFounderTag = assignChildrenOfFoundersFounderTag; } + public boolean isUseMaternityLeave() { + return useMaternityLeave; + } + + public void setUseMaternityLeave(final boolean useMaternityLeave) { + this.useMaternityLeave = useMaternityLeave; + } + /** * @return whether to determine the father at birth instead of at conception */ @@ -4802,6 +4812,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "babySurnameStyle", getBabySurnameStyle().name()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "assignNonPrisonerBabiesFounderTag", isAssignNonPrisonerBabiesFounderTag()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "assignChildrenOfFoundersFounderTag", isAssignChildrenOfFoundersFounderTag()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useMaternityLeave", isUseMaternityLeave()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "determineFatherAtBirth", isDetermineFatherAtBirth()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "displayTrueDueDate", isDisplayTrueDueDate()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "logProcreation", isLogProcreation()); @@ -5565,6 +5576,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setAssignNonPrisonerBabiesFounderTag(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("assignChildrenOfFoundersFounderTag")) { retVal.setAssignChildrenOfFoundersFounderTag(Boolean.parseBoolean(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("useMaternityLeave")) { + retVal.setUseMaternityLeave(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("determineFatherAtBirth")) { retVal.setDetermineFatherAtBirth(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("displayTrueDueDate")) { diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java index 5a1cb12120..37ba7509ba 100644 --- a/MekHQ/src/mekhq/campaign/personnel/Person.java +++ b/MekHQ/src/mekhq/campaign/personnel/Person.java @@ -965,7 +965,7 @@ public void changeStatus(final Campaign campaign, final LocalDate today, campaign.addReport(String.format(resources.getString("recoveredPoW.report"), getHyperlinkedFullTitle())); ServiceLogger.recoveredPoW(this, campaign.getLocalDate()); - } else if (getStatus().isOnLeave()) { + } else if (getStatus().isOnLeave() || getStatus().isOnMaternityLeave()) { campaign.addReport(String.format(resources.getString("returnedFromLeave.report"), getHyperlinkedFullTitle())); ServiceLogger.returnedFromLeave(this, campaign.getLocalDate()); diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java index dda5fa8aaf..6c7870d6e6 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java @@ -54,7 +54,8 @@ public enum PersonnelStatus { MEDICAL_COMPLICATIONS("PersonnelStatus.MEDICAL_COMPLICATIONS.text", "PersonnelStatus.MEDICAL_COMPLICATIONS.toolTipText", "PersonnelStatus.MEDICAL_COMPLICATIONS.reportText", "PersonnelStatus.MEDICAL_COMPLICATIONS.logText"), PREGNANCY_COMPLICATIONS("PersonnelStatus.PREGNANCY_COMPLICATIONS.text", "PersonnelStatus.PREGNANCY_COMPLICATIONS.toolTipText", "PersonnelStatus.PREGNANCY_COMPLICATIONS.reportText", "PersonnelStatus.PREGNANCY_COMPLICATIONS.logText"), UNDETERMINED("PersonnelStatus.UNDETERMINED.text", "PersonnelStatus.UNDETERMINED.toolTipText", "PersonnelStatus.UNDETERMINED.reportText", "PersonnelStatus.UNDETERMINED.logText"), - SUICIDE("PersonnelStatus.SUICIDE.text", "PersonnelStatus.SUICIDE.toolTipText", "PersonnelStatus.SUICIDE.reportText", "PersonnelStatus.SUICIDE.logText"); + SUICIDE("PersonnelStatus.SUICIDE.text", "PersonnelStatus.SUICIDE.toolTipText", "PersonnelStatus.SUICIDE.reportText", "PersonnelStatus.SUICIDE.logText"), + ON_MATERNITY_LEAVE("PersonnelStatus.ON_MATERNITY_LEAVE.text", "PersonnelStatus.ON_MATERNITY_LEAVE.toolTipText", "PersonnelStatus.ON_MATERNITY_LEAVE.reportText", "PersonnelStatus.ON_MATERNITY_LEAVE.logText"); //endregion Enum Declarations //region Variable Declarations @@ -107,6 +108,10 @@ public boolean isOnLeave() { return this == ON_LEAVE; } + public boolean isOnMaternityLeave() { + return this == ON_MATERNITY_LEAVE; + } + public boolean isAwol() { return this == AWOL; } @@ -191,7 +196,7 @@ public boolean isSuicide() { * @return true if a person is currently absent from the core force, otherwise false */ public boolean isAbsent() { - return isMIA() || isPoW() || isOnLeave() || isAwol() || isStudent() || isMissing(); + return isMIA() || isPoW() || isOnLeave() || isOnMaternityLeave() || isAwol() || isStudent() || isMissing(); } /** @@ -283,6 +288,8 @@ public static PersonnelStatus parseFromString(final String text) { return SUICIDE; case 22: return SACKED; + case 23: + return ON_MATERNITY_LEAVE; default: break; } diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java b/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java index 822ea40927..e98a84c6e8 100644 --- a/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java +++ b/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java @@ -21,6 +21,7 @@ import mekhq.MekHQ; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.PersonnelRole; +import mekhq.campaign.personnel.enums.PersonnelStatus; import java.time.LocalDate; import java.util.Arrays; @@ -367,153 +368,132 @@ public boolean getFilteredInformation(final Person person, LocalDate currentDate final boolean active = person.getStatus().isActive() && !person.getPrisonerStatus().isCurrentPrisoner(); final boolean dead = person.getStatus().isDead(); - switch (this) { - case ALL: - return true; - case ACTIVE: - return active; - case COMBAT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isCombat() : person.hasCombatRole()); - case SUPPORT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? !person.getPrimaryRole().isCombat() : person.hasSupportRole(true)); - case MECHWARRIORS: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isMechWarriorGrouping() - : (person.getPrimaryRole().isMechWarriorGrouping() || person.getSecondaryRole().isMechWarriorGrouping())); - case MECHWARRIOR: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isMechWarrior() : person.hasRole(PersonnelRole.MECHWARRIOR)); - case LAM_PILOT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isLAMPilot() : person.hasRole(PersonnelRole.LAM_PILOT)); - case VEHICLE_CREWMEMBER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVehicleCrewmember() - : (person.getPrimaryRole().isVehicleCrewmember() || person.getSecondaryRole().isVehicleCrewmember())); - case GROUND_VEHICLE_DRIVER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isGroundVehicleDriver() : person.hasRole(PersonnelRole.GROUND_VEHICLE_DRIVER)); - case NAVAL_VEHICLE_DRIVER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isNavalVehicleDriver() : person.hasRole(PersonnelRole.NAVAL_VEHICLE_DRIVER)); - case VEHICLE_GUNNER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVehicleGunner() : person.hasRole(PersonnelRole.VEHICLE_GUNNER)); - case VEHICLE_CREW: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVehicleCrew() : person.hasRole(PersonnelRole.VEHICLE_CREW)); - case VTOL_PILOT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVTOLPilot() : person.hasRole(PersonnelRole.VTOL_PILOT)); - case AEROSPACE_PILOT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAerospacePilot() : person.hasRole(PersonnelRole.AEROSPACE_PILOT)); - case CONVENTIONAL_AIRCRAFT_PILOT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isConventionalAircraftPilot() : person.hasRole(PersonnelRole.CONVENTIONAL_AIRCRAFT_PILOT)); - case PROTOMECH_PILOT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isProtoMechPilot() : person.hasRole(PersonnelRole.PROTOMECH_PILOT)); - case BATTLE_ARMOUR: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isBattleArmour() : person.hasRole(PersonnelRole.BATTLE_ARMOUR)); - case SOLDIER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isSoldier() : person.hasRole(PersonnelRole.SOLDIER)); - case VESSEL_CREWMEMBER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVesselCrewmember() - : (person.getPrimaryRole().isVesselCrewmember() || person.getSecondaryRole().isVesselCrewmember())); - case VESSEL_PILOT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVesselPilot() : person.hasRole(PersonnelRole.VESSEL_PILOT)); - case VESSEL_CREW: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVesselCrew() : person.hasRole(PersonnelRole.VESSEL_CREW)); - case VESSEL_GUNNER: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVesselGunner() : person.hasRole(PersonnelRole.VESSEL_GUNNER)); - case VESSEL_NAVIGATOR: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isVesselNavigator() : person.hasRole(PersonnelRole.VESSEL_NAVIGATOR)); - case TECH: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isTech() : person.isTech()); - case MECH_TECH: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isMechTech() : person.hasRole(PersonnelRole.MECH_TECH)); - case MECHANIC: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isMechanic() : person.hasRole(PersonnelRole.MECHANIC)); - case AERO_TECH: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAeroTech() : person.hasRole(PersonnelRole.AERO_TECH)); - case BA_TECH: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isBATech() : person.hasRole(PersonnelRole.BA_TECH)); - case ASTECH: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAstech() : person.hasRole(PersonnelRole.ASTECH)); - case MEDICAL: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isMedicalStaff() - : (person.getPrimaryRole().isMedicalStaff() || person.getSecondaryRole().isMedicalStaff())); - case DOCTOR: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isDoctor() : person.hasRole(PersonnelRole.DOCTOR)); - case MEDIC: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isMedic() : person.hasRole(PersonnelRole.MEDIC)); - case ADMINISTRATOR: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAdministrator() : person.isAdministrator()); - case ADMINISTRATOR_COMMAND: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAdministratorCommand() : person.hasRole(PersonnelRole.ADMINISTRATOR_COMMAND)); - case ADMINISTRATOR_LOGISTICS: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAdministratorLogistics() : person.hasRole(PersonnelRole.ADMINISTRATOR_LOGISTICS)); - case ADMINISTRATOR_TRANSPORT: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAdministratorTransport() : person.hasRole(PersonnelRole.ADMINISTRATOR_TRANSPORT)); - case ADMINISTRATOR_HR: - return active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() - ? person.getPrimaryRole().isAdministratorHR() : person.hasRole(PersonnelRole.ADMINISTRATOR_HR)); - case DEPENDENT: - return ((!dead) && (active && person.getPrimaryRole().isDependent())); - case FOUNDER: - return ((!dead) && (person.isFounder())); - case KIDS: - return ((!dead) && (!person.getStatus().isLeft()) && (person.isChild(currentDate))); - case PRISONER: - return ((!dead) && ((person.getPrisonerStatus().isCurrentPrisoner()) || (person.getPrisonerStatus().isBondsman()))); - case INACTIVE: - return ((!dead) && (!person.getStatus().isActive())); - case ON_LEAVE: - return person.getStatus().isOnLeave(); - case MIA: - return person.getStatus().isMIA() || person.getStatus().isPoW(); - case RETIRED: - return person.getStatus().isRetired(); - case RESIGNED: - return ((person.getStatus().isResigned()) || (person.getStatus().isLeft())); - case AWOL: - return person.getStatus().isAwol(); - case DESERTED: - return person.getStatus().isDeserted(); - case STUDENT: - return person.getStatus().isStudent(); - case MISSING: - return person.getStatus().isMissing(); - case KIA: - return person.getStatus().isKIA(); - case DEAD: - return person.getStatus().isDead(); - default: - return false; - } + PersonnelStatus status = person.getStatus(); + + return switch (this) { + case ALL -> true; + case ACTIVE -> active; + case COMBAT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isCombat() : person.hasCombatRole()); + case SUPPORT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + !person.getPrimaryRole().isCombat() : person.hasSupportRole(true)); + case MECHWARRIORS -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isMechWarriorGrouping() : (person.getPrimaryRole().isMechWarriorGrouping() || person.getSecondaryRole().isMechWarriorGrouping())); + case MECHWARRIOR -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isMechWarrior() : person.hasRole(PersonnelRole.MECHWARRIOR)); + case LAM_PILOT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isLAMPilot() : person.hasRole(PersonnelRole.LAM_PILOT)); + case VEHICLE_CREWMEMBER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVehicleCrewmember() : (person.getPrimaryRole().isVehicleCrewmember() || person.getSecondaryRole().isVehicleCrewmember())); + case GROUND_VEHICLE_DRIVER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isGroundVehicleDriver() : person.hasRole(PersonnelRole.GROUND_VEHICLE_DRIVER)); + case NAVAL_VEHICLE_DRIVER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isNavalVehicleDriver() : person.hasRole(PersonnelRole.NAVAL_VEHICLE_DRIVER)); + case VEHICLE_GUNNER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVehicleGunner() : person.hasRole(PersonnelRole.VEHICLE_GUNNER)); + case VEHICLE_CREW -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVehicleCrew() : person.hasRole(PersonnelRole.VEHICLE_CREW)); + case VTOL_PILOT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVTOLPilot() : person.hasRole(PersonnelRole.VTOL_PILOT)); + case AEROSPACE_PILOT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAerospacePilot() : person.hasRole(PersonnelRole.AEROSPACE_PILOT)); + case CONVENTIONAL_AIRCRAFT_PILOT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isConventionalAircraftPilot() : person.hasRole(PersonnelRole.CONVENTIONAL_AIRCRAFT_PILOT)); + case PROTOMECH_PILOT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isProtoMechPilot() : person.hasRole(PersonnelRole.PROTOMECH_PILOT)); + case BATTLE_ARMOUR -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isBattleArmour() : person.hasRole(PersonnelRole.BATTLE_ARMOUR)); + case SOLDIER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isSoldier() : person.hasRole(PersonnelRole.SOLDIER)); + case VESSEL_CREWMEMBER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVesselCrewmember() : (person.getPrimaryRole().isVesselCrewmember() || person.getSecondaryRole().isVesselCrewmember())); + case VESSEL_PILOT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVesselPilot() : person.hasRole(PersonnelRole.VESSEL_PILOT)); + case VESSEL_CREW -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVesselCrew() : person.hasRole(PersonnelRole.VESSEL_CREW)); + case VESSEL_GUNNER -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVesselGunner() : person.hasRole(PersonnelRole.VESSEL_GUNNER)); + case VESSEL_NAVIGATOR -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isVesselNavigator() : person.hasRole(PersonnelRole.VESSEL_NAVIGATOR)); + case TECH -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isTech() : person.isTech()); + case MECH_TECH -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isMechTech() : person.hasRole(PersonnelRole.MECH_TECH)); + case MECHANIC -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isMechanic() : person.hasRole(PersonnelRole.MECHANIC)); + case AERO_TECH -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAeroTech() : person.hasRole(PersonnelRole.AERO_TECH)); + case BA_TECH -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isBATech() : person.hasRole(PersonnelRole.BA_TECH)); + case ASTECH -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAstech() : person.hasRole(PersonnelRole.ASTECH)); + case MEDICAL -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isMedicalStaff() : (person.getPrimaryRole().isMedicalStaff() || person.getSecondaryRole().isMedicalStaff())); + case DOCTOR -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isDoctor() : person.hasRole(PersonnelRole.DOCTOR)); + case MEDIC -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isMedic() : person.hasRole(PersonnelRole.MEDIC)); + case ADMINISTRATOR -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAdministrator() : person.isAdministrator()); + case ADMINISTRATOR_COMMAND -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAdministratorCommand() : person.hasRole(PersonnelRole.ADMINISTRATOR_COMMAND)); + case ADMINISTRATOR_LOGISTICS -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAdministratorLogistics() : person.hasRole(PersonnelRole.ADMINISTRATOR_LOGISTICS)); + case ADMINISTRATOR_TRANSPORT -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAdministratorTransport() : person.hasRole(PersonnelRole.ADMINISTRATOR_TRANSPORT)); + case ADMINISTRATOR_HR -> + active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? + person.getPrimaryRole().isAdministratorHR() : person.hasRole(PersonnelRole.ADMINISTRATOR_HR)); + case DEPENDENT -> ((!dead) && (active && person.getPrimaryRole().isDependent())); + case FOUNDER -> ((!dead) && (person.isFounder())); + case KIDS -> ((!dead) && (!status.isLeft()) && (person.isChild(currentDate))); + case PRISONER -> ((!dead) && ((person.getPrisonerStatus().isCurrentPrisoner()) || (person.getPrisonerStatus().isBondsman()))); + case INACTIVE -> ((!dead) && (!status.isActive())); + case ON_LEAVE -> status.isOnLeave() || status.isOnMaternityLeave(); + case MIA -> status.isMIA() || status.isPoW(); + case RETIRED -> status.isRetired(); + case RESIGNED -> ((status.isResigned()) || (status.isLeft())); + case AWOL -> status.isAwol(); + case DESERTED -> status.isDeserted(); + case STUDENT -> status.isStudent(); + case MISSING -> status.isMissing(); + case KIA -> status.isKIA(); + case DEAD -> status.isDead(); + }; } @Override diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index 54b9a7efa4..ac54e5501a 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -390,6 +390,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkAssignChildrenOfFoundersFounderTag; private JCheckBox chkDetermineFatherAtBirth; private JCheckBox chkDisplayTrueDueDate; + private JCheckBox chkUseMaternityLeave; private JCheckBox chkLogProcreation; private MMComboBox comboRandomProcreationMethod; private JCheckBox chkUseRelationshiplessRandomProcreation; @@ -6116,6 +6117,10 @@ public Component getListCellRendererComponent(final JList list, final Object chkDisplayTrueDueDate.setToolTipText(resources.getString("chkDisplayTrueDueDate.toolTipText")); chkDisplayTrueDueDate.setName("chkDisplayTrueDueDate"); + chkUseMaternityLeave = new JCheckBox(resources.getString("chkUseMaternityLeave.text")); + chkUseMaternityLeave.setToolTipText(wordWrap(resources.getString("chkUseMaternityLeave.toolTipText"))); + chkUseMaternityLeave.setName("chkUseMaternityLeave"); + chkLogProcreation = new JCheckBox(resources.getString("chkLogProcreation.text")); chkLogProcreation.setToolTipText(resources.getString("chkLogProcreation.toolTipText")); chkLogProcreation.setName("chkLogProcreation"); @@ -6152,6 +6157,7 @@ public Component getListCellRendererComponent(final JList list, final Object .addComponent(chkAssignChildrenOfFoundersFounderTag) .addComponent(chkDetermineFatherAtBirth) .addComponent(chkDisplayTrueDueDate) + .addComponent(chkUseMaternityLeave) .addComponent(chkLogProcreation) .addComponent(randomProcreationPanel) ); @@ -6172,6 +6178,7 @@ public Component getListCellRendererComponent(final JList list, final Object .addComponent(chkAssignChildrenOfFoundersFounderTag) .addComponent(chkDetermineFatherAtBirth) .addComponent(chkDisplayTrueDueDate) + .addComponent(chkUseMaternityLeave) .addComponent(chkLogProcreation) .addComponent(randomProcreationPanel) ); @@ -8265,6 +8272,7 @@ public void setOptions(@Nullable CampaignOptions options, chkAssignChildrenOfFoundersFounderTag.setSelected(options.isAssignChildrenOfFoundersFounderTag()); chkDetermineFatherAtBirth.setSelected(options.isDetermineFatherAtBirth()); chkDisplayTrueDueDate.setSelected(options.isDisplayTrueDueDate()); + chkUseMaternityLeave.setSelected(options.isUseMaternityLeave()); chkLogProcreation.setSelected(options.isLogProcreation()); comboRandomProcreationMethod.setSelectedItem(options.getRandomProcreationMethod()); if (chkUseRelationshiplessRandomProcreation.isSelected() != options.isUseRelationshiplessRandomProcreation()) { @@ -8950,6 +8958,7 @@ public void updateOptions() { options.setAssignChildrenOfFoundersFounderTag(chkAssignChildrenOfFoundersFounderTag.isSelected()); options.setDetermineFatherAtBirth(chkDetermineFatherAtBirth.isSelected()); options.setDisplayTrueDueDate(chkDisplayTrueDueDate.isSelected()); + options.setUseMaternityLeave(chkUseMaternityLeave.isSelected()); options.setLogProcreation(chkLogProcreation.isSelected()); options.setRandomProcreationMethod(comboRandomProcreationMethod.getSelectedItem()); options.setUseRelationshiplessRandomProcreation(chkUseRelationshiplessRandomProcreation.isSelected()); From 7a4b56b53dfcac48a58a7c7a682a08548f3b1b25 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 22:49:57 -0500 Subject: [PATCH 29/41] Add tests for ON_MATERNITY_LEAVE PersonnelStatus Included a new test case to verify the behavior of the isOnMaternityLeave method in PersonnelStatusTest. Also, updated existing tests to include ON_MATERNITY_LEAVE status checks and corrected the parseFromString error case. --- .../personnel/enums/PersonnelStatusTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java index 6e49db9660..e4697b08ff 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java @@ -107,6 +107,17 @@ public void testIsOnLeave() { } } + @Test + public void testIsOnMaternityLeave() { + for (final PersonnelStatus personnelStatus : statuses) { + if (personnelStatus == PersonnelStatus.ON_MATERNITY_LEAVE) { + assertTrue(personnelStatus.isOnMaternityLeave()); + } else { + assertFalse(personnelStatus.isOnMaternityLeave()); + } + } + } + @Test public void testIsAwol() { for (final PersonnelStatus personnelStatus : statuses) { @@ -281,6 +292,7 @@ public void testIsAbsent() { case ON_LEAVE: case STUDENT: case MISSING: + case ON_MATERNITY_LEAVE: case AWOL: assertTrue(personnelStatus.isAbsent()); break; @@ -380,9 +392,10 @@ public void testParseFromString() { assertEquals(PersonnelStatus.UNDETERMINED, PersonnelStatus.parseFromString("20")); assertEquals(PersonnelStatus.SUICIDE, PersonnelStatus.parseFromString("21")); assertEquals(PersonnelStatus.SACKED, PersonnelStatus.parseFromString("22")); + assertEquals(PersonnelStatus.ON_MATERNITY_LEAVE, PersonnelStatus.parseFromString("23")); // Error Case - assertEquals(PersonnelStatus.ACTIVE, PersonnelStatus.parseFromString("23")); + assertEquals(PersonnelStatus.ACTIVE, PersonnelStatus.parseFromString("24")); assertEquals(PersonnelStatus.ACTIVE, PersonnelStatus.parseFromString("blah")); } //endregion File I/O From 9e52e7f5652f9c93547c2fcdcf8a27ac597a56a0 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Sat, 3 Aug 2024 23:18:20 -0500 Subject: [PATCH 30/41] Add adoption functionality for personnel management Implemented the ability to adopt orphans within the personnel management system. This included adding a new command and updating the GUI to reflect adoption options in the context menu. --- .../resources/mekhq/resources/GUI.properties | 2 + .../adapter/PersonnelTableMouseAdapter.java | 73 +++++++++++++++++-- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties index 863f0d5446..894b1743a6 100644 --- a/MekHQ/resources/mekhq/resources/GUI.properties +++ b/MekHQ/resources/mekhq/resources/GUI.properties @@ -102,6 +102,8 @@ execute.text=Execute jettison.text=Jettison recruit.text=Recruit abtakha.text=Adopt (Abtakha) +adopt.text=Adopt +adopt.description=%s, %s, Age %s changePrimaryRole.text=Change Primary Role changeSecondaryRole.text=Change Secondary Role setSalary.text=Set Salary diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java index 280a547a36..f505387fd6 100644 --- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java @@ -147,6 +147,7 @@ public class PersonnelTableMouseAdapter extends JPopupMenuAdapter { private static final String CMD_JETTISON = "JETTISON"; private static final String CMD_RECRUIT = "RECRUIT"; private static final String CMD_ABTAKHA = "ABTAKHA"; + private static final String CMD_ADOPTION = "ADOPTION"; private static final String CMD_RANSOM = "RANSOM"; private static final String CMD_RANSOM_FRIENDLY = "RANSOM_FRIENDLY"; @@ -698,6 +699,34 @@ public void actionPerformed(ActionEvent action) { } break; } + case CMD_ADOPTION: { + Person orphan = gui.getCampaign().getPerson(UUID.fromString(data[1])); + + // clear the old parents + for (Person parent : orphan.getGenealogy().getParents()) { + orphan.getGenealogy().removeFamilyMember(FamilialRelationshipType.PARENT, parent); + } + + // add the new + for (Person person : people) { + person.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, orphan); + orphan.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, person); + + MekHQ.triggerEvent(new PersonChangedEvent(person)); + + if (person.getGenealogy().hasSpouse()) { + Person spouse = person.getGenealogy().getSpouse(); + + spouse.getGenealogy().addFamilyMember(FamilialRelationshipType.CHILD, orphan); + orphan.getGenealogy().addFamilyMember(FamilialRelationshipType.PARENT, spouse); + + MekHQ.triggerEvent(new PersonChangedEvent(spouse)); + } + } + + MekHQ.triggerEvent(new PersonChangedEvent(orphan)); + break; + } case CMD_RANSOM: { // ask the user if they want to sell off their prisoners. If yes, then add a daily report entry, add the money and remove them all. Money total = Money.zero(); @@ -1400,6 +1429,30 @@ protected Optional createPopupMenu() { popup.add(newMenuItem(resources.getString("abtakha.text"), CMD_ABTAKHA)); } + if ((oneSelected) && (!person.isChild(gui.getCampaign().getLocalDate()))) { + List orphans = gui.getCampaign().getActivePersonnel().stream() + .filter(child -> (child.isChild(gui.getCampaign().getLocalDate())) && (!child.getGenealogy().hasLivingParents())) + .toList(); + + if (!orphans.isEmpty()) { + JMenu orphanMenu = new JMenu(resources.getString("adopt.text")); + + for (final Person orphan : orphans) { + String status = String.format(resources.getString("adopt.description"), + orphan.getFullName(), + orphan.getGender(), + orphan.getAge(gui.getCampaign().getLocalDate())); + + JMenuItem orphanItem = new JMenuItem(status); + orphanItem.setActionCommand(makeCommand(CMD_ADOPTION, String.valueOf(orphan.getId()))); + orphanItem.addActionListener(this); + orphanMenu.add(orphanItem); + } + + JMenuHelpers.addMenuIfNonEmpty(popup, orphanMenu); + } + } + final PersonnelRole[] roles = PersonnelRole.values(); menu = new JMenu(resources.getString("changePrimaryRole.text")); @@ -1444,8 +1497,6 @@ protected Optional createPopupMenu() { JMenuHelpers.addMenuIfNonEmpty(popup, new AssignPersonToUnitMenu(gui.getCampaign(), selected)); - LogManager.getLogger().info(gui.getCampaign().getMarriage().canMarry(gui.getCampaign().getLocalDate(), person, false)); - if (oneSelected && person.getStatus().isActive()) { if (gui.getCampaign().getCampaignOptions().isUseManualMarriages() && (gui.getCampaign().getMarriage().canMarry(gui.getCampaign().getLocalDate(), person, false) == null)) { @@ -1468,11 +1519,23 @@ protected Optional createPopupMenu() { final String status; final String founder = potentialSpouse.isFounder() ? resources.getString("spouseFounder.text") : ""; if (potentialSpouse.getPrisonerStatus().isBondsman()) { - status = String.format(resources.getString("marriageBondsmanDesc.format"), potentialSpouse.getFullName(), potentialSpouse.getAge(today), potentialSpouse.getRoleDesc(), founder); + status = String.format(resources.getString("marriageBondsmanDesc.format"), + potentialSpouse.getFullName(), + potentialSpouse.getAge(today), + potentialSpouse.getRoleDesc(), + founder); } else if (potentialSpouse.getPrisonerStatus().isCurrentPrisoner()) { - status = String.format(resources.getString("marriagePrisonerDesc.format"), potentialSpouse.getFullName(), potentialSpouse.getAge(today), potentialSpouse.getRoleDesc(), founder); + status = String.format(resources.getString("marriagePrisonerDesc.format"), + potentialSpouse.getFullName(), + potentialSpouse.getAge(today), + potentialSpouse.getRoleDesc(), + founder); } else { - status = String.format(resources.getString("marriagePartnerDesc.format"), potentialSpouse.getFullName(), potentialSpouse.getAge(today), potentialSpouse.getRoleDesc(), founder); + status = String.format(resources.getString("marriagePartnerDesc.format"), + potentialSpouse.getFullName(), + potentialSpouse.getAge(today), + potentialSpouse.getRoleDesc(), + founder); } spouseMenu = new JMenu(status); From 24e7d9b83ff35b98e1c867612639cb096c17a6c0 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 5 Aug 2024 15:36:00 -0500 Subject: [PATCH 31/41] Added non-binary gender option for personnel generation This commit introduced the ability to generate non-binary characters based on a configurable dice size for random gender selection. Also updated gender handling in various parts of the UI and backend to support the new non-binary option. --- .../CampaignOptionsDialog.properties | 5 +-- MekHQ/src/mekhq/campaign/CampaignOptions.java | 30 ++++++++++----- .../mission/AtBDynamicScenarioFactory.java | 11 +++++- .../campaign/mission/BotForceRandomizer.java | 23 +++++++----- .../generator/AbstractPersonnelGenerator.java | 19 +++++++--- .../generator/DefaultPersonnelGenerator.java | 2 +- .../personnel/marriage/AbstractMarriage.java | 19 ++++++++-- .../procreation/AbstractProcreation.java | 4 +- .../gui/dialog/CreateCharacterDialog.java | 37 ++++++++----------- .../gui/dialog/CustomizePersonDialog.java | 27 +++++--------- MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java | 5 +-- .../mekhq/gui/panes/CampaignOptionsPane.java | 31 ++++++++++++---- 12 files changed, 129 insertions(+), 84 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 51c26b9226..0a95e8cf69 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -432,6 +432,8 @@ lifePathsPanel.title=Life Paths personnelRandomizationPanel.title=Personnel Randomization chkUseDylansRandomXP.text=Use Dylan's Random XP (Unofficial) chkUseDylansRandomXP.toolTipText=Use Dylan's optional random XP on creation of a new person (20% chance each of 0, 1, 2, 3, and randomized between 1 and 8 XP) +lblNonBinaryDiceSize.text=Non-Binary Personnel Dice Size +lblNonBinaryDiceSize.toolTipText=This is the number of sides on the die rolled to determine whether a character's random gender is 'Other.' A character will identify as a gender other than Male or Female on a roll of 1. Set to 0 to disable non-binary characters. The default value is based on the 2022 US Census and gives a result of around 1.6%. # Random Histories randomHistoriesPanel.title=Random Histories @@ -465,8 +467,6 @@ chkUseClanPersonnelMarriages.text=Use Clan Personnel Marriages chkUseClanPersonnelMarriages.toolTipText=Allow clan-origin personnel to marry other personnel. chkUsePrisonerMarriages.text=Use Prisoner Marriages chkUsePrisonerMarriages.toolTipText=Allow prisoners to marry other prisoners, and manually marrying a prisoner to a free member of the force. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. -lblMinimumMarriageAge.text=Minimum Marital Age -lblMinimumMarriageAge.toolTipText=This is the minimum age allowed for a person to be married. lblCheckMutualAncestorsDepth.text=Minimum Mutual Ancestor Check Depth for Marriage to be Possible lblCheckMutualAncestorsDepth.toolTipText=This is the depth to which the ancestry of two people is checked for mutual ancestors to determine if they can marry.
Set to 0 to disable the ancestry check. chkLogMarriageNameChanges.text=Log Marriage Name Changes @@ -722,7 +722,6 @@ chkOverageRepaymentInFinalPayment.toolTipText=This is an unofficial addition tha lblXpCostMultiplier.text=XP Cost Multiplier lblXpCostMultiplier.tooltip=This value multiplies the XP costs for SPA and Skill Levels. lblScenarioXP.text=XP for each completed scenario -lblKillXP.text=XP for every lblXPForEvery.text=XP for every lblKills.text=kills lblTasks.text=successful tasks diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 33612d77ab..67a3cf2e4a 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -273,9 +273,10 @@ public static String getTransitUnitName(final int unit) { //region Life Paths Tab // Personnel Randomization private boolean useDylansRandomXP; // Unofficial - private RandomOriginOptions randomOriginOptions; + private int nonBinaryDiceSize; // Random Histories + private RandomOriginOptions randomOriginOptions; private boolean useRandomPersonalities; private boolean useSimulatedRelationships; @@ -831,6 +832,7 @@ public CampaignOptions() { //region Life Paths Tab // Personnel Randomization setUseDylansRandomXP(false); + setNonBinaryDiceSize(60); setRandomOriginOptions(new RandomOriginOptions(true)); // Random Histories @@ -908,7 +910,7 @@ public CampaignOptions() { setRandomProcreationRelationshipDiceSize(500); setRandomProcreationRelationshiplessDiceSize(2000); - // Education + // Education setUseEducationModule(false); setCurriculumXpRate(3); setMaximumJumpCount(5); @@ -1841,7 +1843,16 @@ public boolean isUseDylansRandomXP() { public void setUseDylansRandomXP(final boolean useDylansRandomXP) { this.useDylansRandomXP = useDylansRandomXP; } + public int getNonBinaryDiceSize() { + return nonBinaryDiceSize; + } + + public void setNonBinaryDiceSize(final int nonBinaryDiceSize) { + this.nonBinaryDiceSize = nonBinaryDiceSize; + } + //endregion Personnel Randomization + //region Random Histories public RandomOriginOptions getRandomOriginOptions() { return randomOriginOptions; } @@ -1849,9 +1860,7 @@ public RandomOriginOptions getRandomOriginOptions() { public void setRandomOriginOptions(final RandomOriginOptions randomOriginOptions) { this.randomOriginOptions = randomOriginOptions; } - //endregion Personnel Randomization - //region Random Histories public boolean isUseRandomPersonalities() { return useRandomPersonalities; } @@ -4699,10 +4708,11 @@ public void writeToXml(final PrintWriter pw, int indent) { //region Life Paths Tab //region Personnel Randomization MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useDylansRandomXP", isUseDylansRandomXP()); - getRandomOriginOptions().writeToXML(pw, indent); - //endregion Personnel Randomization + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "nonBinaryDiceSize", getNonBinaryDiceSize()); + //endregion Personnel Randomization //region Random Histories + getRandomOriginOptions().writeToXML(pw, indent); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRandomPersonalities", isUseRandomPersonalities()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useSimulatedRelationships", isUseSimulatedRelationships()); //endregion Random Histories @@ -5443,6 +5453,11 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve //region Personnel Randomization } else if (wn2.getNodeName().equalsIgnoreCase("useDylansRandomXP")) { retVal.setUseDylansRandomXP(Boolean.parseBoolean(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("nonBinaryDiceSize")) { + retVal.setNonBinaryDiceSize(Integer.parseInt(wn2.getTextContent().trim())); + //endregion Personnel Randomization + + //region Random Histories } else if (wn2.getNodeName().equalsIgnoreCase("randomOriginOptions")) { if (!wn2.hasChildNodes()) { continue; @@ -5452,9 +5467,6 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve continue; } retVal.setRandomOriginOptions(randomOriginOptions); - //endregion Personnel Randomization - - //region Random Histories } else if (wn2.getNodeName().equalsIgnoreCase("useRandomPersonalities")) { retVal.setUseRandomPersonalities(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("useSimulatedRelationships")) { diff --git a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java index 29ce00e7f0..d55daa266b 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBDynamicScenarioFactory.java @@ -1849,7 +1849,16 @@ private static Entity getEntityByName(String name, String factionCode, SkillLeve RandomNameGenerator rng = RandomNameGenerator.getInstance(); rng.setChosenFaction(faction.getNameGenerator()); - Gender gender = RandomGenderGenerator.generate(); + + Gender gender; + int nonBinaryDiceSize = campaign.getCampaignOptions().getNonBinaryDiceSize(); + + if ((nonBinaryDiceSize > 0) && (Compute.randomInt(nonBinaryDiceSize) == 0)) { + gender = RandomGenderGenerator.generateOther(); + } else { + gender = RandomGenderGenerator.generate(); + } + String[] crewNameArray = rng.generateGivenNameSurnameSplit(gender, faction.isClan(), faction.getShortName()); String crewName = crewNameArray[0]; crewName += !StringUtility.isNullOrBlank(crewNameArray[1]) ? ' ' + crewNameArray[1] : ""; diff --git a/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java b/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java index e7b6769d7c..96bf2aedb7 100644 --- a/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java +++ b/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java @@ -29,16 +29,16 @@ import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; import megamek.common.enums.SkillLevel; -import mekhq.campaign.rating.IUnitRating; -import mekhq.utilities.MHQXMLUtility; import mekhq.campaign.Campaign; import mekhq.campaign.personnel.Bloodname; import mekhq.campaign.personnel.enums.Phenotype; +import mekhq.campaign.rating.IUnitRating; import mekhq.campaign.unit.Unit; import mekhq.campaign.universe.Faction; import mekhq.campaign.universe.Factions; import mekhq.campaign.universe.IUnitGenerator; import mekhq.campaign.universe.UnitGeneratorParameters; +import mekhq.utilities.MHQXMLUtility; import org.apache.commons.math3.distribution.GammaDistribution; import org.apache.logging.log4j.LogManager; import org.w3c.dom.Node; @@ -426,7 +426,16 @@ public Entity getEntity(int uType, int weightClass, Campaign campaign) { RandomNameGenerator rng = RandomNameGenerator.getInstance(); rng.setChosenFaction(faction.getNameGenerator()); - Gender gender = RandomGenderGenerator.generate(); + + Gender gender; + int nonBinaryDiceSize = campaign.getCampaignOptions().getNonBinaryDiceSize(); + + if ((nonBinaryDiceSize > 0) && (Compute.randomInt(nonBinaryDiceSize) == 0)) { + gender = RandomGenderGenerator.generateOther(); + } else { + gender = RandomGenderGenerator.generate(); + } + String[] crewNameArray = rng.generateGivenNameSurnameSplit(gender, faction.isClan(), faction.getShortName()); String crewName = crewNameArray[0]; crewName += !StringUtility.isNullOrBlank(crewNameArray[1]) ? " " + crewNameArray[1] : ""; @@ -625,12 +634,8 @@ private double calculateMeanWeightClass(List playerUnits) { } public String getShortDescription() { - StringBuilder sb = new StringBuilder(); - sb.append(forceMultiplier); - sb.append(" ("); - sb.append(balancingMethod.toString()); - sb.append(")"); - return sb.toString(); + String sb = forceMultiplier + " (" + balancingMethod.toString() + ")"; + return sb; } /** diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java index 0c2b4d85ce..16b775298b 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java @@ -111,13 +111,20 @@ public int generateExperienceLevel(Person person) { } /** - * Generates a name for a {@link Person}. - * @param campaign The {@link Campaign} to use to generate the person - * @param person The {@link Person} whose name is being generated. - * @param gender The person's gender, or a randomize value + * Generates and sets the name and gender of a person. + * + * @param campaign the campaign the person belongs to + * @param person the person whose name and gender is being generated + * @param gender the gender of the person. Can be Gender.MALE, Gender.FEMALE, Gender.NON_BINARY, or Gender.RANDOMIZE */ - protected void generateName(Campaign campaign, Person person, Gender gender) { - person.setGender((gender == Gender.RANDOMIZE) ? RandomGenderGenerator.generate() : gender); + protected void generateNameAndGender(Campaign campaign, Person person, Gender gender) { + int nonBinaryDiceSize = campaign.getCampaignOptions().getNonBinaryDiceSize(); + + if ((gender == Gender.RANDOMIZE) && (nonBinaryDiceSize > 0) && (Compute.randomInt(nonBinaryDiceSize) == 0)) { + person.setGender(RandomGenderGenerator.generateOther()); + } else { + person.setGender(RandomGenderGenerator.generate()); + } String factionCode = campaign.getCampaignOptions().isUseOriginFactionForNames() ? person.getOriginFaction().getShortName() diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java index 83dffd4110..b5a331a776 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java @@ -109,7 +109,7 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo } // Do naming at the end, to ensure the keys are set - generateName(campaign, person, gender); + generateNameAndGender(campaign, person, gender); //check for Bloodname campaign.checkBloodnameAdd(person, false); diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index d7df2c46a0..4b812a7e81 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -18,6 +18,7 @@ */ package mekhq.campaign.personnel.marriage; +import megamek.client.generator.RandomGenderGenerator; import megamek.common.Compute; import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; @@ -343,15 +344,25 @@ public void processBackgroundMarriageRolls(final Campaign campaign, final LocalD protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, final Person person, final boolean sameSex, boolean isInterUnit, boolean isBackground) { - final Gender gender = sameSex ? person.getGender() - : (person.getGender().isMale() ? Gender.FEMALE : Gender.MALE); + Gender personGender = person.getGender(); + + boolean isNonBinary = (campaign.getCampaignOptions().getNonBinaryDiceSize() > 0) + && (Compute.randomInt(campaign.getCampaignOptions().getNonBinaryDiceSize()) == 0); + + Gender spouseGender = switch (personGender) { + case MALE, OTHER_MALE -> sameSex ? (isNonBinary ? + Gender.OTHER_MALE : Gender.MALE) : (isNonBinary ? Gender.OTHER_FEMALE : Gender.FEMALE); + case FEMALE, OTHER_FEMALE -> sameSex ? (isNonBinary ? + Gender.OTHER_FEMALE : Gender.FEMALE) : (isNonBinary ? Gender.OTHER_MALE : Gender.MALE); + case RANDOMIZE -> RandomGenderGenerator.generate(); + }; List potentialSpouses = new ArrayList<>(); Person spouse = null; if (isInterUnit) { potentialSpouses = campaign.getActivePersonnel().stream() - .filter(potentialSpouse -> isPotentialRandomSpouse(campaign, today, person, potentialSpouse, gender)) + .filter(potentialSpouse -> isPotentialRandomSpouse(campaign, today, person, potentialSpouse, spouseGender)) .toList(); if (!potentialSpouses.isEmpty()) { @@ -360,7 +371,7 @@ protected void marryRandomSpouse(final Campaign campaign, final LocalDate today, } if ((!isInterUnit) || (potentialSpouses.isEmpty())) { - spouse = createExternalSpouse(campaign, today, person, gender); + spouse = createExternalSpouse(campaign, today, person, spouseGender); } marry(campaign, today, person, spouse, MergingSurnameStyle.WEIGHTED, isBackground); diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 2b7a43ad42..0f02e017f5 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -523,8 +523,8 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final // Check if they are already pregnant if (person.isPregnant()) { - // They give birth if the due date is the current day - if (today.isEqual(person.getDueDate())) { + // They give birth if the due date has passed + if ((today.isAfter(person.getDueDate())) || (today.isEqual(person.getDueDate()))) { birth(campaign, today, person); } return; diff --git a/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java b/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java index 1f91ce94a7..5ae14a3e3a 100644 --- a/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/CreateCharacterDialog.java @@ -69,26 +69,26 @@ public enum NameRestrictions { NONE } - private Person person; - private boolean editOrigin; - private boolean editBirthday; - private boolean editGender; + private final Person person; + private final boolean editOrigin; + private final boolean editBirthday; + private final boolean editGender; private boolean limitFaction; - private NameRestrictions nameRestrictions; + private final NameRestrictions nameRestrictions; private String instructions; - private int xpPool; + private final int xpPool; private Portrait portrait; private List optionComps = new ArrayList<>(); - private Map skillLvls = new Hashtable<>(); - private Map skillBonus = new Hashtable<>(); - private Map skillValues = new Hashtable<>(); - private Map skillChks = new Hashtable<>(); + private final Map skillLvls = new Hashtable<>(); + private final Map skillBonus = new Hashtable<>(); + private final Map skillValues = new Hashtable<>(); + private final Map skillChks = new Hashtable<>(); private PersonnelOptions options; private LocalDate birthdate; - private JFrame frame; + private final JFrame frame; private JButton btnDate; private JComboBox choiceGender; @@ -125,7 +125,7 @@ public enum NameRestrictions { private JButton doneButton; - private Campaign campaign; + private final Campaign campaign; private static final ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.CreateCharacterDialog", MekHQ.getMHQOptions().getLocale()); @@ -345,14 +345,9 @@ private JPanel getDemogPanel() { gridBagConstraints.insets = new Insets(0, 5, 0, 0); demogPanel.add(lblGender, gridBagConstraints); - DefaultComboBoxModel genderModel = new DefaultComboBoxModel<>(); - for (Gender gender : Gender.getExternalOptions()) { - genderModel.addElement(gender); - } - choiceGender = new JComboBox<>(genderModel); + choiceGender = new JComboBox<>(Gender.values()); choiceGender.setName("choiceGender"); - choiceGender.setSelectedItem(person.getGender().isExternal() ? person.getGender() - : person.getGender().getExternalVariant()); + choiceGender.setSelectedItem(person.getGender()); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = y; @@ -1454,9 +1449,7 @@ private void done() { ? "" : textBloodname.getText()); person.setBiography(txtBio.getText()); if (choiceGender.getSelectedItem() != null) { - person.setGender(person.getGender().isInternal() - ? ((Gender) choiceGender.getSelectedItem()).getInternalVariant() - : (Gender) choiceGender.getSelectedItem()); + person.setGender((Gender) choiceGender.getSelectedItem()); } person.setBirthday(birthdate); person.setOriginFaction((Faction) choiceFaction.getSelectedItem()); diff --git a/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java b/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java index 7ff3c22737..8570199152 100644 --- a/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/CustomizePersonDialog.java @@ -68,18 +68,18 @@ */ public class CustomizePersonDialog extends JDialog implements DialogOptionListener { //region Variable declarations - private Person person; + private final Person person; private List optionComps = new ArrayList<>(); - private Map skillLvls = new Hashtable<>(); - private Map skillBonus = new Hashtable<>(); - private Map skillValues = new Hashtable<>(); - private Map skillChks = new Hashtable<>(); + private final Map skillLvls = new Hashtable<>(); + private final Map skillBonus = new Hashtable<>(); + private final Map skillValues = new Hashtable<>(); + private final Map skillChks = new Hashtable<>(); private PersonnelOptions options; private LocalDate birthdate; private LocalDate recruitment; private LocalDate lastRankChangeDate; private LocalDate retirement; - private JFrame frame; + private final JFrame frame; private JButton btnDate; private JButton btnServiceDate; @@ -123,7 +123,7 @@ public class CustomizePersonDialog extends JDialog implements DialogOptionListen private MMComboBox comboPersonalityQuirk; private MMComboBox comboIntelligence; - private Campaign campaign; + private final Campaign campaign; private final transient ResourceBundle resourceMap = ResourceBundle.getBundle("mekhq.resources.CustomizePersonDialog", MekHQ.getMHQOptions().getLocale()); @@ -329,14 +329,9 @@ private void initComponents() { gridBagConstraints.insets = new Insets(0, 5, 0, 0); panDemog.add(lblGender, gridBagConstraints); - DefaultComboBoxModel genderModel = new DefaultComboBoxModel<>(); - for (Gender gender : Gender.getExternalOptions()) { - genderModel.addElement(gender); - } - choiceGender = new JComboBox<>(genderModel); + choiceGender = new JComboBox<>(Gender.values()); choiceGender.setName("choiceGender"); - choiceGender.setSelectedItem(person.getGender().isExternal() ? person.getGender() - : person.getGender().getExternalVariant()); + choiceGender.setSelectedItem(person.getGender()); gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = y; @@ -1166,9 +1161,7 @@ private void btnOkActionPerformed(ActionEvent evt) { person.setBiography(txtBio.getText()); if (choiceGender.getSelectedItem() != null) { - person.setGender(person.getGender().isInternal() - ? ((Gender) choiceGender.getSelectedItem()).getInternalVariant() - : (Gender) choiceGender.getSelectedItem()); + person.setGender((Gender) choiceGender.getSelectedItem()); } person.setBirthday(birthdate); diff --git a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java index e1cefe3d70..e119cb17cc 100644 --- a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java @@ -1232,15 +1232,14 @@ private void setValuesFromPerson() { getLblCurrentName().setText(getPerson().getFullName()); // Gender is set based on the person's gender - getComboGender().setSelectedItem(getPerson().getGender().isExternal() ? getPerson().getGender() - : getPerson().getGender().getExternalVariant()); + getComboGender().setSelectedItem(getPerson().getGender()); // Current Callsign is set if applicable if (!StringUtility.isNullOrBlank(getPerson().getCallsign())) { getLblCurrentCallsign().setText(getPerson().getCallsign()); } - // We set the clan personnel value based on whether or not the person is clan personell + // We set the clan personnel value based on whether the person is clan personnel getChkClanPersonnel().setSelected(getPerson().isClanPersonnel()); // Now we figure out the person's origin faction diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index ac54e5501a..fe18f50f59 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -346,9 +346,10 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { //region Life Paths Tab // Personnel Randomization private JCheckBox chkUseDylansRandomXP; - private RandomOriginOptionsPanel randomOriginOptionsPanel; + private JSpinner spnNonBinaryDiceSize; // Random Histories + private RandomOriginOptionsPanel randomOriginOptionsPanel; private JCheckBox chkUseRandomPersonalities; private JCheckBox chkUseSimulatedRelationships; @@ -5017,7 +5018,13 @@ private JPanel createPersonnelRandomizationPanel() { chkUseDylansRandomXP.setToolTipText(resources.getString("chkUseDylansRandomXP.toolTipText")); chkUseDylansRandomXP.setName("chkUseDylansRandomXP"); - randomOriginOptionsPanel = new RandomOriginOptionsPanel(getFrame(), campaign, comboFaction); + JLabel lblNonBinaryDiceSize = new JLabel(resources.getString("lblNonBinaryDiceSize.text")); + lblNonBinaryDiceSize.setToolTipText(resources.getString("lblNonBinaryDiceSize.toolTipText")); + lblNonBinaryDiceSize.setName("lblNonBinaryDiceSize"); + + spnNonBinaryDiceSize = new JSpinner(new SpinnerNumberModel(60, 0, 100000, 1)); + spnNonBinaryDiceSize.setToolTipText(wordWrap(resources.getString("lblNonBinaryDiceSize.toolTipText"))); + spnNonBinaryDiceSize.setName("spnNonBinaryDiceSize"); // Layout the Panel final JPanel panel = new JPanel(); @@ -5032,19 +5039,25 @@ private JPanel createPersonnelRandomizationPanel() { layout.setVerticalGroup( layout.createSequentialGroup() .addComponent(chkUseDylansRandomXP) - .addComponent(randomOriginOptionsPanel) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(lblNonBinaryDiceSize) + .addComponent(spnNonBinaryDiceSize, Alignment.LEADING)) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addComponent(chkUseDylansRandomXP) - .addComponent(randomOriginOptionsPanel) + .addGroup(layout.createSequentialGroup() + .addComponent(lblNonBinaryDiceSize) + .addComponent(spnNonBinaryDiceSize)) ); return panel; } private JPanel createRandomHistoriesPanel() { + randomOriginOptionsPanel = new RandomOriginOptionsPanel(getFrame(), campaign, comboFaction); + chkUseRandomPersonalities = new JCheckBox(resources.getString("chkUseRandomPersonalities.text")); chkUseRandomPersonalities.setToolTipText(resources.getString("chkUseRandomPersonalities.toolTipText")); chkUseRandomPersonalities.setName("chkUseRandomPersonalities"); @@ -5065,12 +5078,14 @@ private JPanel createRandomHistoriesPanel() { layout.setVerticalGroup( layout.createSequentialGroup() + .addComponent(randomOriginOptionsPanel) .addComponent(chkUseRandomPersonalities) .addComponent(chkUseSimulatedRelationships) ); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) + .addComponent(randomOriginOptionsPanel) .addComponent(chkUseRandomPersonalities) .addComponent(chkUseSimulatedRelationships) ); @@ -8204,9 +8219,10 @@ public void setOptions(@Nullable CampaignOptions options, //region Life Paths Tab // Personnel Randomization chkUseDylansRandomXP.setSelected(options.isUseDylansRandomXP()); - randomOriginOptionsPanel.setOptions(options.getRandomOriginOptions()); + spnNonBinaryDiceSize.setValue(options.getNonBinaryDiceSize()); // Random Histories + randomOriginOptionsPanel.setOptions(options.getRandomOriginOptions()); chkUseRandomPersonalities.setSelected(options.isUseRandomPersonalities()); chkUseSimulatedRelationships.setSelected(options.isUseSimulatedRelationships()); @@ -8903,9 +8919,10 @@ public void updateOptions() { //region Life Paths Tab // Personnel Randomization options.setUseDylansRandomXP(chkUseDylansRandomXP.isSelected()); - options.setRandomOriginOptions(randomOriginOptionsPanel.createOptionsFromPanel()); + options.setNonBinaryDiceSize((int) spnNonBinaryDiceSize.getValue()); // Random Histories + options.setRandomOriginOptions(randomOriginOptionsPanel.createOptionsFromPanel()); options.setUseRandomPersonalities(chkUseRandomPersonalities.isSelected()); options.setUseSimulatedRelationships(chkUseSimulatedRelationships.isSelected()); @@ -9569,7 +9586,7 @@ public int getRowHeight(int row) { /* * This table does not use any data from the main TableModel, - * so just return a value based on the row parameter. + * so return a value based on the row parameter. */ @Override public Object getValueAt(int row, int column) { From 183052c0267140a3df8cc83bf1415516f18ba606 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 5 Aug 2024 16:08:25 -0500 Subject: [PATCH 32/41] Refactored Gender Enum and Added Marriage/Children Dice Sizes Updated Gender enum with improved documentation and corrected method comments. Modified GUI to include options for marriage and children interest dice sizes, and adjusted error messages to use contractions for clarity. --- .../CampaignOptionsDialog.properties | 4 + .../resources/mekhq/resources/GUI.properties | 84 +++++++++---------- MekHQ/src/mekhq/campaign/CampaignOptions.java | 26 ++++++ .../generator/DefaultPersonnelGenerator.java | 7 ++ .../mekhq/gui/panes/CampaignOptionsPane.java | 34 ++++++++ 5 files changed, 112 insertions(+), 43 deletions(-) diff --git a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties index 0a95e8cf69..cf27b286d1 100644 --- a/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties +++ b/MekHQ/resources/mekhq/resources/CampaignOptionsDialog.properties @@ -467,6 +467,8 @@ chkUseClanPersonnelMarriages.text=Use Clan Personnel Marriages chkUseClanPersonnelMarriages.toolTipText=Allow clan-origin personnel to marry other personnel. chkUsePrisonerMarriages.text=Use Prisoner Marriages chkUsePrisonerMarriages.toolTipText=Allow prisoners to marry other prisoners, and manually marrying a prisoner to a free member of the force. Bondsmen are treated as free personnel when it comes to this option, and are thus not affected by it. +lblNoInterestInMarriageDiceSize.text=No Interest in Marriage Dice Size +lblNoInterestInMarriageDiceSize.toolTipText=This is the number of sides on the die rolled to determine whether a character has no interest in marriage. This die is rolled when a character is created, with no interest in marriage being determined on a roll of 1. This can be overridden by right-clicking on the character and changing their 'Interested in Marriage' flag. lblCheckMutualAncestorsDepth.text=Minimum Mutual Ancestor Check Depth for Marriage to be Possible lblCheckMutualAncestorsDepth.toolTipText=This is the depth to which the ancestry of two people is checked for mutual ancestors to determine if they can marry.
Set to 0 to disable the ancestry check. chkLogMarriageNameChanges.text=Log Marriage Name Changes @@ -536,6 +538,8 @@ chkDetermineFatherAtBirth.text=Determine Father at Birth instead of Conception chkDetermineFatherAtBirth.toolTipText=The father of a child will be determined based on the spouse at the birth of the child, followed by the spouse at time of conception, followed by nobody.
This is opposed to just using the spouse, if any, at the time of conception. chkDisplayTrueDueDate.text=Display True Due Date chkDisplayTrueDueDate.toolTipText=This displays the actual date the baby will be delivered on the mother's personnel sheet instead of an estimated due date. +lblNoInterestInChildrenDiceSize.text=No Interest in Children Die Size +lblNoInterestInChildrenDiceSize.toolTipText=This is the number of sides on the die rolled to determine whether a character has no interest in children. This die is rolled when creating the character, with no interest occurring on a roll of 1. The results of this roll can be changed by right-clicking on the character and changing the 'Interested in Children' flag. Changing this value to 1 will mean all characters are interested in children. chkUseMaternityLeave.text=Use Automatic Maternity Leave chkUseMaternityLeave.toolTipText=If enabled, pregnant personnel will be placed on maternity leave 20 weeks before they give birth and will not return to active duty until 6 after they have given birth. chkLogProcreation.text=Log Conception and Birth in Personnel and Medical Logs diff --git a/MekHQ/resources/mekhq/resources/GUI.properties b/MekHQ/resources/mekhq/resources/GUI.properties index 894b1743a6..5ee67509c6 100644 --- a/MekHQ/resources/mekhq/resources/GUI.properties +++ b/MekHQ/resources/mekhq/resources/GUI.properties @@ -282,7 +282,7 @@ addMinimumComplement.text=Add minimum complement ##### Base Components - These may originate in MM, but are in active use #### AbstractMHQNagDialog -chkIgnore.text=Do not bother me again +chkIgnore.text=Don't bother me again chkIgnore.toolTipText=If selected, this nag will no longer show until re-enabled under Suite Options. @@ -299,20 +299,20 @@ StandardForceIconDialog.title=Select Force Icon ### UnitIconDialog Class UnitIconDialog.title=Select Unit Icon -UnitIconDialog.btnNone.toolTipText=The unit does not have a unit icon. This will hide all displays of the unit icon outside Campaign Options. +UnitIconDialog.btnNone.toolTipText=The unit doesn't have a unit icon. This will hide all displays of the unit icon outside Campaign Options. #### Nag Dialogs ### InsufficientAstechsNagDialog Class InsufficientAstechsNagDialog.title=Astech Shortage -InsufficientAstechsNagDialog.text=You do not have enough astechs for your techs. You need %d more astech(s). Do you wish to proceed? +InsufficientAstechsNagDialog.text=You don't have enough astechs for your techs. You need %d more astech(s). Do you wish to proceed? ### InsufficientAstechTimeNagDialog Class InsufficientAstechTimeNagDialog.title=Astech Shortage -InsufficientAstechTimeNagDialog.text=You do not have enough remaining astech time for maintenance. You need %d more astech(s). Do you wish to proceed? +InsufficientAstechTimeNagDialog.text=You don't have enough remaining astech time for maintenance. You need %d more astech(s). Do you wish to proceed? ### InsufficientMedicsNagDialog Class InsufficientMedicsNagDialog.title=Medic Shortage -InsufficientMedicsNagDialog.text=You do not have enough medics for your doctors. You need %d more medic(s). Do you wish to proceed? +InsufficientMedicsNagDialog.text=You don't have enough medics for your doctors. You need %d more medic(s). Do you wish to proceed? ### OutstandingScenariosNagDialog Class OutstandingScenariosNagDialog.title=Pending Battle @@ -320,7 +320,7 @@ OutstandingScenariosNagDialog.text=You have a pending battle. Failure to deploy ### ShortDeploymentNagDialog Class ShortDeploymentNagDialog.title=Unmet Deployment Requirements -ShortDeploymentNagDialog.text=You have not met the deployment levels required by your contracts. Do you really wish to advance the day? +ShortDeploymentNagDialog.text=You haven't met the deployment levels required by your contracts. Do you really wish to advance the day? ### UnmaintainedUnitsNagDialog Class UnmaintainedUnitsNagDialog.title=Unmaintained Units @@ -356,12 +356,12 @@ InvalidFactionNagDialog.text=Your campaign faction is invalid. Either it has not ### UnableToAffordExpensesNagDialog Class UnableToAffordExpensesNagDialog.title=Unable to Afford Expenses -UnableToAffordExpensesNagDialog.text=Payday is due tomorrow, but you cannot afford to cover all expenses.\n\nAdvance day anyway? +UnableToAffordExpensesNagDialog.text=Payday is due tomorrow, but you can't afford to cover all expenses.\n\nAdvance day anyway? ### UnableToAffordJumpNagDialog Class UnableToAffordJumpNagDialog.title=Unable to Afford Jump -UnableToAffordJumpNagDialog.text=You are unable to afford your next jump.\n\nAdvance day anyway? +UnableToAffordJumpNagDialog.text=You're unable to afford your next jump.\n\nAdvance day anyway? #### Report Dialogs ### CargoReportDialog Class @@ -456,7 +456,7 @@ chkSpecifyFaction.text=Specify Starting Faction chkSpecifyFaction.toolTipText=This allows you to specify the faction a campaign will start with. The default starting faction is Mercenary. chkSpecifyPlanet.text=Specify Starting Planet chkSpecifyPlanet.toolTipText=This allows you to specify the starting planet for a campaign. The default starting planet is otherwise the starting planet per faction as per /data/universe/factions.xml. -chkStartingSystemFactionSpecific.toolTipText=Filter the starting planet options, so they are specific to the selected starting faction. +chkStartingSystemFactionSpecific.toolTipText=Filter the starting planet options, so they're specific to the selected starting faction. comboStartingSystem.toolTipText=This is the system to select the starting planet from. comboStartingPlanet.toolTipText=This is the planet the campaign will start at. chkSpecifyRankSystem.text=Specify Rank System @@ -480,7 +480,7 @@ btnGameOptions.toolTipText=This lets you view the current MegaMek game options. chkSpecifyCampaignOptions.text=Specify Campaign Options chkSpecifyCampaignOptions.toolTipText=This allows you to specify the MekHQ campaign options. If this is left empty, the default options will be kept. ## Button Actions -blankPresetName.text=The entered preset name cannot be blank. +blankPresetName.text=The entered preset name can't be blank. nullFactionSpecified.text=The specified faction is non-existent. Do you want to continue ignoring the faction specification? nullPlanetSpecified.text=The specified planet is non-existent. Do you want to continue ignoring the planet specification? nullRankSystemSpecified.text=The specified rank system is non-existent. Do you want to continue ignoring the rank system specification? @@ -490,7 +490,7 @@ CustomRankSystemCreationDialog.title=Custom Rank System Creation lblRankSystemCode.text=Rank System Code lblRankSystemCode.toolTipText=This is the internal code used to process rank systems. This should be a handful of capital letters, although they will be capitalized automatically if this is missed. lblRankSystemName.text=Rank System Name -lblRankSystemName.toolTipText=This is the name of the rank system. It cannot be blank. +lblRankSystemName.toolTipText=This is the name of the rank system. It can't be blank. lblRankSystemDescription.text=Rank System Description lblRankSystemDescription.toolTipText=This is a description of the rank system. chkUseROMDesignation.text=Use ROM Designation @@ -498,12 +498,12 @@ chkUseROMDesignation.toolTipText=The rank system uses ComStar's ROM branch desig chkUseManeiDomini.text=Use Manei Domini Class/Rank chkUseManeiDomini.toolTipText=The rank system uses the Word of Blake's Manei Domini Class and Rank designations. lblRankSystemType.text=Rank System Type -lblRankSystemType.toolTipText=This is the type for the rank system, which is used to determine how they are saved and processed. +lblRankSystemType.toolTipText=This is the type for the rank system, which is used to determine how they're saved and processed. chkSwapToRankSystem.text=Swap to Rank System upon Creation chkSwapToRankSystem.toolTipText=This will swap you to having this rank system when working with rank systems. -CustomRankSystemCreationDialog.BlankRankSystemCode.text=The entered rank system code cannot be blank. -CustomRankSystemCreationDialog.BlankRankSystemName.text=The entered rank system name cannot be blank. -CustomRankSystemCreationDialog.DuplicateCode.text=The entered rank system code cannot duplicate an existing code, as all rank systems must have a unique system code. +CustomRankSystemCreationDialog.BlankRankSystemCode.text=The entered rank system code can't be blank. +CustomRankSystemCreationDialog.BlankRankSystemName.text=The entered rank system name can't be blank. +CustomRankSystemCreationDialog.DuplicateCode.text=The entered rank system code can't duplicate an existing code, as all rank systems must have a unique system code. ### DataLoadingDialog Class DataLoadingDialog.title=Data Loading @@ -521,13 +521,13 @@ applyingLoadedCampaign.text=Applying Loaded Campaign... DataLoadingDialog.progress.accessibleDescription=%s Please Wait. ## Exception Messages DataLoadingDialog.NullEntityException.title=Unit Loading Error(s) -DataLoadingDialog.NullEntityException.text=The following units could not be loaded by the campaign: \n%s \n\nPlease be sure to copy over any custom units before starting a new version of MekHQ. \nIf you believe the units listed are not customs, then try deleting the file data/mechfiles/units.cache and restarting MekHQ. \nIt is also possible that unit chassi and model names have changed across versions of MegaMek. You can check this by opening up MegaMek and searching for the units. Chassis and models can be edited in your MekHQ save file with a text editor. +DataLoadingDialog.NullEntityException.text=The following units couldn't be loaded by the campaign: \n%s \n\nPlease be sure to copy over any custom units before starting a new version of MekHQ. \nIf you believe the units listed aren't customs, then try deleting the file data/mechfiles/units.cache and restarting MekHQ. \nIt is also possible that unit chassi and model names have changed across versions of MegaMek. You can check this by opening up MegaMek and searching for the units. Chassis and models can be edited in your MekHQ save file with a text editor. DataLoadingDialog.NullPointerException.title=Error Loading Academies -DataLoadingDialog.NullPointerException.text=The following academies could not be loaded by the campaign: \n%s \n\nPlease be sure to copy over any custom academy sets before starting a new version of MekHQ. \n\nIf you believe the academies listed are not customs, then please load your campaign into the last working version of MekHQ and set all students attending the affected academy to the 'Active' status. +DataLoadingDialog.NullPointerException.text=The following academies couldn't be loaded by the campaign: \n%s \n\nPlease be sure to copy over any custom academy sets before starting a new version of MekHQ. \n\nIf you believe the academies listed are not customs, then please load your campaign into the last working version of MekHQ and set all students attending the affected academy to the 'Active' status. DataLoadingDialog.OutOfMemoryError.title=Not Enough Memory -DataLoadingDialog.OutOfMemoryError.text=MekHQ ran out of memory attempting to load the campaign file. \nTry increasing the memory allocated to MekHQ and reloading. \nSee the FAQ at http://megamek.org/ for details. +DataLoadingDialog.OutOfMemoryError.text=MekHQ ran out of memory attempting to load the campaign file. \nTry increasing the memory allocated to MekHQ and reloading. \nSee the FAQ at https://megamek.org/ for details. DataLoadingDialog.ExecutionException.title=Campaign Loading Error -DataLoadingDialog.ExecutionException.text=The campaign file could not be loaded. \nPlease check the MekHQ.log file for details. +DataLoadingDialog.ExecutionException.text=The campaign file couldn't be loaded. \nPlease check the MekHQ.log file for details. ### GMToolsDialog Class GMToolsDialog.title=GM Tools @@ -551,7 +551,7 @@ lblWeight.text=Weight btnRollRAT.text=Roll For RAT btnRollRAT.toolTipText=Roll a unit on the selected RATs or the force generator (based on Campaign Options settings) using the provided values. btnAddUnit.text=Add Unit -btnAddUnit.toolTipText=Add the unit to the campaign at no cost, assigning them to the current person if loaded with a person, and they do not have a unit assigned. +btnAddUnit.toolTipText=Add the unit to the campaign at no cost, assigning them to the current person if loaded with a person, and they don't have a unit assigned. invalidYear.error=Please enter a valid year noValidUnit.error=No unit matching criteria and purchase restrictions. entityLoadFailure.error=Failed to load entity %s from %s @@ -675,8 +675,6 @@ optionHealedInjuriesForeground.text=Healed Injuries Foreground optionHealedInjuriesBackground.text=Healed Injuries Background optionPregnantForeground.text=Pregnant Foreground optionPregnantBackground.text=Pregnant Background -optionPaidRetirementForeground.text=Paid Retirement Foreground -optionPaidRetirementBackground.text=Paid Retirement Background optionStratConHexCoordForeground.text=StratCon Hex Coordinate Foreground optionFontColorNegative.text=Font Color Negative Event optionFontColorWarning.text=Font Color Warning @@ -723,11 +721,11 @@ optionPregnantCombatantNag.toolTipText=This allows you to ignore the daily warni optionPrisonersNag.text=Hide Prisoners of War Nag optionPrisonersNag.toolTipText=This allows you to ignore the daily warning for when you have prisoners of war outside of a contract. optionUntreatedPersonnelNag.text=Hide Untreated Personnel Nag -optionUntreatedPersonnelNag.toolTipText=This allows you to ignore the daily warning for when you have wounded personnel that have not been assigned to a doctor. +optionUntreatedPersonnelNag.toolTipText=This allows you to ignore the daily warning for when you've wounded personnel that haven't been assigned to a doctor. optionNoCommanderNag.text=Hide No Commander Nag -optionNoCommanderNag.toolTipText=This allows you to ignore the daily warning for when you do not have someone assigned as the overall force commander. +optionNoCommanderNag.toolTipText=This allows you to ignore the daily warning for when you don't have someone assigned as the overall force commander. optionContractEndedNag.text=Hide Contract Ended Nag -optionContractEndedNag.toolTipText=This allows you to ignore the daily warning for when you do not have a completed contract still active in the briefing tab. +optionContractEndedNag.toolTipText=This allows you to ignore the daily warning for when you don't have a completed contract still active in the briefing tab. optionInsufficientAstechsNag.text=Hide Insufficient Astechs Nag optionInsufficientAstechsNag.toolTipText=This allows you to ignore the daily warning for when you don't have enough astechs to support your techs. optionInsufficientAstechTimeNag.text=Hide Insufficient Astech Time Nag @@ -743,7 +741,7 @@ optionOutstandingScenariosNag.toolTipText=This allows you to ignore the daily wa optionInvalidFactionNag.text=Hide Invalid Faction Nag optionInvalidFactionNag.toolTipText=This allows you to ignore the daily warning for having an invalid faction. optionUnableToAffordExpensesNag.text=Hide Unable to Afford Expenses Nag -optionUnableToAffordExpensesNag.toolTipText=This allows you to ignore the monthly warning for having insufficient funds to cover all expenses. +optionUnableToAffordExpensesNag.toolTipText=This allows you to ignore the monthly warning for having not enough funds to cover all expenses. optionUnableToAffordJumpNag.text=Hide Unable to Afford Next Jump Nag optionUnableToAffordJumpNag.toolTipText=This allows you to ignore the daily warning when unable to afford a jump. ## Miscellaneous Tab @@ -752,7 +750,7 @@ lblUserDir.text=User Files Directory: lblUserDir.toolTipText=Use this directory for resources you want to share between different installations or versions of MegaMek, MegaMekLab and MekHQ. Fonts, units, camos, portraits and fluff images will also be loaded from this directory.
Note: Inside the user directory, use the directory structure of MM/MML/MHQ for camos, portraits and fluff images, i.e. data/images/camo, data/images/portraits and data/images/fluff/.
Fonts and units can be placed anywhere in the user directory. userDirChooser.title=Choose User Data Folder lblStartGameDelay.text=Start Game Base Delay (ms) -lblStartGameDelay.toolTipText=This is the base start game delay, in milliseconds.
Increase this value when settings are not being set properly, the board isn't being loaded, and / or planetary conditions aren't loading properly.
This is limited to values between 250 and 2,500, with a default value of 1,000. +lblStartGameDelay.toolTipText=This is the base start game delay, in milliseconds.
Increase this value when settings aren't being set properly, the board isn't being loaded, and / or planetary conditions aren't loading properly.
This is limited to values between 250 and 2,500, with a default value of 1,000. lblStartGameClientDelay.text=Start Game Client Delay (ms) lblStartGameClientDelay.toolTipText=Client start game delay time in milliseconds.
Increase this value when the "Client has not finished initialization, and is currently in an unknown phase" error message is repeatedly logged without progressing past that point.
If this causes timeout issues, decrease this value and increase the client retry count instead.
This is limited to values between 50 and 2,500, with a default value of 50. lblStartGameClientRetryCount.text=Start Game Client Retry Count @@ -874,27 +872,27 @@ PersonnelFilter.FOUNDER.toolTipText=Display personnel with the Founder tag. PersonnelFilter.PRISONER.text=Prisoners PersonnelFilter.PRISONER.toolTipText=Display prisoners and bondsmen. PersonnelFilter.INACTIVE.text=Inactive Personnel -PersonnelFilter.INACTIVE.toolTipText=Display personnel who are currently inactive. +PersonnelFilter.INACTIVE.toolTipText=Display personnel who're currently inactive. PersonnelFilter.ON_LEAVE.text=Personnel on Leave PersonnelFilter.ON_LEAVE.toolTipText=Display personnel who are currently on leave. PersonnelFilter.MIA.text=MIA & PoW Personnel -PersonnelFilter.MIA.toolTipText=Display personnel who are currently missing in action or prisoners of the enemy. +PersonnelFilter.MIA.toolTipText=Display personnel who're currently missing in action or prisoners of the enemy. PersonnelFilter.RETIRED.text=Retired Personnel PersonnelFilter.RETIRED.toolTipText=Display retired personnel. PersonnelFilter.RESIGNED.text=Resigned Personnel -PersonnelFilter.RESIGNED.toolTipText=Display personnel who have resigned. +PersonnelFilter.RESIGNED.toolTipText=Display personnel who've resigned. PersonnelFilter.DESERTED.text=Deserters & Defectors PersonnelFilter.DESERTED.toolTipText=Display former personnel who deserted or defected. PersonnelFilter.AWOL.text=AWOL Personnel -PersonnelFilter.AWOL.toolTipText=Display personnel who are currently AWOL. +PersonnelFilter.AWOL.toolTipText=Display personnel who're currently AWOL. PersonnelFilter.STUDENT.text=Students PersonnelFilter.STUDENT.toolTipText=Display personnel that are currently undergoing a period of education or training PersonnelFilter.MISSING.text=Missing PersonnelFilter.MISSING.toolTipText=Display personnel that are currently missing PersonnelFilter.KIA.text=Rolls of Honor -PersonnelFilter.KIA.toolTipText=Display personnel who have been killed in action. +PersonnelFilter.KIA.toolTipText=Display personnel who've been killed in action. PersonnelFilter.DEAD.text=Cemetery -PersonnelFilter.DEAD.toolTipText=Display personnel who have passed away. +PersonnelFilter.DEAD.toolTipText=Display personnel who've passed away. #### PersonnelFilterStyle Enum PersonnelFilterStyle.STANDARD.text=Standard @@ -963,9 +961,9 @@ PersonnelTableModelColumn.DEATH_DATE.text=Death Date PersonnelTableModelColumn.COMMANDER.text=Commander PersonnelTableModelColumn.FOUNDER.text=Founder PersonnelTableModelColumn.CLAN_PERSONNEL.text=Clan Personnel -PersonnelTableModelColumn.MARRIAGEABLE.text=Marriageable +PersonnelTableModelColumn.MARRIAGEABLE.text=Interested in Marriage PersonnelTableModelColumn.DIVORCEABLE.text=Divorceable -PersonnelTableModelColumn.TRYING_TO_CONCEIVE.text=Trying to Conceive +PersonnelTableModelColumn.TRYING_TO_CONCEIVE.text=Interested in Children PersonnelTableModelColumn.IMMORTAL.text=Immortal PersonnelTableModelColumn.TOUGHNESS.text=Toughness PersonnelTableModelColumn.FATIGUE.text=Fatigue @@ -1092,11 +1090,11 @@ lblLanceSize.toolTipText=The number of BattleMechs to generate per lance, from 3 ### Personnel Panel personnelPanel.title=Personnel lblTotalSupportPersonnel.text=Number of Support Personnel: %d -lblTotalSupportPersonnel.toolTipText=This is the maximum number of starting support personnel for the force. This does not include assistants. +lblTotalSupportPersonnel.toolTipText=This is the maximum number of starting support personnel for the force. This doesn't include assistants. supportPersonnelNumbersPanel.title=Support Personnel Assignment supportPersonnelNumber.toolTipText=The number of %s(s) to hire. chkPoolAssistants.text=Pool Assistants -chkPoolAssistants.toolTipText=Automatically fills the unit's astech and medic pools, otherwise they are hired as permanent members of the unit. +chkPoolAssistants.toolTipText=Automatically fills the unit's astech and medic pools, otherwise they're hired as permanent members of the unit. chkGenerateCaptains.text=Generate Captains chkGenerateCaptains.toolTipText=This creates Captains for every company after the first, or for every company when using a mercenary company command lance.
They have two officer skill increases, and are assigned the rank of Captain. chkAssignCompanyCommanderFlag.text=Assign Commander Flag @@ -1118,7 +1116,7 @@ chkAutomaticallyAssignRanks.toolTipText=This automatically assigns ranks t chkUseSpecifiedFactionToAssignRanks.text=Use Specified Faction to Assign Ranks chkUseSpecifiedFactionToAssignRanks.toolTipText=This uses the specified faction to assign ranks instead of the campaign's faction. chkAssignMechWarriorsCallsigns.text=Assign MekWarriors Callsigns -chkAssignMechWarriorsCallsigns.toolTipText=This automatically assigns MekWarriors callsigns, provided they are not Clan Mekwarriors. +chkAssignMechWarriorsCallsigns.toolTipText=This automatically assigns MekWarriors callsigns, provided they aren't Clan Mekwarriors. chkAssignFounderFlag.text=Assign Founder Flag chkAssignFounderFlag.toolTipText=This automatically applies the founder flag to all generated personnel. ### Starting Simulation Panel @@ -1220,7 +1218,7 @@ chkPayForSetup.toolTipText=Pay for the generated unit from the starting cash, to chkPayForPersonnel.text=Pay for Personnel chkPayForPersonnel.toolTipText=Pay to hire personnel, at the standard hiring rate of two-month salary. chkPayForUnits.text=Pay for Units -chkPayForUnits.toolTipText=Pay for units, at either their full purchase cost or half of it if they are a person's attached unit. +chkPayForUnits.toolTipText=Pay for units, at either their full purchase cost or half of it if they're a person's attached unit. chkPayForParts.text=Pay for Parts chkPayForParts.toolTipText=Pay for the spare parts generated, if any are generated. chkPayForArmour.text=Pay for Armour @@ -1259,7 +1257,7 @@ chkRandomizeDependentsOrigin.text=Randomize Origin for Dependents chkRandomizeDependentsOrigin.toolTipText=Dependents have their origins randomized so that they don't come from the current planet and the campaign's faction
but instead have origins randomized in the same way as standard personnel. chkRandomizeAroundSpecifiedPlanet.text=Randomize Around Specified Planet chkRandomizeAroundSpecifiedPlanet.toolTipText=This randomizes the personnel around a specified planet instead of the current planet, which allows one to have a company generated from within a specified region around that planet. -chkSpecifiedSystemFactionSpecific.toolTipText=Filter the specified planet options, so they are specific to the faction selected. +chkSpecifiedSystemFactionSpecific.toolTipText=Filter the specified planet options, so they're specific to the faction selected. lblSpecifiedPlanet.text=Specified Planet lblSpecifiedPlanet.toolTipText=This is the specified planet around which personnel are randomized. comboSpecifiedSystem.toolTipText=This is the system from which to select the specified planet around which origin planet and faction are randomized. @@ -1268,7 +1266,7 @@ lblOriginSearchRadius.toolTipText=This is the radius in light years from the cur lblOriginDistanceScale.text=Origin Distance Scale lblOriginDistanceScale.toolTipText=A scaling factor to apply to planetary distances during weighting when randomizing the faction and planetary origins.
Values above 1.0 prefer the current location, while values closer to 0.1 spread out the faction selection. chkAllowClanOrigins.text=Clan Origin Faction Generated for Non-Clan Factions -chkAllowClanOrigins.toolTipText=Generate Clan origin factions for factions that are not tagged as Clan. +chkAllowClanOrigins.toolTipText=Generate Clan origin factions for factions that aren't tagged as Clan. chkExtraRandomOrigin.text=Extra Random Planetary Origin chkExtraRandomOrigin.toolTipText=Random origin is randomized to the planetary level when selected, rather than just randomizing to the system level
(with the planet being the primary planet). ### Option Validation Warnings @@ -1286,7 +1284,7 @@ btnLoadStoryArc.text=Load a Story Arc ### Rank System rankSystemPanel.title=Rank System txtInstructionsRanks.title=Customizing Ranks -txtInstructionsRanks.text=You can use the table here to assign ranks for your campaign. You can use one of the preset rank systems from the pull-down menu, or you can design your own by creating a custom rank system. \nYou can save a single rank system as part of the campaign, with any additional custom rank systems to be saved in the user data file instead. Any additional campaign rank systems will be deleted. \nYou can also assign custom multipliers for salary. These multipliers do not need to take into account the officer multiplier which is addressed elsewhere. \n\nWARNING: \n1) This dialog does not warn about the deletion of any campaign custom rank systems that are not the selected rank system for the campaign at this time. \n2) All personnel ranks will be revalidated when this is changed, to migrate them to the proper setup for their new rank system. \n3) This dialog does not validate the data at this time, so be careful with circular logic and ensure you have a valid E0 rank (one MUST be a name like "None" or "Grunt", with "None" specifically handled in code to show as a blank string when the rank name is displayed). +txtInstructionsRanks.text=You can use the table here to assign ranks for your campaign. You can use one of the preset rank systems from the pull-down menu, or you can design your own by creating a custom rank system. \nYou can save a single rank system as part of the campaign, with any additional custom rank systems to be saved in the user data file instead. Any additional campaign rank systems will be deleted. \nYou can also assign custom multipliers for salary. These multipliers don't need to take into account the officer multiplier which is addressed elsewhere. \n\nWARNING: \n1) This dialog doesn't warn about the deletion of any campaign custom rank systems that aren't the selected rank system for the campaign at this time. \n2) All personnel ranks will be revalidated when this is changed, to migrate them to the proper setup for their new rank system. \n3) This dialog does not validate the data at this time, so be careful with circular logic and ensure you have a valid E0 rank (one MUST be a name like "None" or "Grunt", with "None" specifically handled in code to show as a blank string when the rank name is displayed). lblRankSystem.text=Rank System lblRankSystem.toolTipText=This is the standard rank system used in this campaign. comboRankSystemType.toolTipText=This is the type of rank system selected, which is where the information about the rank system is stored. @@ -1303,7 +1301,7 @@ btnExportRankSystems.toolTipText=This exports all rank systems to a specif btnImportIndividualRankSystem.text=Import Individual Rank System btnImportIndividualRankSystem.toolTipText=This imports an individual rank system from a selected file.
This is loaded as an option for ranks, and in the style of a campaign custom rank system.
This can then be stored in user data by converting the system into a user data rank system before exporting it as part of exporting the user data rank systems. btnImportRankSystems.text=Import Rank Systems -btnImportRankSystems.toolTipText=This bulk imports rank systems from a selected file. They are not saved to the user data file and will be discarded
unless they are either selected for the campaign (which saves the single selected one with the campaign)
or are individually converted into user data rank systems and then exported as part of exporting the user data rank systems. +btnImportRankSystems.toolTipText=This bulk imports rank systems from a selected file. They aren't saved to the user data file and will be discarded
unless they're either selected for the campaign (which saves the single selected one with the campaign)
or are individually converted into user data rank systems and then exported as part of exporting the user data rank systems. btnRefreshRankSystemsFromFile.text=Refresh Rank Systems From Files btnRefreshRankSystemsFromFile.toolTipText=This clears and does a complete reload of ranks from file, updating the GUI and rerunning rank validation for all personnel. diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 67a3cf2e4a..9f7282d3b4 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -294,6 +294,7 @@ public static String getTransitUnitName(final int unit) { private boolean useClanPersonnelMarriages; private boolean usePrisonerMarriages; private int checkMutualAncestorsDepth; + private int noInterestInMarriageDiceSize; private boolean logMarriageNameChanges; private Map marriageSurnameWeights; private RandomMarriageMethod randomMarriageMethod; @@ -328,6 +329,7 @@ public static String getTransitUnitName(final int unit) { private boolean useMaternityLeave; private boolean determineFatherAtBirth; private boolean displayTrueDueDate; + private int noInterestInChildrenDiceSize; private boolean logProcreation; private RandomProcreationMethod randomProcreationMethod; private boolean useRelationshiplessRandomProcreation; @@ -852,6 +854,7 @@ public CampaignOptions() { setUseClanPersonnelMarriages(false); setUsePrisonerMarriages(true); setCheckMutualAncestorsDepth(4); + setNoInterestInMarriageDiceSize(10); setLogMarriageNameChanges(false); setMarriageSurnameWeights(new HashMap<>()); getMarriageSurnameWeights().put(MergingSurnameStyle.NO_CHANGE, 100); @@ -902,6 +905,7 @@ public CampaignOptions() { setUseMaternityLeave(true); setDetermineFatherAtBirth(false); setDisplayTrueDueDate(false); + setNoInterestInChildrenDiceSize(3); setLogProcreation(false); setRandomProcreationMethod(RandomProcreationMethod.NONE); setUseRelationshiplessRandomProcreation(false); @@ -2335,6 +2339,14 @@ public void setCheckMutualAncestorsDepth(final int checkMutualAncestorsDepth) { this.checkMutualAncestorsDepth = checkMutualAncestorsDepth; } + public int getNoInterestInMarriageDiceSize() { + return noInterestInMarriageDiceSize; + } + + public void setNoInterestInMarriageDiceSize(final int noInterestInMarriageDiceSize) { + this.noInterestInMarriageDiceSize = noInterestInMarriageDiceSize; + } + /** * @return whether to log a name change in a marriage */ @@ -2656,6 +2668,14 @@ public void setDisplayTrueDueDate(final boolean displayTrueDueDate) { this.displayTrueDueDate = displayTrueDueDate; } + public int getNoInterestInChildrenDiceSize() { + return noInterestInChildrenDiceSize; + } + + public void setNoInterestInChildrenDiceSize(final int noInterestInChildrenDiceSize) { + this.noInterestInChildrenDiceSize = noInterestInChildrenDiceSize; + } + /** * @return whether to log procreation */ @@ -4782,6 +4802,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useClanPersonnelMarriages", isUseClanPersonnelMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "usePrisonerMarriages", isUsePrisonerMarriages()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "checkMutualAncestorsDepth", getCheckMutualAncestorsDepth()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "noInterestInMarriageDiceSize", getNoInterestInMarriageDiceSize()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "logMarriageNameChanges", isLogMarriageNameChanges()); MHQXMLUtility.writeSimpleXMLOpenTag(pw, indent++, "marriageSurnameWeights"); for (final Entry entry : getMarriageSurnameWeights().entrySet()) { @@ -4825,6 +4846,7 @@ public void writeToXml(final PrintWriter pw, int indent) { MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useMaternityLeave", isUseMaternityLeave()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "determineFatherAtBirth", isDetermineFatherAtBirth()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "displayTrueDueDate", isDisplayTrueDueDate()); + MHQXMLUtility.writeSimpleXMLTag(pw, indent, "noInterestInChildrenDiceSize", getNoInterestInChildrenDiceSize()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "logProcreation", isLogProcreation()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "randomProcreationMethod", getRandomProcreationMethod().name()); MHQXMLUtility.writeSimpleXMLTag(pw, indent, "useRelationshiplessRandomProcreation", isUseRelationshiplessRandomProcreation()); @@ -5498,6 +5520,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUsePrisonerMarriages(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("checkMutualAncestorsDepth")) { retVal.setCheckMutualAncestorsDepth(Integer.parseInt(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("noInterestInMarriageDiceSize")) { + retVal.setNoInterestInMarriageDiceSize(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("logMarriageNameChanges")) { retVal.setLogMarriageNameChanges(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("marriageSurnameWeights")) { @@ -5594,6 +5618,8 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setDetermineFatherAtBirth(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("displayTrueDueDate")) { retVal.setDisplayTrueDueDate(Boolean.parseBoolean(wn2.getTextContent().trim())); + } else if (wn2.getNodeName().equalsIgnoreCase("noInterestInChildrenDiceSize")) { + retVal.setNoInterestInChildrenDiceSize(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("logProcreation")) { retVal.setLogProcreation(Boolean.parseBoolean(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("randomProcreationMethod")) { diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java index b5a331a776..8c45b98a6f 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java @@ -108,6 +108,13 @@ public Person generate(Campaign campaign, PersonnelRole primaryRole, PersonnelRo specialAbilityGenerator.generateSpecialAbilities(campaign, person, expLvl); } + // set interest in marriage and children flags + int interestInMarriageDiceSize = campaign.getCampaignOptions().getNoInterestInMarriageDiceSize(); + person.setMarriageable(((interestInMarriageDiceSize != 0) && (Compute.randomInt(interestInMarriageDiceSize)) != 0)); + + int interestInChildren = campaign.getCampaignOptions().getNoInterestInChildrenDiceSize(); + person.setTryingToConceive(((interestInChildren != 0) && (Compute.randomInt(interestInChildren)) != 0)); + // Do naming at the end, to ensure the keys are set generateNameAndGender(campaign, person, gender); diff --git a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java index fe18f50f59..2a648a4471 100644 --- a/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java +++ b/MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java @@ -358,6 +358,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkUseClanPersonnelMarriages; private JCheckBox chkUsePrisonerMarriages; private JSpinner spnCheckMutualAncestorsDepth; + private JSpinner spnNoInterestInMarriageDiceSize; private JCheckBox chkLogMarriageNameChanges; private Map spnMarriageSurnameWeights; private MMComboBox comboRandomMarriageMethod; @@ -391,6 +392,7 @@ public class CampaignOptionsPane extends AbstractMHQTabbedPane { private JCheckBox chkAssignChildrenOfFoundersFounderTag; private JCheckBox chkDetermineFatherAtBirth; private JCheckBox chkDisplayTrueDueDate; + private JSpinner spnNoInterestInChildrenDiceSize; private JCheckBox chkUseMaternityLeave; private JCheckBox chkLogProcreation; private MMComboBox comboRandomProcreationMethod; @@ -5582,6 +5584,14 @@ private JPanel createMarriagePanel() { chkUseRandomPrisonerMarriages.setEnabled(!method.isNone() && chkUsePrisonerMarriages.isSelected()); }); + final JLabel lblNoInterestInMarriageDiceSize = new JLabel(resources.getString("lblNoInterestInMarriageDiceSize.text")); + lblNoInterestInMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblNoInterestInMarriageDiceSize.toolTipText"))); + lblNoInterestInMarriageDiceSize.setName("lblNoInterestInMarriageDiceSize"); + + spnNoInterestInMarriageDiceSize = new JSpinner(new SpinnerNumberModel(10, 1, 100000, 1)); + spnNoInterestInMarriageDiceSize.setToolTipText(wordWrap(resources.getString("lblNoInterestInMarriageDiceSize.toolTipText"))); + spnNoInterestInMarriageDiceSize.setName("spnNoInterestInMarriageDiceSize"); + final JLabel lblCheckMutualAncestorsDepth = new JLabel(resources.getString("lblCheckMutualAncestorsDepth.text")); lblCheckMutualAncestorsDepth.setToolTipText(resources.getString("lblCheckMutualAncestorsDepth.toolTipText")); lblCheckMutualAncestorsDepth.setName("lblCheckMutualAncestorsDepth"); @@ -5616,6 +5626,9 @@ private JPanel createMarriagePanel() { .addComponent(chkUseManualMarriages) .addComponent(chkUseClanPersonnelMarriages) .addComponent(chkUsePrisonerMarriages) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(lblNoInterestInMarriageDiceSize) + .addComponent(spnNoInterestInMarriageDiceSize, Alignment.LEADING)) .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(lblCheckMutualAncestorsDepth) .addComponent(spnCheckMutualAncestorsDepth, Alignment.LEADING)) @@ -5629,6 +5642,9 @@ private JPanel createMarriagePanel() { .addComponent(chkUseManualMarriages) .addComponent(chkUseClanPersonnelMarriages) .addComponent(chkUsePrisonerMarriages) + .addGroup(layout.createSequentialGroup() + .addComponent(lblNoInterestInMarriageDiceSize) + .addComponent(spnNoInterestInMarriageDiceSize)) .addGroup(layout.createSequentialGroup() .addComponent(lblCheckMutualAncestorsDepth) .addComponent(spnCheckMutualAncestorsDepth)) @@ -6132,6 +6148,14 @@ public Component getListCellRendererComponent(final JList list, final Object chkDisplayTrueDueDate.setToolTipText(resources.getString("chkDisplayTrueDueDate.toolTipText")); chkDisplayTrueDueDate.setName("chkDisplayTrueDueDate"); + final JLabel lblNoInterestInChildrenDiceSize = new JLabel(resources.getString("lblNoInterestInChildrenDiceSize.text")); + lblNoInterestInChildrenDiceSize.setToolTipText(wordWrap(resources.getString("lblNoInterestInChildrenDiceSize.toolTipText"))); + lblNoInterestInChildrenDiceSize.setName("lblNoInterestInChildrenDiceSize"); + + spnNoInterestInChildrenDiceSize = new JSpinner(new SpinnerNumberModel(3, 1, 100000, 1)); + spnNoInterestInChildrenDiceSize.setToolTipText(wordWrap(resources.getString("lblNoInterestInChildrenDiceSize.toolTipText"))); + spnNoInterestInChildrenDiceSize.setName("spnNoInterestInChildrenDiceSize"); + chkUseMaternityLeave = new JCheckBox(resources.getString("chkUseMaternityLeave.text")); chkUseMaternityLeave.setToolTipText(wordWrap(resources.getString("chkUseMaternityLeave.toolTipText"))); chkUseMaternityLeave.setName("chkUseMaternityLeave"); @@ -6172,6 +6196,9 @@ public Component getListCellRendererComponent(final JList list, final Object .addComponent(chkAssignChildrenOfFoundersFounderTag) .addComponent(chkDetermineFatherAtBirth) .addComponent(chkDisplayTrueDueDate) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(lblNoInterestInChildrenDiceSize) + .addComponent(spnNoInterestInChildrenDiceSize, Alignment.LEADING)) .addComponent(chkUseMaternityLeave) .addComponent(chkLogProcreation) .addComponent(randomProcreationPanel) @@ -6193,6 +6220,9 @@ public Component getListCellRendererComponent(final JList list, final Object .addComponent(chkAssignChildrenOfFoundersFounderTag) .addComponent(chkDetermineFatherAtBirth) .addComponent(chkDisplayTrueDueDate) + .addGroup(layout.createSequentialGroup() + .addComponent(lblNoInterestInChildrenDiceSize) + .addComponent(spnNoInterestInChildrenDiceSize)) .addComponent(chkUseMaternityLeave) .addComponent(chkLogProcreation) .addComponent(randomProcreationPanel) @@ -8238,6 +8268,7 @@ public void setOptions(@Nullable CampaignOptions options, chkUseManualMarriages.setSelected(options.isUseManualMarriages()); chkUseClanPersonnelMarriages.setSelected(options.isUseClanPersonnelMarriages()); chkUsePrisonerMarriages.setSelected(options.isUsePrisonerMarriages()); + spnNoInterestInMarriageDiceSize.setValue(options.getNoInterestInMarriageDiceSize()); spnCheckMutualAncestorsDepth.setValue(options.getCheckMutualAncestorsDepth()); chkLogMarriageNameChanges.setSelected(options.isLogMarriageNameChanges()); for (final Entry entry : spnMarriageSurnameWeights.entrySet()) { @@ -8288,6 +8319,7 @@ public void setOptions(@Nullable CampaignOptions options, chkAssignChildrenOfFoundersFounderTag.setSelected(options.isAssignChildrenOfFoundersFounderTag()); chkDetermineFatherAtBirth.setSelected(options.isDetermineFatherAtBirth()); chkDisplayTrueDueDate.setSelected(options.isDisplayTrueDueDate()); + spnNoInterestInChildrenDiceSize.setValue(options.getNoInterestInChildrenDiceSize()); chkUseMaternityLeave.setSelected(options.isUseMaternityLeave()); chkLogProcreation.setSelected(options.isLogProcreation()); comboRandomProcreationMethod.setSelectedItem(options.getRandomProcreationMethod()); @@ -8938,6 +8970,7 @@ public void updateOptions() { options.setUseManualMarriages(chkUseManualMarriages.isSelected()); options.setUseClanPersonnelMarriages(chkUseClanPersonnelMarriages.isSelected()); options.setUsePrisonerMarriages(chkUsePrisonerMarriages.isSelected()); + options.setNoInterestInMarriageDiceSize((int) spnNoInterestInMarriageDiceSize.getValue()); options.setCheckMutualAncestorsDepth((Integer) spnCheckMutualAncestorsDepth.getValue()); options.setLogMarriageNameChanges(chkLogMarriageNameChanges.isSelected()); for (final Entry entry : spnMarriageSurnameWeights.entrySet()) { @@ -8975,6 +9008,7 @@ public void updateOptions() { options.setAssignChildrenOfFoundersFounderTag(chkAssignChildrenOfFoundersFounderTag.isSelected()); options.setDetermineFatherAtBirth(chkDetermineFatherAtBirth.isSelected()); options.setDisplayTrueDueDate(chkDisplayTrueDueDate.isSelected()); + options.setNoInterestInChildrenDiceSize((int) spnNoInterestInChildrenDiceSize.getValue()); options.setUseMaternityLeave(chkUseMaternityLeave.isSelected()); options.setLogProcreation(chkLogProcreation.isSelected()); options.setRandomProcreationMethod(comboRandomProcreationMethod.getSelectedItem()); From 94fc17730c254bd8467d0741f963bd53e1861d43 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Mon, 5 Aug 2024 16:43:20 -0500 Subject: [PATCH 33/41] Update copyright years for MekHQ source files Updated the copyright statements across multiple source and test files to include the year 2024. This change ensures all files reflect the current year in their copyright information. --- MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java | 2 +- MekHQ/src/mekhq/campaign/mission/AtBContract.java | 2 +- MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java | 2 +- .../mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java | 2 +- MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java | 2 +- .../src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java | 2 +- .../mekhq/campaign/personnel/enums/RandomMarriageMethod.java | 2 +- .../personnel/generator/AbstractPersonnelGenerator.java | 2 +- .../campaign/personnel/generator/DefaultPersonnelGenerator.java | 2 +- .../campaign/personnel/generator/DefaultSkillGenerator.java | 2 +- .../campaign/personnel/procreation/AbstractProcreation.java | 2 +- .../personnel/procreation/DisabledRandomProcreation.java | 2 +- MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java | 2 +- MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java | 2 +- MekHQ/src/mekhq/gui/enums/PersonnelFilter.java | 2 +- .../mekhq/campaign/personnel/divorce/AbstractDivorceTest.java | 2 +- .../campaign/personnel/divorce/DisabledRandomDivorceTest.java | 2 +- .../mekhq/campaign/personnel/enums/PersonnelStatusTest.java | 2 +- .../mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java | 2 +- .../campaign/personnel/procreation/AbstractProcreationTest.java | 2 +- .../personnel/procreation/DisabledRandomProcreationTest.java | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java index 6756ecda81..149369f890 100644 --- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java +++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2018-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/mission/AtBContract.java b/MekHQ/src/mekhq/campaign/mission/AtBContract.java index 32973512ea..fe5ebfa33c 100644 --- a/MekHQ/src/mekhq/campaign/mission/AtBContract.java +++ b/MekHQ/src/mekhq/campaign/mission/AtBContract.java @@ -2,7 +2,7 @@ * AtBContract.java * * Copyright (c) 2014 Carl Spain. All rights reserved. - * Copyright (c) 2020 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2020-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java b/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java index 96bf2aedb7..a14997c4f1 100644 --- a/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java +++ b/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - The Megamek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The Megamek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java index 7f1b143d37..fb164273dd 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java index 6c7870d6e6..344abd1c3b 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2020-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java index 9bef1f1074..d328296a06 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java index a1517a61dc..9c8bddbac2 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java index 16b775298b..4b438366d1 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/AbstractPersonnelGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 - The MegaMek Team. All Rights Reserved. + * Copyright (C) 2019-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java index 8c45b98a6f..806528a0f3 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultPersonnelGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 MegaMek team + * Copyright (C) 2019-2024 MegaMek team * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java index 2a5c8fd715..4a74691b63 100644 --- a/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java +++ b/MekHQ/src/mekhq/campaign/personnel/generator/DefaultSkillGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 - The MegaMek Team. All Rights Reserved. + * Copyright (C) 2019-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index 0f02e017f5..3bd9d335d4 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java index 78d096c32f..0c3cb78e9e 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/DisabledRandomProcreation.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 - The MegaMek Team. All Rights Reserved. + * Copyright (C) 2021-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java index e119cb17cc..4476445cac 100644 --- a/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/GMToolsDialog.java @@ -1,7 +1,7 @@ /* * GMToolsDialog.java * - * Copyright (c) 2013-2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2013-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java index 5a8c24eec0..a7fa4fdd86 100644 --- a/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java +++ b/MekHQ/src/mekhq/gui/dialog/HireBulkPersonnelDialog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2021 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2010-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java b/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java index e98a84c6e8..032fbda4e0 100644 --- a/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java +++ b/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2020-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java index 9c8809016f..b2e8a695b3 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java index 1d7e815b03..aec516f3e1 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java index e4697b08ff..1ad0336714 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/PersonnelStatusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java index 63b830e974..f4fa738809 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/enums/RandomDivorceMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java index e4973151b3..7cdafedfae 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/AbstractProcreationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * diff --git a/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java b/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java index 324a1dc6fb..72ce804322 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/procreation/DisabledRandomProcreationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 - The MegaMek Team. All Rights Reserved. + * Copyright (c) 2022-2024 - The MegaMek Team. All Rights Reserved. * * This file is part of MekHQ. * From c54baed110e3b9f87e681ec51e702238c8501be5 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Fri, 9 Aug 2024 00:03:42 -0500 Subject: [PATCH 34/41] Refactored imports in AbstractProcreation.java --- .../campaign/personnel/procreation/AbstractProcreation.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java index c80fdfd4f1..e4798039b4 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/AbstractProcreation.java @@ -33,10 +33,8 @@ import mekhq.campaign.log.PersonalLogger; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.PersonnelOptions; -import mekhq.campaign.personnel.enums.FamilialRelationshipType; -import mekhq.campaign.personnel.enums.GenderDescriptors; -import mekhq.campaign.personnel.enums.PrisonerStatus; -import mekhq.campaign.personnel.enums.RandomProcreationMethod; +import mekhq.campaign.personnel.education.EducationController; +import mekhq.campaign.personnel.enums.*; import mekhq.campaign.personnel.enums.education.EducationLevel; import java.time.LocalDate; From d83c2a1dd920623e059d37463bee6b9bbbb956bb Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 20 Aug 2024 09:28:34 -0500 Subject: [PATCH 35/41] Refactor randomize methods to remove Person parameter Removed the Person parameter from various randomMarriage and randomDivorce methods for consistency and simplicity. Updated corresponding method calls and test cases to reflect these changes. This refactor reduces redundant code and improves method clarity. --- MekHQ/src/mekhq/campaign/CampaignOptions.java | 1 - MekHQ/src/mekhq/campaign/personnel/Person.java | 3 --- .../mekhq/campaign/personnel/divorce/AbstractDivorce.java | 5 ++--- .../campaign/personnel/divorce/DisabledRandomDivorce.java | 3 +-- .../mekhq/campaign/personnel/divorce/RandomDivorce.java | 3 +-- .../campaign/personnel/marriage/AbstractMarriage.java | 7 +++---- .../personnel/marriage/DisabledRandomMarriage.java | 3 +-- .../mekhq/campaign/personnel/marriage/RandomMarriage.java | 3 +-- .../personnel/divorce/DisabledRandomDivorceTest.java | 2 +- .../personnel/divorce/PercentageRandomDivorceTest.java | 4 ++-- .../campaign/personnel/marriage/AbstractMarriageTest.java | 6 +++--- .../personnel/marriage/DisabledRandomMarriageTest.java | 2 +- .../personnel/marriage/PercentageRandomMarriageTest.java | 4 ++-- 13 files changed, 18 insertions(+), 28 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 83ee76cf44..78359d0f36 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -282,7 +282,6 @@ public static String getTransitUnitName(final int unit) { private boolean useRandomPersonalityReputation; private boolean useIntelligenceXpMultiplier; private boolean useSimulatedRelationships; - private boolean useSimulatedRelationships; // Family diff --git a/MekHQ/src/mekhq/campaign/personnel/Person.java b/MekHQ/src/mekhq/campaign/personnel/Person.java index b81eec27d6..ce264c0b57 100644 --- a/MekHQ/src/mekhq/campaign/personnel/Person.java +++ b/MekHQ/src/mekhq/campaign/personnel/Person.java @@ -30,7 +30,6 @@ import megamek.common.options.IOption; import megamek.common.options.IOptionGroup; import megamek.common.options.OptionsConstants; -import megamek.logging.MMLogger; import megamek.common.options.PilotOptions; import megamek.logging.MMLogger; import mekhq.MekHQ; @@ -252,8 +251,6 @@ public class Person { MekHQ.getMHQOptions().getLocale()); private static final MMLogger logger = MMLogger.create(Person.class); - private static final MMLogger logger = MMLogger.create(Person.class); - // initializes the AtB ransom values static { MECHWARRIOR_AERO_RANSOM_VALUES = new HashMap<>(); diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index 92211d3ef0..cf5b9a2fa7 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -344,7 +344,7 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final return; } - if (randomDivorce(person)) { + if (randomDivorce()) { if (isBackground) { backgroundDivorce(campaign, today, person, SplittingSurnameStyle.WEIGHTED); } else { @@ -356,10 +356,9 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final //region Random Divorce /** * This determines if a person will randomly divorce their spouse - * @param person the person to determine if they are to randomly divorce their spouse * @return true if the person is to randomly divorce */ - protected abstract boolean randomDivorce(final Person person); + protected abstract boolean randomDivorce(); //endregion Random Divorce //endregion New Day } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java index fb164273dd..f24ea6d52f 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/DisabledRandomDivorce.java @@ -19,7 +19,6 @@ package mekhq.campaign.personnel.divorce; import mekhq.campaign.CampaignOptions; -import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomDivorceMethod; public class DisabledRandomDivorce extends AbstractDivorce { @@ -30,7 +29,7 @@ public DisabledRandomDivorce(final CampaignOptions options) { //endregion Constructors @Override - protected boolean randomDivorce(final Person person) { + protected boolean randomDivorce() { return false; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index 3558bcefbd..bbe0a163a1 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -20,7 +20,6 @@ import megamek.common.Compute; import mekhq.campaign.CampaignOptions; -import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomDivorceMethod; public class RandomDivorce extends AbstractDivorce { @@ -48,7 +47,7 @@ public void setDivorceDiceSize(final int divorceDiceSize) { //endregion Getters/Setters @Override - protected boolean randomDivorce(final Person person) { + protected boolean randomDivorce() { if (divorceDiceSize == 0) { return false; } else if (divorceDiceSize == 1) { diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 4b812a7e81..15e1f24fd0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -271,7 +271,7 @@ public void processNewWeek(final Campaign campaign, final LocalDate today, final return; } - if (randomMarriage(person)) { + if (randomMarriage()) { boolean isSameSex = false; int sameSexDiceSize = campaign.getCampaignOptions().getRandomSameSexMarriageDiceSize(); @@ -308,7 +308,7 @@ public void processBackgroundMarriageRolls(final Campaign campaign, final LocalD return; } - if (randomMarriage(person)) { + if (randomMarriage()) { boolean isSameSex = false; int sameSexDiceSize = campaign.getCampaignOptions().getRandomSameSexMarriageDiceSize(); @@ -326,10 +326,9 @@ public void processBackgroundMarriageRolls(final Campaign campaign, final LocalD //region Random Marriage /** * This determines if a person will randomly marry an opposite sex spouse. - * @param person the person to determine if they are getting randomly married * @return true if the person is to randomly marry */ - protected abstract boolean randomMarriage(final Person person); + protected abstract boolean randomMarriage(); /** * This finds a random spouse and marries them to the provided person. diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java index b52377f0b0..c54825bffd 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/DisabledRandomMarriage.java @@ -19,7 +19,6 @@ package mekhq.campaign.personnel.marriage; import mekhq.campaign.CampaignOptions; -import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomMarriageMethod; public class DisabledRandomMarriage extends AbstractMarriage { @@ -30,7 +29,7 @@ public DisabledRandomMarriage(final CampaignOptions options) { //endregion Constructors @Override - protected boolean randomMarriage(final Person person) { + protected boolean randomMarriage() { return false; } } diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index ef42e71316..9b8a3242b9 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -20,7 +20,6 @@ import megamek.common.Compute; import mekhq.campaign.CampaignOptions; -import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomMarriageMethod; public class RandomMarriage extends AbstractMarriage { @@ -49,7 +48,7 @@ public void setMarriageDiceSize(final int marriageDiceSize) { //endregion Getters/Setters @Override - protected boolean randomMarriage(final Person person) { + protected boolean randomMarriage() { if (marriageDiceSize == 0) { return false; } else if (marriageDiceSize == 1) { diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java index aec516f3e1..103c1b7c2d 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/DisabledRandomDivorceTest.java @@ -49,6 +49,6 @@ public void beforeEach() { @Test public void testRandomDivorce() { - assertFalse(new DisabledRandomDivorce(mockOptions).randomDivorce(mockPerson)); + assertFalse(new DisabledRandomDivorce(mockOptions).randomDivorce()); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java index 2fc91b4e01..15b7e0da1d 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/PercentageRandomDivorceTest.java @@ -60,9 +60,9 @@ public void testRandomDivorce() { try(MockedStatic compute = Mockito.mockStatic(Compute.class)) { compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); - assertTrue(randomDivorce.randomDivorce(mockPerson)); + assertTrue(randomDivorce.randomDivorce()); compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); - assertFalse(randomDivorce.randomDivorce(mockPerson)); + assertFalse(randomDivorce.randomDivorce()); } } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java index 77c3b7c28f..b2bcd479ab 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/AbstractMarriageTest.java @@ -269,13 +269,13 @@ public void testProcessNewWeek() { when(mockMarriage.canMarry(any(), any(), anyBoolean())).thenReturn("Married"); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(0)).randomMarriage(any()); + verify(mockMarriage, times(0)).randomMarriage(); verify(mockMarriage, times(0)).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); when(mockMarriage.canMarry(any(), any(), anyBoolean())).thenReturn(null); - when(mockMarriage.randomMarriage(any())).thenReturn(true); + when(mockMarriage.randomMarriage()).thenReturn(true); mockMarriage.processNewWeek(mockCampaign, LocalDate.ofYearDay(3025, 1), mockPerson); - verify(mockMarriage, times(1)).randomMarriage(any()); + verify(mockMarriage, times(1)).randomMarriage(); verify(mockMarriage, times(1)).marryRandomSpouse(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()); } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java index b3aec99acd..499f13de52 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/DisabledRandomMarriageTest.java @@ -47,6 +47,6 @@ public void beforeEach() { @Test public void testRandomMarriage() { - assertFalse(new DisabledRandomMarriage(mockOptions).randomMarriage(mockPerson)); + assertFalse(new DisabledRandomMarriage(mockOptions).randomMarriage()); } } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java index 245b5b77b3..021ae51cba 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/marriage/PercentageRandomMarriageTest.java @@ -58,9 +58,9 @@ public void testRandomMarriage() { try (MockedStatic compute = Mockito.mockStatic(Compute.class)) { compute.when(() -> Compute.randomInt(diceSize)).thenReturn(0); - assertTrue(randomMarriage.randomMarriage(mockPerson)); + assertTrue(randomMarriage.randomMarriage()); compute.when(() -> Compute.randomInt(diceSize)).thenReturn(1); - assertFalse(randomMarriage.randomMarriage(mockPerson)); + assertFalse(randomMarriage.randomMarriage()); } } } From f1f7c5ab4a6fba2b7d532fb10d691cafda589f8e Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 24 Sep 2024 20:10:41 -0500 Subject: [PATCH 36/41] Fixed post-merge weirdness --- MekHQ/src/mekhq/campaign/Campaign.java | 58 ++------------- MekHQ/src/mekhq/campaign/CampaignOptions.java | 25 +++---- .../mekhq/campaign/io/CampaignXmlParser.java | 59 ++------------- .../campaign/mission/BotForceRandomizer.java | 33 ++------- .../personnel/enums/PersonnelStatus.java | 74 +++++++++---------- .../AbstractCompanyGenerator.java | 29 +++----- .../adapter/PersonnelTableMouseAdapter.java | 54 +++++--------- .../src/mekhq/gui/enums/PersonnelFilter.java | 29 ++++---- 8 files changed, 110 insertions(+), 251 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 94271aca9e..085fc70f0b 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -21,23 +21,6 @@ */ package mekhq.campaign; -import static mekhq.campaign.personnel.backgrounds.BackgroundsController.randomMercenaryCompanyNameGenerator; -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 java.io.PrintWriter; -import java.text.MessageFormat; -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.Month; -import java.time.temporal.ChronoUnit; -import java.util.*; -import java.util.Map.Entry; -import java.util.stream.Collectors; - -import javax.swing.JOptionPane; - import megamek.client.generator.RandomGenderGenerator; import megamek.client.generator.RandomNameGenerator; import megamek.client.generator.RandomUnitGenerator; @@ -54,11 +37,7 @@ import megamek.common.loaders.BLKFile; import megamek.common.loaders.EntityLoadingException; import megamek.common.loaders.EntitySavingException; -import megamek.common.options.GameOptions; -import megamek.common.options.IBasicOption; -import megamek.common.options.IOption; -import megamek.common.options.IOptionGroup; -import megamek.common.options.OptionsConstants; +import megamek.common.options.*; import megamek.common.util.BuildingBlock; import megamek.common.weapons.autocannons.ACWeapon; import megamek.common.weapons.flamers.FlamerWeapon; @@ -71,11 +50,7 @@ import mekhq.campaign.Quartermaster.PartAcquisitionResult; import mekhq.campaign.againstTheBot.AtBConfiguration; import mekhq.campaign.event.*; -import mekhq.campaign.finances.Accountant; -import mekhq.campaign.finances.CurrencyManager; -import mekhq.campaign.finances.Finances; -import mekhq.campaign.finances.Loan; -import mekhq.campaign.finances.Money; +import mekhq.campaign.finances.*; import mekhq.campaign.finances.enums.TransactionType; import mekhq.campaign.force.Force; import mekhq.campaign.force.Lance; @@ -90,12 +65,7 @@ import mekhq.campaign.market.ShoppingList; import mekhq.campaign.market.unitMarket.AbstractUnitMarket; import mekhq.campaign.market.unitMarket.DisabledUnitMarket; -import mekhq.campaign.mission.AtBContract; -import mekhq.campaign.mission.AtBDynamicScenario; -import mekhq.campaign.mission.AtBScenario; -import mekhq.campaign.mission.Contract; -import mekhq.campaign.mission.Mission; -import mekhq.campaign.mission.Scenario; +import mekhq.campaign.mission.*; import mekhq.campaign.mission.atb.AtBScenarioFactory; import mekhq.campaign.mission.enums.AtBLanceRole; import mekhq.campaign.mission.enums.MissionStatus; @@ -105,12 +75,7 @@ import mekhq.campaign.parts.equipment.AmmoBin; import mekhq.campaign.parts.equipment.EquipmentPart; import mekhq.campaign.parts.equipment.MissingEquipmentPart; -import mekhq.campaign.personnel.Bloodname; -import mekhq.campaign.personnel.Person; -import mekhq.campaign.personnel.PersonnelOptions; -import mekhq.campaign.personnel.Skill; -import mekhq.campaign.personnel.SkillType; -import mekhq.campaign.personnel.SpecialAbility; +import mekhq.campaign.personnel.*; import mekhq.campaign.personnel.autoAwards.AutoAwardsController; import mekhq.campaign.personnel.death.AbstractDeath; import mekhq.campaign.personnel.death.DisabledRandomDeath; @@ -129,21 +94,16 @@ import mekhq.campaign.personnel.ranks.Ranks; import mekhq.campaign.personnel.turnoverAndRetention.Fatigue; import mekhq.campaign.personnel.turnoverAndRetention.RetirementDefectionTracker; +import mekhq.campaign.rating.CamOpsReputation.ReputationController; import mekhq.campaign.rating.FieldManualMercRevDragoonsRating; import mekhq.campaign.rating.IUnitRating; import mekhq.campaign.rating.UnitRatingMethod; -import mekhq.campaign.rating.CamOpsReputation.ReputationController; import mekhq.campaign.storyarc.StoryArc; import mekhq.campaign.stratcon.StratconContractInitializer; import mekhq.campaign.stratcon.StratconRulesManager; import mekhq.campaign.stratcon.StratconTrackState; -import mekhq.campaign.unit.CargoStatistics; import mekhq.campaign.unit.CrewType; -import mekhq.campaign.unit.HangarStatistics; -import mekhq.campaign.unit.TestUnit; -import mekhq.campaign.unit.Unit; -import mekhq.campaign.unit.UnitOrder; -import mekhq.campaign.unit.UnitTechProgression; +import mekhq.campaign.unit.*; import mekhq.campaign.universe.*; import mekhq.campaign.universe.Planet.PlanetaryEvent; import mekhq.campaign.universe.PlanetarySystem.PlanetarySystemEvent; @@ -190,8 +150,6 @@ public class Campaign implements ITechManager { public static final String REPORT_LINEBREAK = "

"; - private static final MMLogger logger = MMLogger.create(Person.class); - private UUID id; // we have three things to track: (1) teams, (2) units, (3) repair tasks @@ -4254,7 +4212,7 @@ private void processRandomDependents() { int lowerRoll = (dependents.size() > dependentCapacity) ? getLowerRandomInt() : Compute.randomInt(100); - if (lowerRoll <= 4 - getUnitRatingMod()) { + if (lowerRoll <= 4 - getAtBUnitRatingMod()) { addReport(String.format(resources.getString("dependentLeavesForce.text"), dependent.getFullTitle())); @@ -4272,7 +4230,7 @@ private void processRandomDependents() { for (int i = 0; i < rollCount; i++) { int lowerRoll = (dependentCount <= (dependentCapacity / 2)) ? getLowerRandomInt() : Compute.randomInt(100); - if (lowerRoll <= (getUnitRatingMod() * 2)) { + if (lowerRoll <= (getAtBUnitRatingMod() * 2)) { final Person dependent = newDependent(false, Gender.RANDOMIZE); recruitPerson(dependent, PrisonerStatus.FREE, true, false); diff --git a/MekHQ/src/mekhq/campaign/CampaignOptions.java b/MekHQ/src/mekhq/campaign/CampaignOptions.java index 3a13f94937..ed8d130226 100644 --- a/MekHQ/src/mekhq/campaign/CampaignOptions.java +++ b/MekHQ/src/mekhq/campaign/CampaignOptions.java @@ -19,23 +19,13 @@ */ package mekhq.campaign; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.codeUtilities.MathUtility; import megamek.common.EquipmentType; import megamek.common.TechConstants; import megamek.common.enums.SkillLevel; import megamek.logging.MMLogger; +import mekhq.MekHQ; import mekhq.Utilities; import mekhq.campaign.enums.PlanetaryAcquisitionFactionLimit; import mekhq.campaign.finances.Money; @@ -45,10 +35,17 @@ import mekhq.campaign.market.enums.UnitMarketMethod; import mekhq.campaign.mission.enums.AtBLanceRole; import mekhq.campaign.parts.enums.PartRepairType; +import mekhq.campaign.personnel.Skills; import mekhq.campaign.personnel.enums.*; import mekhq.campaign.rating.UnitRatingMethod; import mekhq.service.mrms.MRMSOption; import mekhq.utilities.MHQXMLUtility; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintWriter; +import java.util.*; +import java.util.Map.Entry; /** * @author natit @@ -6165,7 +6162,7 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve } else if (wn2.getNodeName().equalsIgnoreCase("scenarioModBV")) { retVal.setScenarioModBV(Integer.parseInt(wn2.getTextContent().trim())); } else if (wn2.getNodeName().equalsIgnoreCase("autoconfigMunitions")) { - retVal.setAutoconfigMunitions(Boolean.parseBoolean(wn2.getTextContent().trim())); + retVal.setAutoConfigMunitions(Boolean.parseBoolean(wn2.getTextContent().trim())); //region Legacy // Removed in 0.49.* @@ -6217,7 +6214,7 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve } else if (values.length == 9) { retVal.migrateMarriageSurnameWeights47(values); } else { - LogManager.getLogger().error("Unknown length of randomMarriageSurnameWeights"); + logger.error("Unknown length of randomMarriageSurnameWeights"); } } else if (wn2.getNodeName().equalsIgnoreCase("logConception")) { // Legacy - 0.49.4 Removal retVal.setLogProcreation(Boolean.parseBoolean(wn2.getTextContent().trim())); @@ -6277,7 +6274,7 @@ public static CampaignOptions generateCampaignOptionsFromXml(Node wn, Version ve retVal.setUnitRatingMethod(UnitRatingMethod.NONE); } } else if (wn2.getNodeName().equalsIgnoreCase("probPhenoMW")) { // Legacy - retVal.phenotypeProbabilities[Phenotype.MECHWARRIOR.ordinal()] = Integer.parseInt(wn2.getTextContent().trim()); + retVal.phenotypeProbabilities[Phenotype.MEKWARRIOR.ordinal()] = Integer.parseInt(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("probPhenoBA")) { // Legacy retVal.phenotypeProbabilities[Phenotype.ELEMENTAL.ordinal()] = Integer.parseInt(wn2.getTextContent().trim()); } else if (wn2.getNodeName().equalsIgnoreCase("probPhenoAero")) { // Legacy diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java index 710242eaa6..3251695314 100644 --- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java +++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java @@ -18,44 +18,12 @@ */ package mekhq.campaign.io; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import javax.xml.parsers.DocumentBuilder; - -import org.apache.commons.lang3.StringUtils; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.client.generator.RandomGenderGenerator; import megamek.client.generator.RandomNameGenerator; import megamek.client.ui.swing.util.PlayerColour; import megamek.common.Entity; -import megamek.common.EntityMovementMode; -import megamek.common.Jumpship; -import megamek.common.Mek; -import megamek.common.MekSummaryCache; -import megamek.common.MiscType; -import megamek.common.Mounted; -import megamek.common.SmallCraft; -import megamek.common.Tank; +import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.icons.Camouflage; import megamek.common.weapons.bayweapons.BayWeapon; @@ -63,12 +31,7 @@ import mekhq.MekHQ; import mekhq.NullEntityException; import mekhq.Utilities; -import mekhq.campaign.Campaign; -import mekhq.campaign.CampaignOptions; -import mekhq.campaign.CurrentLocation; -import mekhq.campaign.Kill; -import mekhq.campaign.RandomSkillPreferences; -import mekhq.campaign.Warehouse; +import mekhq.campaign.*; import mekhq.campaign.againstTheBot.AtBConfiguration; import mekhq.campaign.finances.Finances; import mekhq.campaign.force.Force; @@ -81,20 +44,8 @@ import mekhq.campaign.mission.Mission; import mekhq.campaign.mission.Scenario; import mekhq.campaign.mod.am.InjuryTypes; -import mekhq.campaign.parts.EnginePart; -import mekhq.campaign.parts.MekActuator; -import mekhq.campaign.parts.MekLocation; -import mekhq.campaign.parts.MissingEnginePart; -import mekhq.campaign.parts.MissingMekActuator; -import mekhq.campaign.parts.MissingPart; -import mekhq.campaign.parts.Part; -import mekhq.campaign.parts.equipment.AmmoBin; -import mekhq.campaign.parts.equipment.EquipmentPart; -import mekhq.campaign.parts.equipment.HeatSink; -import mekhq.campaign.parts.equipment.MASC; -import mekhq.campaign.parts.equipment.MissingAmmoBin; -import mekhq.campaign.parts.equipment.MissingEquipmentPart; -import mekhq.campaign.parts.equipment.MissingMASC; +import mekhq.campaign.parts.*; +import mekhq.campaign.parts.equipment.*; import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.PersonnelOptions; import mekhq.campaign.personnel.SkillType; @@ -301,7 +252,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { } else if (xn.equalsIgnoreCase("location")) { retVal.setLocation(CurrentLocation.generateInstanceFromXML(wn, retVal)); } else if (xn.equalsIgnoreCase("skillTypes")) { - processSkillTypeNodes(wn); + processSkillTypeNodes(retVal, wn, version); } else if (xn.equalsIgnoreCase("specialAbilities")) { processSpecialAbilityNodes(retVal, wn, version); } else if (xn.equalsIgnoreCase("storyArc")) { diff --git a/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java b/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java index 05426c9d68..8a922275ba 100644 --- a/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java +++ b/MekHQ/src/mekhq/campaign/mission/BotForceRandomizer.java @@ -18,17 +18,6 @@ */ package mekhq.campaign.mission; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.commons.math3.distribution.GammaDistribution; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.client.generator.RandomGenderGenerator; import megamek.client.generator.RandomNameGenerator; @@ -36,16 +25,11 @@ import megamek.client.generator.skillGenerators.AbstractSkillGenerator; import megamek.client.generator.skillGenerators.TaharqaSkillGenerator; import megamek.codeUtilities.StringUtility; -import megamek.common.Compute; -import megamek.common.Crew; -import megamek.common.Entity; -import megamek.common.EntityWeightClass; -import megamek.common.MekFileParser; -import megamek.common.MekSummary; -import megamek.common.UnitType; +import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; import megamek.common.enums.SkillLevel; +import megamek.logging.MMLogger; import mekhq.campaign.Campaign; import mekhq.campaign.personnel.Bloodname; import mekhq.campaign.personnel.enums.Phenotype; @@ -57,7 +41,6 @@ import mekhq.campaign.universe.UnitGeneratorParameters; import mekhq.utilities.MHQXMLUtility; import org.apache.commons.math3.distribution.GammaDistribution; -import org.apache.logging.log4j.LogManager; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -501,7 +484,7 @@ public Entity getEntity(int uType, int weightClass, Campaign campaign) { String[] crewNameArray = rng.generateGivenNameSurnameSplit(gender, faction.isClan(), faction.getShortName()); String crewName = crewNameArray[0]; - crewName += !StringUtility.isNullOrBlank(crewNameArray[1]) ? " " + crewNameArray[1] : ""; + crewName += !StringUtility.isNullOrBlank(crewNameArray[1]) ? ' ' + crewNameArray[1] : ""; Map> extraData = new HashMap<>(); Map innerMap = new HashMap<>(); @@ -552,7 +535,7 @@ public Entity getEntity(int uType, int weightClass, Campaign campaign) { if (!phenotype.isNone()) { String bloodname = Bloodname.randomBloodname(faction.getShortName(), phenotype, campaign.getGameYear()).getName(); - crewName += " " + bloodname; + crewName += ' ' + bloodname; innerMap.put(Crew.MAP_BLOODNAME, bloodname); innerMap.put(Crew.MAP_PHENOTYPE, phenotype.name()); } @@ -714,7 +697,7 @@ private double calculateMeanWeightClass(List playerUnits) { } public String getShortDescription() { - String sb = forceMultiplier + " (" + balancingMethod.toString() + ")"; + String sb = forceMultiplier + " (" + balancingMethod.toString() + ')'; return sb; } @@ -728,9 +711,9 @@ public String getShortDescription() { public String getDescription(Campaign campaign) { StringBuilder sb = new StringBuilder(); sb.append(Factions.getInstance().getFaction(factionCode).getFullName(campaign.getGameYear())); - sb.append(" "); + sb.append(' '); sb.append(skill.toString()); - sb.append(" "); + sb.append(' '); String typeDesc = UnitType.getTypeDisplayableName(unitType); if (percentConventional > 0) { typeDesc = typeDesc + " and Conventional"; @@ -740,7 +723,7 @@ public String getDescription(Campaign campaign) { sb.append(forceMultiplier); sb.append(" multiplier ("); sb.append(balancingMethod.toString()); - sb.append(")"); + sb.append(')'); return sb.toString(); } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java index 45dabd1b3e..005baf2f40 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java @@ -18,69 +18,69 @@ */ package mekhq.campaign.personnel.enums; +import megamek.logging.MMLogger; +import mekhq.MekHQ; + import java.util.List; import java.util.ResourceBundle; import java.util.stream.Collectors; import java.util.stream.Stream; -import megamek.logging.MMLogger; -import mekhq.MekHQ; - /** * TODO : Add PoW, On Leave and AWOL implementations */ public enum PersonnelStatus { // region Enum Declarations - ACTIVE("PersonnelStatus.ACTIVE.text", "PersonnelStatus.ACTIVE.toolTipText", "PersonnelStatus.ACTIVE.reportText", - "PersonnelStatus.ACTIVE.logText"), - MIA("PersonnelStatus.MIA.text", "PersonnelStatus.MIA.toolTipText", "PersonnelStatus.MIA.reportText", - "PersonnelStatus.MIA.logText"), - POW("PersonnelStatus.POW.text", "PersonnelStatus.POW.toolTipText", "PersonnelStatus.POW.reportText", - "PersonnelStatus.POW.logText"), + ACTIVE("PersonnelStatus.ACTIVE.text", "PersonnelStatus.ACTIVE.toolTipText", + "PersonnelStatus.ACTIVE.reportText", "PersonnelStatus.ACTIVE.logText"), + MIA("PersonnelStatus.MIA.text", "PersonnelStatus.MIA.toolTipText", + "PersonnelStatus.MIA.reportText", "PersonnelStatus.MIA.logText"), + POW("PersonnelStatus.POW.text", "PersonnelStatus.POW.toolTipText", + "PersonnelStatus.POW.reportText", "PersonnelStatus.POW.logText"), ON_LEAVE("PersonnelStatus.ON_LEAVE.text", "PersonnelStatus.ON_LEAVE.toolTipText", "PersonnelStatus.ON_LEAVE.reportText", "PersonnelStatus.ON_LEAVE.logText"), - AWOL("PersonnelStatus.AWOL.text", "PersonnelStatus.AWOL.toolTipText", "PersonnelStatus.AWOL.reportText", - "PersonnelStatus.AWOL.logText"), - RETIRED("PersonnelStatus.RETIRED.text", "PersonnelStatus.RETIRED.toolTipText", "PersonnelStatus.RETIRED.reportText", - "PersonnelStatus.RETIRED.logText"), + ON_MATERNITY_LEAVE("PersonnelStatus.ON_MATERNITY_LEAVE.text", "PersonnelStatus.ON_MATERNITY_LEAVE.toolTipText", + "PersonnelStatus.ON_MATERNITY_LEAVE.reportText", "PersonnelStatus.ON_MATERNITY_LEAVE.logText"), + AWOL("PersonnelStatus.AWOL.text", "PersonnelStatus.AWOL.toolTipText", + "PersonnelStatus.AWOL.reportText", "PersonnelStatus.AWOL.logText"), + RETIRED("PersonnelStatus.RETIRED.text", "PersonnelStatus.RETIRED.toolTipText", + "PersonnelStatus.RETIRED.reportText", "PersonnelStatus.RETIRED.logText"), RESIGNED("PersonnelStatus.RESIGNED.text", "PersonnelStatus.RESIGNED.toolTipText", "PersonnelStatus.RESIGNED.reportText", "PersonnelStatus.RESIGNED.logText"), - SACKED("PersonnelStatus.SACKED.text", "PersonnelStatus.SACKED.toolTipText", "PersonnelStatus.SACKED.reportText", - "PersonnelStatus.SACKED.logText"), - LEFT("PersonnelStatus.LEFT.text", "PersonnelStatus.LEFT.toolTipText", "PersonnelStatus.LEFT.reportText", - "PersonnelStatus.LEFT.logText"), + SACKED("PersonnelStatus.SACKED.text", "PersonnelStatus.SACKED.toolTipText", + "PersonnelStatus.SACKED.reportText", "PersonnelStatus.SACKED.logText"), + LEFT("PersonnelStatus.LEFT.text", "PersonnelStatus.LEFT.toolTipText", + "PersonnelStatus.LEFT.reportText", "PersonnelStatus.LEFT.logText"), DESERTED("PersonnelStatus.DESERTED.text", "PersonnelStatus.DESERTED.toolTipText", "PersonnelStatus.DESERTED.reportText", "PersonnelStatus.DESERTED.logText"), DEFECTED("PersonnelStatus.DEFECTED.text", "PersonnelStatus.DEFECTED.toolTipText", "PersonnelStatus.DEFECTED.reportText", "PersonnelStatus.DEFECTED.logText"), - STUDENT("PersonnelStatus.STUDENT.text", "PersonnelStatus.STUDENT.toolTipText", "PersonnelStatus.STUDENT.reportText", - "PersonnelStatus.STUDENT.logText"), - MISSING("PersonnelStatus.MISSING.text", "PersonnelStatus.MISSING.toolTipText", "PersonnelStatus.MISSING.reportText", - "PersonnelStatus.MISSING.logText"), - KIA("PersonnelStatus.KIA.text", "PersonnelStatus.KIA.toolTipText", "PersonnelStatus.KIA.reportText", - "PersonnelStatus.KIA.logText"), + STUDENT("PersonnelStatus.STUDENT.text", "PersonnelStatus.STUDENT.toolTipText", + "PersonnelStatus.STUDENT.reportText", "PersonnelStatus.STUDENT.logText"), + MISSING("PersonnelStatus.MISSING.text", "PersonnelStatus.MISSING.toolTipText", + "PersonnelStatus.MISSING.reportText", "PersonnelStatus.MISSING.logText"), + KIA("PersonnelStatus.KIA.text", "PersonnelStatus.KIA.toolTipText", + "PersonnelStatus.KIA.reportText", "PersonnelStatus.KIA.logText"), HOMICIDE("PersonnelStatus.HOMICIDE.text", "PersonnelStatus.HOMICIDE.toolTipText", "PersonnelStatus.HOMICIDE.reportText", "PersonnelStatus.HOMICIDE.logText"), - WOUNDS("PersonnelStatus.WOUNDS.text", "PersonnelStatus.WOUNDS.toolTipText", "PersonnelStatus.WOUNDS.reportText", - "PersonnelStatus.WOUNDS.logText"), - DISEASE("PersonnelStatus.DISEASE.text", "PersonnelStatus.DISEASE.toolTipText", "PersonnelStatus.DISEASE.reportText", - "PersonnelStatus.DISEASE.logText"), + WOUNDS("PersonnelStatus.WOUNDS.text", "PersonnelStatus.WOUNDS.toolTipText", + "PersonnelStatus.WOUNDS.reportText", "PersonnelStatus.WOUNDS.logText"), + DISEASE("PersonnelStatus.DISEASE.text", "PersonnelStatus.DISEASE.toolTipText", + "PersonnelStatus.DISEASE.reportText", "PersonnelStatus.DISEASE.logText"), ACCIDENTAL("PersonnelStatus.ACCIDENTAL.text", "PersonnelStatus.ACCIDENTAL.toolTipText", "PersonnelStatus.ACCIDENTAL.reportText", "PersonnelStatus.ACCIDENTAL.logText"), NATURAL_CAUSES("PersonnelStatus.NATURAL_CAUSES.text", "PersonnelStatus.NATURAL_CAUSES.toolTipText", "PersonnelStatus.NATURAL_CAUSES.reportText", "PersonnelStatus.NATURAL_CAUSES.logText"), - OLD_AGE("PersonnelStatus.OLD_AGE.text", "PersonnelStatus.OLD_AGE.toolTipText", "PersonnelStatus.OLD_AGE.reportText", - "PersonnelStatus.OLD_AGE.logText"), - MEDICAL_COMPLICATIONS("PersonnelStatus.MEDICAL_COMPLICATIONS.text", - "PersonnelStatus.MEDICAL_COMPLICATIONS.toolTipText", "PersonnelStatus.MEDICAL_COMPLICATIONS.reportText", - "PersonnelStatus.MEDICAL_COMPLICATIONS.logText"), - PREGNANCY_COMPLICATIONS("PersonnelStatus.PREGNANCY_COMPLICATIONS.text", - "PersonnelStatus.PREGNANCY_COMPLICATIONS.toolTipText", "PersonnelStatus.PREGNANCY_COMPLICATIONS.reportText", - "PersonnelStatus.PREGNANCY_COMPLICATIONS.logText"), + OLD_AGE("PersonnelStatus.OLD_AGE.text", "PersonnelStatus.OLD_AGE.toolTipText", + "PersonnelStatus.OLD_AGE.reportText", "PersonnelStatus.OLD_AGE.logText"), + MEDICAL_COMPLICATIONS("PersonnelStatus.MEDICAL_COMPLICATIONS.text", "PersonnelStatus.MEDICAL_COMPLICATIONS.toolTipText", + "PersonnelStatus.MEDICAL_COMPLICATIONS.reportText", "PersonnelStatus.MEDICAL_COMPLICATIONS.logText"), + PREGNANCY_COMPLICATIONS("PersonnelStatus.PREGNANCY_COMPLICATIONS.text", "PersonnelStatus.PREGNANCY_COMPLICATIONS.toolTipText", + "PersonnelStatus.PREGNANCY_COMPLICATIONS.reportText", "PersonnelStatus.PREGNANCY_COMPLICATIONS.logText"), UNDETERMINED("PersonnelStatus.UNDETERMINED.text", "PersonnelStatus.UNDETERMINED.toolTipText", "PersonnelStatus.UNDETERMINED.reportText", "PersonnelStatus.UNDETERMINED.logText"), - SUICIDE("PersonnelStatus.SUICIDE.text", "PersonnelStatus.SUICIDE.toolTipText", "PersonnelStatus.SUICIDE.reportText", - "PersonnelStatus.SUICIDE.logText"); + SUICIDE("PersonnelStatus.SUICIDE.text", "PersonnelStatus.SUICIDE.toolTipText", + "PersonnelStatus.SUICIDE.reportText", "PersonnelStatus.SUICIDE.logText"); // endregion Enum Declarations // region Variable Declarations diff --git a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java index 2737ba4037..2ea402711d 100644 --- a/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java +++ b/MekHQ/src/mekhq/campaign/universe/generators/companyGenerators/AbstractCompanyGenerator.java @@ -18,26 +18,8 @@ */ package mekhq.campaign.universe.generators.companyGenerators; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.ResourceBundle; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - import megamek.client.generator.RandomCallsignGenerator; -import megamek.common.AmmoType; -import megamek.common.Entity; -import megamek.common.EntityWeightClass; -import megamek.common.MekFileParser; -import megamek.common.MekSummary; -import megamek.common.UnitType; +import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.options.OptionsConstants; import megamek.logging.MMLogger; @@ -63,6 +45,7 @@ import mekhq.campaign.personnel.Skill; import mekhq.campaign.personnel.SkillType; import mekhq.campaign.personnel.enums.PersonnelRole; +import mekhq.campaign.personnel.enums.education.EducationLevel; import mekhq.campaign.personnel.generator.AbstractPersonnelGenerator; import mekhq.campaign.personnel.ranks.Rank; import mekhq.campaign.unit.Unit; @@ -83,6 +66,14 @@ import mekhq.campaign.universe.selectors.planetSelectors.RangedPlanetSelector; import mekhq.campaign.work.WorkTime; +import java.time.LocalDate; +import java.util.*; +import java.util.Map.Entry; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + /** * Startup: * Second Panel: Presets, Date, Starting Faction, Starting Planet, AtB diff --git a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java index 1f8fc9858b..5b89015eb6 100644 --- a/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java +++ b/MekHQ/src/mekhq/gui/adapter/PersonnelTableMouseAdapter.java @@ -18,27 +18,6 @@ */ package mekhq.gui.adapter; -import static megamek.client.ui.WrapLayout.wordWrap; -import static mekhq.campaign.personnel.education.Academy.skillParser; -import static mekhq.campaign.personnel.education.EducationController.getAcademy; -import static mekhq.campaign.personnel.education.EducationController.makeEnrollmentCheck; - -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.time.LocalDate; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JSplitPane; -import javax.swing.JTable; - import megamek.client.generator.RandomCallsignGenerator; import megamek.client.generator.RandomNameGenerator; import megamek.client.ui.dialogs.PortraitChooserDialog; @@ -62,26 +41,12 @@ import mekhq.campaign.finances.enums.TransactionType; import mekhq.campaign.log.LogEntry; import mekhq.campaign.log.PersonalLogger; -import mekhq.campaign.personnel.Award; -import mekhq.campaign.personnel.AwardsFactory; -import mekhq.campaign.personnel.Injury; -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.autoAwards.AutoAwardsController; import mekhq.campaign.personnel.education.Academy; import mekhq.campaign.personnel.education.AcademyFactory; import mekhq.campaign.personnel.education.EducationController; -import mekhq.campaign.personnel.enums.ManeiDominiClass; -import mekhq.campaign.personnel.enums.ManeiDominiRank; -import mekhq.campaign.personnel.enums.MergingSurnameStyle; -import mekhq.campaign.personnel.enums.PersonnelRole; -import mekhq.campaign.personnel.enums.PersonnelStatus; -import mekhq.campaign.personnel.enums.PrisonerStatus; -import mekhq.campaign.personnel.enums.Profession; -import mekhq.campaign.personnel.enums.ROMDesignation; -import mekhq.campaign.personnel.enums.SplittingSurnameStyle; +import mekhq.campaign.personnel.enums.*; import mekhq.campaign.personnel.enums.education.EducationLevel; import mekhq.campaign.personnel.enums.education.EducationStage; import mekhq.campaign.personnel.generator.SingleSpecialAbilityGenerator; @@ -104,6 +69,21 @@ import mekhq.gui.utilities.MultiLineTooltip; import mekhq.gui.utilities.StaticChecks; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.time.LocalDate; +import java.util.List; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static megamek.client.ui.WrapLayout.wordWrap; +import static mekhq.campaign.personnel.education.Academy.skillParser; +import static mekhq.campaign.personnel.education.EducationController.getAcademy; +import static mekhq.campaign.personnel.education.EducationController.makeEnrollmentCheck; + public class PersonnelTableMouseAdapter extends JPopupMenuAdapter { private static final MMLogger logger = MMLogger.create(PersonnelTableMouseAdapter.class); diff --git a/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java b/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java index 526c04578d..28f5d3b35d 100644 --- a/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java +++ b/MekHQ/src/mekhq/gui/enums/PersonnelFilter.java @@ -30,10 +30,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import mekhq.MekHQ; -import mekhq.campaign.personnel.Person; -import mekhq.campaign.personnel.enums.PersonnelRole; - public enum PersonnelFilter { // region Enum Declarations // region Standard Personnel Filters @@ -393,18 +389,20 @@ public boolean getFilteredInformation(final Person person, LocalDate currentDate case SUPPORT -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? !person.getPrimaryRole().isCombat() : person.hasSupportRole(true)); - case MECHWARRIORS -> + case MEKWARRIORS -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isMechWarriorGrouping() : (person.getPrimaryRole().isMechWarriorGrouping() || person.getSecondaryRole().isMechWarriorGrouping())); - case MECHWARRIOR -> + person.getPrimaryRole().isMekWarriorGrouping() : + (person.getPrimaryRole().isMekWarriorGrouping() || person.getSecondaryRole().isMekWarriorGrouping())); + case MEKWARRIOR -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isMechWarrior() : person.hasRole(PersonnelRole.MECHWARRIOR)); + person.getPrimaryRole().isMekWarrior() : person.hasRole(PersonnelRole.MEKWARRIOR)); case LAM_PILOT -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isLAMPilot() : person.hasRole(PersonnelRole.LAM_PILOT)); case VEHICLE_CREWMEMBER -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isVehicleCrewmember() : (person.getPrimaryRole().isVehicleCrewmember() || person.getSecondaryRole().isVehicleCrewmember())); + person.getPrimaryRole().isVehicleCrew() : + (person.getPrimaryRole().isVehicleCrew() || person.getSecondaryRole().isVehicleCrew())); case GROUND_VEHICLE_DRIVER -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isGroundVehicleDriver() : person.hasRole(PersonnelRole.GROUND_VEHICLE_DRIVER)); @@ -426,9 +424,9 @@ public boolean getFilteredInformation(final Person person, LocalDate currentDate case CONVENTIONAL_AIRCRAFT_PILOT -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isConventionalAircraftPilot() : person.hasRole(PersonnelRole.CONVENTIONAL_AIRCRAFT_PILOT)); - case PROTOMECH_PILOT -> + case PROTOMEK_PILOT -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isProtoMechPilot() : person.hasRole(PersonnelRole.PROTOMECH_PILOT)); + person.getPrimaryRole().isProtoMekPilot() : person.hasRole(PersonnelRole.PROTOMEK_PILOT)); case BATTLE_ARMOUR -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isBattleArmour() : person.hasRole(PersonnelRole.BATTLE_ARMOUR)); @@ -437,7 +435,8 @@ public boolean getFilteredInformation(final Person person, LocalDate currentDate person.getPrimaryRole().isSoldier() : person.hasRole(PersonnelRole.SOLDIER)); case VESSEL_CREWMEMBER -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isVesselCrewmember() : (person.getPrimaryRole().isVesselCrewmember() || person.getSecondaryRole().isVesselCrewmember())); + person.getPrimaryRole().isVesselCrew() : + (person.getPrimaryRole().isVesselCrew() || person.getSecondaryRole().isVesselCrew())); case VESSEL_PILOT -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isVesselPilot() : person.hasRole(PersonnelRole.VESSEL_PILOT)); @@ -453,15 +452,15 @@ public boolean getFilteredInformation(final Person person, LocalDate currentDate case TECH -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isTech() : person.isTech()); - case MECH_TECH -> + case MEK_TECH -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isMechTech() : person.hasRole(PersonnelRole.MECH_TECH)); + person.getPrimaryRole().isMekTech() : person.hasRole(PersonnelRole.MEK_TECH)); case MECHANIC -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isMechanic() : person.hasRole(PersonnelRole.MECHANIC)); case AERO_TECH -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? - person.getPrimaryRole().isAeroTech() : person.hasRole(PersonnelRole.AERO_TECH)); + person.getPrimaryRole().isAeroTek() : person.hasRole(PersonnelRole.AERO_TEK)); case BA_TECH -> active && (MekHQ.getMHQOptions().getPersonnelFilterOnPrimaryRole() ? person.getPrimaryRole().isBATech() : person.hasRole(PersonnelRole.BA_TECH)); From b6d9d00e23b0a3a98c2841d65a936f0652151455 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 24 Sep 2024 20:48:02 -0500 Subject: [PATCH 37/41] Remove @SuppressWarnings annotations and add documentation Removed redundant @SuppressWarnings annotations from multiple classes and enhanced codebase documentation. The changes add clarity to the functionality of classes and methods through JavaDocs, improving maintainability and readability. --- .../personnel/divorce/AbstractDivorce.java | 10 +- .../personnel/divorce/RandomDivorce.java | 21 +- .../personnel/enums/PersonnelStatus.java | 203 ++++++++++++++++-- .../personnel/enums/RandomDivorceMethod.java | 38 +++- .../personnel/enums/RandomMarriageMethod.java | 36 +++- .../enums/RandomProcreationMethod.java | 36 +++- .../personnel/marriage/AbstractMarriage.java | 10 - .../personnel/marriage/RandomMarriage.java | 22 +- .../procreation/RandomProcreation.java | 34 +-- .../divorce/AbstractDivorceTest.java | 23 -- 10 files changed, 357 insertions(+), 76 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index cf5b9a2fa7..1d4642f854 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -173,7 +173,7 @@ public void setUseRandomPrisonerDivorce(final boolean useRandomPrisonerDivorce) /** * This is a standardization method for the divorce surname style to use when a person's spouse * dies. - * + *

* TODO : I should be part of AbstractDeath * * @param campaign the campaign the person is in @@ -300,6 +300,14 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person MekHQ.triggerEvent(new PersonChangedEvent(origin)); } + /** + * Processes divorce events that occur as part of a character's background. + * + * @param campaign the campaign associated with the divorce + * @param today the current date of the divorce + * @param origin the person whose background is being divorced + * @param style the splitting surname style to be applied + */ public void backgroundDivorce(final Campaign campaign, final LocalDate today, final Person origin, final SplittingSurnameStyle style) { final Person spouse = origin.getGenealogy().getSpouse(); diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index bbe0a163a1..5226acc6c6 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -22,25 +22,42 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.enums.RandomDivorceMethod; +/** + * The {@link RandomDivorce} class is an implementation of the {@link AbstractDivorce} class that + * represents a divorce method based on random chance. + * The divorce outcome is determined by rolling a die with a specified number of sides. + */ public class RandomDivorce extends AbstractDivorce { //region Variable Declarations private int divorceDiceSize; //endregion Variable Declarations //region Constructors + /** + * The {@link RandomDivorce} class is an implementation of the {@link AbstractDivorce} class that + * represents a divorce method based on random chance. + */ public RandomDivorce(final CampaignOptions options) { super(RandomDivorceMethod.DICE_ROLL, options); setDivorceDiceSize(options.getRandomDivorceDiceSize()); } //endregion Constructors + /** + * Retrieves the size of the divorce dice. + * + * @return The size of the divorce dice as an integer. + */ //region Getters/Setters - @SuppressWarnings(value = "unused") public int getDivorceDiceSize() { return divorceDiceSize; } - @SuppressWarnings(value = "unused") + /** + * Sets the size of the divorce dice. + * + * @param divorceDiceSize the size of the dice used to determine divorce outcomes + */ public void setDivorceDiceSize(final int divorceDiceSize) { this.divorceDiceSize = divorceDiceSize; } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java index 005baf2f40..5d7794974b 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java @@ -27,7 +27,7 @@ import java.util.stream.Stream; /** - * TODO : Add PoW, On Leave and AWOL implementations + * Enum class representing personnel status. */ public enum PersonnelStatus { // region Enum Declarations @@ -91,6 +91,14 @@ public enum PersonnelStatus { // endregion Variable Declarations // region Constructors + /** + * Initializes a new instance of the {@link PersonnelStatus} class with the given parameters. + * + * @param name the name of the personnel status + * @param toolTipText the tooltip text for the personnel status + * @param reportText the report text for the personnel status + * @param logText the log text for the personnel status + */ PersonnelStatus(final String name, final String toolTipText, final String reportText, final String logText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", @@ -102,131 +110,296 @@ public enum PersonnelStatus { } // endregion Constructors + /** + * Retrieves the tooltip text for a given component. + * + * @return The tooltip text of the component, or null if no tooltip text is set. + */ // region Getters public String getToolTipText() { return toolTipText; } + /** + * Retrieves the report text. + * + * @return The report text as a string. + */ public String getReportText() { return reportText; } + /** + * Retrieves the log text. + * + * @return The log text. + */ public String getLogText() { return logText; } // endregion Getters // region Boolean Comparison Methods + /** + * Checks if the character has the {@code ACTIVE} personnel status. + * + * @return {@code true} if the character has the {@code ACTIVE} personnel status {@code false} + * otherwise. + */ public boolean isActive() { return this == ACTIVE; } + /** + * Checks if the character has the {@code MIA} personnel status. + * + * @return {@code true} if the character has the {@code MIA} personnel status {@code false} + * otherwise. + */ public boolean isMIA() { return this == MIA; } + /** + * Checks if the character has the {@code POW} personnel status. + * + * @return {@code true} if the character has the {@code POW} personnel status {@code false} + * otherwise. + */ public boolean isPoW() { return this == POW; } + /** + * Checks if the character has the {@code ON_LEAVE} personnel status. + * + * @return {@code true} if the character has the {@code ON_LEAVE} personnel status {@code false} + * otherwise. + */ public boolean isOnLeave() { return this == ON_LEAVE; } + /** + * Checks if the character has the {@code ON_MATERNITY_LEAVE} personnel status. + * + * @return {@code true} if the character has the {@code ON_MATERNITY_LEAVE} personnel status + * {@code false} otherwise. + */ public boolean isOnMaternityLeave() { return this == ON_MATERNITY_LEAVE; } + /** + * Checks if the character has the {@code AWOL} personnel status. + * + * @return {@code true} if the character has the {@code AWOL} personnel status {@code false} + * otherwise. + */ public boolean isAwol() { return this == AWOL; } + /** + * Checks if the character has the {@code RETIRED} personnel status. + * + * @return {@code true} if the character has the {@code RETIRED} personnel status {@code false} + * otherwise. + */ public boolean isRetired() { return this == RETIRED; } + /** + * Checks if the character has the {@code RESIGNED} personnel status. + * + * @return {@code true} if the character has the {@code RESIGNED} personnel status {@code false} + * otherwise. + */ public boolean isResigned() { return this == RESIGNED; } + /** + * Checks if the character has the {@code SACKED} personnel status. + * + * @return {@code true} if the character has the {@code SACKED} personnel status {@code false} + * otherwise. + */ public boolean isSacked() { return this == SACKED; } + /** + * Checks if the character has the {@code LEFT} personnel status. + * + * @return {@code true} if the character has the {@code LEFT} personnel status {@code false} + * otherwise. + */ public boolean isLeft() { return this == LEFT; } + /** + * Checks if the character has the {@code DESERTED} personnel status. + * + * @return {@code true} if the character has the {@code DESERTED} personnel status {@code false} + * otherwise. + */ public boolean isDeserted() { return this == DESERTED; } + /** + * Checks if the character has the {@code DEFECTED} personnel status. + * + * @return {@code true} if the character has the {@code DEFECTED} personnel status {@code false} + * otherwise. + */ public boolean isDefected() { return this == DEFECTED; } + /** + * Checks if the character has the {@code STUDENT} personnel status. + * + * @return {@code true} if the character has the {@code STUDENT} personnel status {@code false} + * otherwise. + */ public boolean isStudent() { return this == STUDENT; } + /** + * Checks if the character has the {@code MISSING} personnel status. + * + * @return {@code true} if the character has the {@code MISSING} personnel status {@code false} + * otherwise. + */ public boolean isMissing() { return this == MISSING; } + /** + * Checks if the character has the {@code KIA} personnel status. + * + * @return {@code true} if the character has the {@code KIA} personnel status {@code false} + * otherwise. + */ public boolean isKIA() { return this == KIA; } + /** + * Checks if the character has the {@code HOMICIDE} personnel status. + * + * @return {@code true} if the character has the {@code HOMICIDE} personnel status {@code false} + * otherwise. + */ public boolean isHomicide() { return this == HOMICIDE; } + /** + * Checks if the character has the {@code WOUNDS} personnel status. + * + * @return {@code true} if the character has the {@code WOUNDS} personnel status {@code false} + * otherwise. + */ public boolean isWounds() { return this == WOUNDS; } + /** + * Checks if the character has the {@code DISEASE} personnel status. + * + * @return {@code true} if the character has the {@code DISEASE} personnel status {@code false} + * otherwise. + */ public boolean isDisease() { return this == DISEASE; } + /** + * Checks if the character has the {@code ACCIDENTAL} personnel status. + * + * @return {@code true} if the character has the {@code ACCIDENTAL} personnel status {@code false} + * otherwise. + */ public boolean isAccidental() { return this == ACCIDENTAL; } + /** + * Checks if the character has the {@code NATURAL_CAUSES} personnel status. + * + * @return {@code true} if the character has the {@code NATURAL_CAUSES} personnel status {@code false} + * otherwise. + */ public boolean isNaturalCauses() { return this == NATURAL_CAUSES; } + /** + * Checks if the character has the {@code OLD_AGE} personnel status. + * + * @return {@code true} if the character has the {@code OLD_AGE} personnel status {@code false} + * otherwise. + */ public boolean isOldAge() { return this == OLD_AGE; } + /** + * Checks if the character has the {@code MEDICAL_COMPLICATIONS} personnel status. + * + * @return {@code true} if the character has the {@code MEDICAL_COMPLICATIONS} personnel status + * {@code false} otherwise. + */ public boolean isMedicalComplications() { return this == MEDICAL_COMPLICATIONS; } + /** + * Checks if the character has the {@code PREGNANCY_COMPLICATIONS} personnel status. + * + * @return {@code true} if the character has the {@code PREGNANCY_COMPLICATIONS} personnel status + * {@code false} otherwise. + */ public boolean isPregnancyComplications() { return this == PREGNANCY_COMPLICATIONS; } + /** + * Checks if the character has the {@code UNDETERMINED} personnel status. + * + * @return {@code true} if the character has the {@code UNDETERMINED} personnel status {@code false} + * otherwise. + */ public boolean isUndetermined() { return this == UNDETERMINED; } + /** + * Checks if the character has the {@code SUICIDE} personnel status. + * + * @return {@code true} if the character has the {@code SUICIDE} personnel status {@code false} + * otherwise. + */ public boolean isSuicide() { return this == SUICIDE; } /** - * @return true if a person is currently absent from the core force, otherwise - * false + * @return {@code true} if a person is currently absent from the core force, otherwise + * {@code false} */ public boolean isAbsent() { return isMIA() || isPoW() || isOnLeave() || isOnMaternityLeave() || isAwol() || isStudent() || isMissing(); } /** - * @return true if a person has left the unit, otherwise false + * @return {@code true} if a person has left the unit, otherwise {@code false} */ public boolean isDepartedUnit() { return isDead() || isRetired() || isResigned() || isSacked() || isDeserted() || isDefected() || isMissing() @@ -234,7 +407,7 @@ public boolean isDepartedUnit() { } /** - * @return true if a person is dead, otherwise false + * @return {@code true} if a person is dead, otherwise {@code false} */ public boolean isDead() { return isKIA() || isHomicide() || isWounds() || isDisease() || isAccidental() @@ -243,13 +416,16 @@ public boolean isDead() { } /** - * @return true if a person is dead or MIA, otherwise false + * @return {@code true} if a person is dead or MIA, otherwise {@code false} */ public boolean isDeadOrMIA() { return isDead() || isMIA(); } // endregion Boolean Comparison Methods + /** + * @return The list of implemented personnel statuses. + */ public static List getImplementedStatuses() { return Stream.of(values()) .collect(Collectors.toList()); @@ -257,15 +433,16 @@ public static List getImplementedStatuses() { // region File I/O /** - * @param text containing the PersonnelStatus - * @return the saved PersonnelStatus + * Parses a string representation of {@link PersonnelStatus} into a {@link PersonnelStatus} object. + * If the string representation cannot be parsed, it returns the default {@code PersonnelStatus.ACTIVE}. + * + * @param text The {@link String} representation of {@link PersonnelStatus} + * @return The parsed {@link PersonnelStatus} object or {@code PersonnelStatus.ACTIVE} if parsing fails */ public static PersonnelStatus parseFromString(final String text) { try { return valueOf(text); - } catch (Exception ignored) { - - } + } catch (Exception ignored) {} try { switch (Integer.parseInt(text)) { @@ -320,11 +497,11 @@ public static PersonnelStatus parseFromString(final String text) { default: break; } - } catch (Exception ignored) { + } catch (Exception ignored) {} - } String message = String.format("Unable to parse %s into a PersonnelStatus. Returning ACTIVE.", text); + MMLogger.create(PersonnelStatus.class).error(message); return ACTIVE; } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java index d328296a06..db526631d2 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java @@ -28,6 +28,15 @@ import static megamek.client.ui.WrapLayout.wordWrap; +/** + * An enumeration representing the available random divorce methods. + *

+ * The {@link RandomDivorceMethod} enum is used to specify the method of randomly generating a divorce. + * It supports two methods: {@code NONE} and {@code DICE_ROLL}. + *

+ * The {@code NONE} method represents no random divorce generation, and the {@code DICE_ROLL} method + * represents randomly generated divorce using dice rolls. + */ public enum RandomDivorceMethod { //region Enum Declarations NONE("RandomDivorceMethod.NONE.text", "RandomDivorceMethod.NONE.toolTipText"), @@ -40,6 +49,13 @@ public enum RandomDivorceMethod { //endregion Variable Declarations //region Constructors + /** + * Constructor for the {@link RandomDivorceMethod} class. + * Initializes the name and toolTipText variables using the specified name and toolTipText resources. + * + * @param name the name resource key used to retrieve the name from the resource bundle + * @param toolTipText the tooltip text resource key used to retrieve the tool tip text from the resource bundle + */ RandomDivorceMethod(final String name, final String toolTipText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); @@ -49,24 +65,40 @@ public enum RandomDivorceMethod { //endregion Constructors //region Getters - @SuppressWarnings(value = "unused") + /** + * @return the tooltip text for the current object + */ public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparisons - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomDivorceMethod} is {@code NONE}. + * + * @return {@code true} if the current {@link RandomDivorceMethod} is {@code NONE}, + * {@code false} otherwise. + */ public boolean isNone() { return this == NONE; } - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomDivorceMethod} is {@code DICE_ROLL}. + * + * @return {@code true} if the current {@link RandomDivorceMethod} is {@code DICE_ROLL}, + * {@code false} otherwise. + */ public boolean isDiceRoll() { return this == DICE_ROLL; } //endregion Boolean Comparisons + /** + * @param options the {@link CampaignOptions} object used to initialize the {@link AbstractDivorce} instance + * @return an instance of {@link AbstractDivorce} based on the {@link RandomDivorceMethod} + */ public AbstractDivorce getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { return new RandomDivorce(options); diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java index 9c8bddbac2..aa9bd9d8dc 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java @@ -28,6 +28,13 @@ import static megamek.client.ui.WrapLayout.wordWrap; +/** + * The {@link RandomMarriageMethod} enum represents different methods of getting random marriages. + *

+ * The available methods are: + * - {@code NONE}: No random marriage method. + * - {@code DICE_ROLL}: Random marriage method using dice roll. + */ public enum RandomMarriageMethod { //region Enum Declarations NONE("RandomMarriageMethod.NONE.text", "RandomMarriageMethod.NONE.toolTipText"), @@ -39,6 +46,13 @@ public enum RandomMarriageMethod { private final String toolTipText; //endregion Variable Declarations + /** + * Constructor for the {@link RandomMarriageMethod} class. + * Initializes the name and toolTipText variables using the specified name and toolTipText resources. + * + * @param name the name resource key used to retrieve the name from the resource bundle + * @param toolTipText the tooltip text resource key used to retrieve the tool tip text from the resource bundle + */ //region Constructors RandomMarriageMethod(final String name, final String toolTipText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", @@ -48,25 +62,41 @@ public enum RandomMarriageMethod { } //endregion Constructors + /** + * @return The tooltip text associated with the current instance of the class. + */ //region Getters - @SuppressWarnings(value = "unused") public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparison Methods - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomMarriageMethod} is {@code NONE}. + * + * @return {@code true} if the current {@link RandomMarriageMethod} is {@code NONE}, + * {@code false} otherwise. + */ public boolean isNone() { return this == NONE; } - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomMarriageMethod} is {@code DICE_ROLL}. + * + * @return {@code true} if the current {@link RandomMarriageMethod} is {@code DICE_ROLL}, + * {@code false} otherwise. + */ public boolean isDiceRoll() { return this == DICE_ROLL; } //endregion Boolean Comparison Methods + /** + * @param options the {@link CampaignOptions} object used to initialize the {@link AbstractMarriage} instance + * @return an instance of {@link AbstractMarriage} based on the {@link RandomMarriageMethod} + */ public AbstractMarriage getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { return new RandomMarriage(options); diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java index 471bfabc8a..2cef0e7441 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java @@ -28,6 +28,13 @@ import static megamek.client.ui.WrapLayout.wordWrap; +/** + * The {@link RandomProcreationMethod} enum represents different methods of getting random procreation. + *

+ * The available methods are: + * - {@code NONE}: No random procreation method. + * - {@code DICE_ROLL}: Random procreation method using dice roll. + */ public enum RandomProcreationMethod { //region Enum Declarations NONE("RandomProcreationMethod.NONE.text", "RandomProcreationMethod.NONE.toolTipText"), @@ -40,6 +47,13 @@ public enum RandomProcreationMethod { //endregion Variable Declarations //region Constructors + /** + * Constructor for the {@link RandomProcreationMethod} class. + * Initializes the name and toolTipText variables using the specified name and toolTipText resources. + * + * @param name the name resource key used to retrieve the name from the resource bundle + * @param toolTipText the tooltip text resource key used to retrieve the tool tip text from the resource bundle + */ RandomProcreationMethod(final String name, final String toolTipText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); @@ -49,24 +63,40 @@ public enum RandomProcreationMethod { //endregion Constructors //region Getters - @SuppressWarnings(value = "unused") + /** + * @return The tooltip text associated with the current instance of the class. + */ public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparison Methods - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomProcreationMethod} is {@code NONE}. + * + * @return {@code true} if the current {@link RandomProcreationMethod} is {@code NONE}, + * {@code false} otherwise. + */ public boolean isNone() { return this == NONE; } - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomProcreationMethod} is {@code DICE_ROLL}. + * + * @return {@code true} if the current {@link RandomProcreationMethod} is {@code DICE_ROLL}, + * {@code false} otherwise. + */ public boolean isDiceRoll() { return this == DICE_ROLL; } //endregion Boolean Comparison Methods + /** + * @param options the {@link CampaignOptions} object used to initialize the {@link AbstractProcreation} instance + * @return an instance of {@link AbstractProcreation} based on the {@link RandomProcreationMethod} + */ public AbstractProcreation getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { return new RandomProcreation(options); diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 15e1f24fd0..536434303c 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -65,47 +65,38 @@ protected AbstractMarriage(final RandomMarriageMethod method, final CampaignOpti //endregion Constructors //region Getters/Setters - @SuppressWarnings(value = "unused") public RandomMarriageMethod getMethod() { return method; } - @SuppressWarnings(value = "unused") public boolean isUseClanPersonnelMarriages() { return useClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public void setUseClanPersonnelMarriages(final boolean useClanPersonnelMarriages) { this.useClanPersonnelMarriages = useClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public boolean isUsePrisonerMarriages() { return usePrisonerMarriages; } - @SuppressWarnings(value = "unused") public void setUsePrisonerMarriages(final boolean usePrisonerMarriages) { this.usePrisonerMarriages = usePrisonerMarriages; } - @SuppressWarnings(value = "unused") public boolean isUseRandomClanPersonnelMarriages() { return useRandomClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public void setUseRandomClanPersonnelMarriages(final boolean useRandomClanPersonnelMarriages) { this.useRandomClanPersonnelMarriages = useRandomClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public boolean isUseRandomPrisonerMarriages() { return useRandomPrisonerMarriages; } - @SuppressWarnings(value = "unused") public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriages) { this.useRandomPrisonerMarriages = useRandomPrisonerMarriages; } @@ -113,7 +104,6 @@ public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriag /** * This is used to determine if a person can marry - * @param campaign the campaign the person is a part of * @param today the current date * @param person the person to determine for * @param randomMarriage if this is for random marriage or manual marriage diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index 9b8a3242b9..dbb82764c0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -22,12 +22,23 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.enums.RandomMarriageMethod; +/** + * {@link RandomMarriage} class represents a type of marriage where the result is determined by + * rolling a die. + * It extends the {@link AbstractMarriage} class. + */ public class RandomMarriage extends AbstractMarriage { //region Variable Declarations private int marriageDiceSize; //endregion Variable Declarations //region Constructors + /** + * Constructs a {@link RandomMarriage} object. This object is used to manage randomly determined + * marriages. + * + * @param options the {@link CampaignOptions} object that contains current game campaign settings. + */ public RandomMarriage(final CampaignOptions options) { super(RandomMarriageMethod.DICE_ROLL, options); @@ -36,12 +47,11 @@ public RandomMarriage(final CampaignOptions options) { //endregion Constructors //region Getters/Setters - @SuppressWarnings(value = "unused") - public int getMarriageDiceSize() { - return marriageDiceSize; - } - - @SuppressWarnings(value = "unused") + /** + * Sets the size of the marriage dice used in a random marriage. + * + * @param marriageDiceSize the size of the marriage dice to set + */ public void setMarriageDiceSize(final int marriageDiceSize) { this.marriageDiceSize = marriageDiceSize; } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java index 1e78c3142f..8a30e6ecc2 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java @@ -23,6 +23,9 @@ import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomProcreationMethod; +/** + * Represents a random procreation method that is based on dice rolls. + */ public class RandomProcreation extends AbstractProcreation { //region Variable Declarations private int relationshipDieSize; @@ -30,6 +33,12 @@ public class RandomProcreation extends AbstractProcreation { //endregion Variable Declarations //region Constructors + /** + * Constructor to create a {@link RandomProcreation} object. This object is used to manage + * randomly determined procreation events within the game's campaign. + * + * @param options the campaign settings. + */ public RandomProcreation(final CampaignOptions options) { super(RandomProcreationMethod.DICE_ROLL, options); setRelationshipDieSize(options.getRandomProcreationRelationshipDiceSize()); @@ -38,22 +47,23 @@ public RandomProcreation(final CampaignOptions options) { //endregion Constructors //region Getters/Setters - @SuppressWarnings(value = "unused") - public double getRelationshipDieSize() { - return relationshipDieSize; - } - - @SuppressWarnings(value = "unused") + /** + * Sets the size of the relationship die. + * The relationship die size determines the probability of procreation for a person who has a spouse. + * + * @param relationshipDieSize the size of the relationship die + */ public void setRelationshipDieSize(final int relationshipDieSize) { this.relationshipDieSize = relationshipDieSize; } - @SuppressWarnings(value = "unused") - public double getRelationshiplessDieSize() { - return relationshiplessDieSize; - } - - @SuppressWarnings(value = "unused") + /** + * Sets the size of the relationshipless die. + * The relationship die size determines the probability of procreation for a person who does not + * have a spouse. + * + * @param relationshiplessDieSize the size of the relationship die + */ public void setRelationshiplessDieSize(final int relationshiplessDieSize) { this.relationshiplessDieSize = relationshiplessDieSize; } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java index b2e8a695b3..773a4198c6 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java @@ -54,29 +54,6 @@ public void beforeEach() { lenient().when(mockCampaign.getCampaignOptions()).thenReturn(mockCampaignOptions); } - //region Getters/Setters - @Disabled // FIXME : Windchild : Test Missing - @Test - public void testGettersAndSetters() { -/* - when(mockCampaignOptions.isUseClanPersonnelDivorce()).thenReturn(false); - when(mockCampaignOptions.isUsePrisonerDivorce()).thenReturn(false); - when(mockCampaignOptions.isUseRandomSameSexDivorce()).thenReturn(false); - when(mockCampaignOptions.isUseRandomClanPersonnelDivorce()).thenReturn(false); - when(mockCampaignOptions.isUseRandomPrisonerDivorce()).thenReturn(false); - - final AbstractDivorce disabledDivorce = new DisabledRandomDivorce(mockCampaignOptions); - - assertEquals(RandomDivorceMethod.NONE, disabledDivorce.getMethod()); - assertFalse(disabledDivorce.isUseClanPersonnelDivorce()); - assertFalse(disabledDivorce.isUsePrisonerDivorce()); - assertFalse(disabledDivorce.isUseRandomSameSexDivorce()); - assertFalse(disabledDivorce.isUseRandomClanPersonnelDivorce()); - assertFalse(disabledDivorce.isUseRandomPrisonerDivorce()); -*/ - } - //endregion Getters/Setters - @Disabled // FIXME : Windchild : Test Missing @Test public void testCanDivorce() { From 30e3fe18a9cfbbdfe14d0ab9ddfe21ae36c2cd0c Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Tue, 24 Sep 2024 20:48:02 -0500 Subject: [PATCH 38/41] Remove @SuppressWarnings annotations and add documentation Removed redundant @SuppressWarnings annotations from multiple classes and enhanced codebase documentation. The changes add clarity to the functionality of classes and methods through JavaDocs, improving maintainability and readability. --- .../mekhq/campaign/io/CampaignXmlParser.java | 4 +- .../personnel/divorce/AbstractDivorce.java | 10 +- .../personnel/divorce/RandomDivorce.java | 21 +- .../personnel/enums/PersonnelStatus.java | 203 ++++++++++++++++-- .../personnel/enums/RandomDivorceMethod.java | 38 +++- .../personnel/enums/RandomMarriageMethod.java | 36 +++- .../enums/RandomProcreationMethod.java | 36 +++- .../personnel/marriage/AbstractMarriage.java | 10 - .../personnel/marriage/RandomMarriage.java | 22 +- .../procreation/RandomProcreation.java | 34 +-- .../divorce/AbstractDivorceTest.java | 23 -- 11 files changed, 359 insertions(+), 78 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java index 3251695314..8999037e6e 100644 --- a/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java +++ b/MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java @@ -252,7 +252,7 @@ public Campaign parse() throws CampaignXmlParseException, NullEntityException { } else if (xn.equalsIgnoreCase("location")) { retVal.setLocation(CurrentLocation.generateInstanceFromXML(wn, retVal)); } else if (xn.equalsIgnoreCase("skillTypes")) { - processSkillTypeNodes(retVal, wn, version); + processSkillTypeNodes(wn); } else if (xn.equalsIgnoreCase("specialAbilities")) { processSpecialAbilityNodes(retVal, wn, version); } else if (xn.equalsIgnoreCase("storyArc")) { @@ -890,7 +890,7 @@ private static void processPersonnelNodes(Campaign retVal, Node wn, Version vers logger.info("Load Personnel Nodes Complete!"); } - private static void processSkillTypeNodes(Campaign retVal, Node wn, Version version) { + private static void processSkillTypeNodes(Node wn) { logger.info("Loading Skill Type Nodes from XML..."); NodeList wList = wn.getChildNodes(); diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java index cf5b9a2fa7..1d4642f854 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/AbstractDivorce.java @@ -173,7 +173,7 @@ public void setUseRandomPrisonerDivorce(final boolean useRandomPrisonerDivorce) /** * This is a standardization method for the divorce surname style to use when a person's spouse * dies. - * + *

* TODO : I should be part of AbstractDeath * * @param campaign the campaign the person is in @@ -300,6 +300,14 @@ public void divorce(final Campaign campaign, final LocalDate today, final Person MekHQ.triggerEvent(new PersonChangedEvent(origin)); } + /** + * Processes divorce events that occur as part of a character's background. + * + * @param campaign the campaign associated with the divorce + * @param today the current date of the divorce + * @param origin the person whose background is being divorced + * @param style the splitting surname style to be applied + */ public void backgroundDivorce(final Campaign campaign, final LocalDate today, final Person origin, final SplittingSurnameStyle style) { final Person spouse = origin.getGenealogy().getSpouse(); diff --git a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java index bbe0a163a1..5226acc6c6 100644 --- a/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java +++ b/MekHQ/src/mekhq/campaign/personnel/divorce/RandomDivorce.java @@ -22,25 +22,42 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.enums.RandomDivorceMethod; +/** + * The {@link RandomDivorce} class is an implementation of the {@link AbstractDivorce} class that + * represents a divorce method based on random chance. + * The divorce outcome is determined by rolling a die with a specified number of sides. + */ public class RandomDivorce extends AbstractDivorce { //region Variable Declarations private int divorceDiceSize; //endregion Variable Declarations //region Constructors + /** + * The {@link RandomDivorce} class is an implementation of the {@link AbstractDivorce} class that + * represents a divorce method based on random chance. + */ public RandomDivorce(final CampaignOptions options) { super(RandomDivorceMethod.DICE_ROLL, options); setDivorceDiceSize(options.getRandomDivorceDiceSize()); } //endregion Constructors + /** + * Retrieves the size of the divorce dice. + * + * @return The size of the divorce dice as an integer. + */ //region Getters/Setters - @SuppressWarnings(value = "unused") public int getDivorceDiceSize() { return divorceDiceSize; } - @SuppressWarnings(value = "unused") + /** + * Sets the size of the divorce dice. + * + * @param divorceDiceSize the size of the dice used to determine divorce outcomes + */ public void setDivorceDiceSize(final int divorceDiceSize) { this.divorceDiceSize = divorceDiceSize; } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java index 005baf2f40..5d7794974b 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/PersonnelStatus.java @@ -27,7 +27,7 @@ import java.util.stream.Stream; /** - * TODO : Add PoW, On Leave and AWOL implementations + * Enum class representing personnel status. */ public enum PersonnelStatus { // region Enum Declarations @@ -91,6 +91,14 @@ public enum PersonnelStatus { // endregion Variable Declarations // region Constructors + /** + * Initializes a new instance of the {@link PersonnelStatus} class with the given parameters. + * + * @param name the name of the personnel status + * @param toolTipText the tooltip text for the personnel status + * @param reportText the report text for the personnel status + * @param logText the log text for the personnel status + */ PersonnelStatus(final String name, final String toolTipText, final String reportText, final String logText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", @@ -102,131 +110,296 @@ public enum PersonnelStatus { } // endregion Constructors + /** + * Retrieves the tooltip text for a given component. + * + * @return The tooltip text of the component, or null if no tooltip text is set. + */ // region Getters public String getToolTipText() { return toolTipText; } + /** + * Retrieves the report text. + * + * @return The report text as a string. + */ public String getReportText() { return reportText; } + /** + * Retrieves the log text. + * + * @return The log text. + */ public String getLogText() { return logText; } // endregion Getters // region Boolean Comparison Methods + /** + * Checks if the character has the {@code ACTIVE} personnel status. + * + * @return {@code true} if the character has the {@code ACTIVE} personnel status {@code false} + * otherwise. + */ public boolean isActive() { return this == ACTIVE; } + /** + * Checks if the character has the {@code MIA} personnel status. + * + * @return {@code true} if the character has the {@code MIA} personnel status {@code false} + * otherwise. + */ public boolean isMIA() { return this == MIA; } + /** + * Checks if the character has the {@code POW} personnel status. + * + * @return {@code true} if the character has the {@code POW} personnel status {@code false} + * otherwise. + */ public boolean isPoW() { return this == POW; } + /** + * Checks if the character has the {@code ON_LEAVE} personnel status. + * + * @return {@code true} if the character has the {@code ON_LEAVE} personnel status {@code false} + * otherwise. + */ public boolean isOnLeave() { return this == ON_LEAVE; } + /** + * Checks if the character has the {@code ON_MATERNITY_LEAVE} personnel status. + * + * @return {@code true} if the character has the {@code ON_MATERNITY_LEAVE} personnel status + * {@code false} otherwise. + */ public boolean isOnMaternityLeave() { return this == ON_MATERNITY_LEAVE; } + /** + * Checks if the character has the {@code AWOL} personnel status. + * + * @return {@code true} if the character has the {@code AWOL} personnel status {@code false} + * otherwise. + */ public boolean isAwol() { return this == AWOL; } + /** + * Checks if the character has the {@code RETIRED} personnel status. + * + * @return {@code true} if the character has the {@code RETIRED} personnel status {@code false} + * otherwise. + */ public boolean isRetired() { return this == RETIRED; } + /** + * Checks if the character has the {@code RESIGNED} personnel status. + * + * @return {@code true} if the character has the {@code RESIGNED} personnel status {@code false} + * otherwise. + */ public boolean isResigned() { return this == RESIGNED; } + /** + * Checks if the character has the {@code SACKED} personnel status. + * + * @return {@code true} if the character has the {@code SACKED} personnel status {@code false} + * otherwise. + */ public boolean isSacked() { return this == SACKED; } + /** + * Checks if the character has the {@code LEFT} personnel status. + * + * @return {@code true} if the character has the {@code LEFT} personnel status {@code false} + * otherwise. + */ public boolean isLeft() { return this == LEFT; } + /** + * Checks if the character has the {@code DESERTED} personnel status. + * + * @return {@code true} if the character has the {@code DESERTED} personnel status {@code false} + * otherwise. + */ public boolean isDeserted() { return this == DESERTED; } + /** + * Checks if the character has the {@code DEFECTED} personnel status. + * + * @return {@code true} if the character has the {@code DEFECTED} personnel status {@code false} + * otherwise. + */ public boolean isDefected() { return this == DEFECTED; } + /** + * Checks if the character has the {@code STUDENT} personnel status. + * + * @return {@code true} if the character has the {@code STUDENT} personnel status {@code false} + * otherwise. + */ public boolean isStudent() { return this == STUDENT; } + /** + * Checks if the character has the {@code MISSING} personnel status. + * + * @return {@code true} if the character has the {@code MISSING} personnel status {@code false} + * otherwise. + */ public boolean isMissing() { return this == MISSING; } + /** + * Checks if the character has the {@code KIA} personnel status. + * + * @return {@code true} if the character has the {@code KIA} personnel status {@code false} + * otherwise. + */ public boolean isKIA() { return this == KIA; } + /** + * Checks if the character has the {@code HOMICIDE} personnel status. + * + * @return {@code true} if the character has the {@code HOMICIDE} personnel status {@code false} + * otherwise. + */ public boolean isHomicide() { return this == HOMICIDE; } + /** + * Checks if the character has the {@code WOUNDS} personnel status. + * + * @return {@code true} if the character has the {@code WOUNDS} personnel status {@code false} + * otherwise. + */ public boolean isWounds() { return this == WOUNDS; } + /** + * Checks if the character has the {@code DISEASE} personnel status. + * + * @return {@code true} if the character has the {@code DISEASE} personnel status {@code false} + * otherwise. + */ public boolean isDisease() { return this == DISEASE; } + /** + * Checks if the character has the {@code ACCIDENTAL} personnel status. + * + * @return {@code true} if the character has the {@code ACCIDENTAL} personnel status {@code false} + * otherwise. + */ public boolean isAccidental() { return this == ACCIDENTAL; } + /** + * Checks if the character has the {@code NATURAL_CAUSES} personnel status. + * + * @return {@code true} if the character has the {@code NATURAL_CAUSES} personnel status {@code false} + * otherwise. + */ public boolean isNaturalCauses() { return this == NATURAL_CAUSES; } + /** + * Checks if the character has the {@code OLD_AGE} personnel status. + * + * @return {@code true} if the character has the {@code OLD_AGE} personnel status {@code false} + * otherwise. + */ public boolean isOldAge() { return this == OLD_AGE; } + /** + * Checks if the character has the {@code MEDICAL_COMPLICATIONS} personnel status. + * + * @return {@code true} if the character has the {@code MEDICAL_COMPLICATIONS} personnel status + * {@code false} otherwise. + */ public boolean isMedicalComplications() { return this == MEDICAL_COMPLICATIONS; } + /** + * Checks if the character has the {@code PREGNANCY_COMPLICATIONS} personnel status. + * + * @return {@code true} if the character has the {@code PREGNANCY_COMPLICATIONS} personnel status + * {@code false} otherwise. + */ public boolean isPregnancyComplications() { return this == PREGNANCY_COMPLICATIONS; } + /** + * Checks if the character has the {@code UNDETERMINED} personnel status. + * + * @return {@code true} if the character has the {@code UNDETERMINED} personnel status {@code false} + * otherwise. + */ public boolean isUndetermined() { return this == UNDETERMINED; } + /** + * Checks if the character has the {@code SUICIDE} personnel status. + * + * @return {@code true} if the character has the {@code SUICIDE} personnel status {@code false} + * otherwise. + */ public boolean isSuicide() { return this == SUICIDE; } /** - * @return true if a person is currently absent from the core force, otherwise - * false + * @return {@code true} if a person is currently absent from the core force, otherwise + * {@code false} */ public boolean isAbsent() { return isMIA() || isPoW() || isOnLeave() || isOnMaternityLeave() || isAwol() || isStudent() || isMissing(); } /** - * @return true if a person has left the unit, otherwise false + * @return {@code true} if a person has left the unit, otherwise {@code false} */ public boolean isDepartedUnit() { return isDead() || isRetired() || isResigned() || isSacked() || isDeserted() || isDefected() || isMissing() @@ -234,7 +407,7 @@ public boolean isDepartedUnit() { } /** - * @return true if a person is dead, otherwise false + * @return {@code true} if a person is dead, otherwise {@code false} */ public boolean isDead() { return isKIA() || isHomicide() || isWounds() || isDisease() || isAccidental() @@ -243,13 +416,16 @@ public boolean isDead() { } /** - * @return true if a person is dead or MIA, otherwise false + * @return {@code true} if a person is dead or MIA, otherwise {@code false} */ public boolean isDeadOrMIA() { return isDead() || isMIA(); } // endregion Boolean Comparison Methods + /** + * @return The list of implemented personnel statuses. + */ public static List getImplementedStatuses() { return Stream.of(values()) .collect(Collectors.toList()); @@ -257,15 +433,16 @@ public static List getImplementedStatuses() { // region File I/O /** - * @param text containing the PersonnelStatus - * @return the saved PersonnelStatus + * Parses a string representation of {@link PersonnelStatus} into a {@link PersonnelStatus} object. + * If the string representation cannot be parsed, it returns the default {@code PersonnelStatus.ACTIVE}. + * + * @param text The {@link String} representation of {@link PersonnelStatus} + * @return The parsed {@link PersonnelStatus} object or {@code PersonnelStatus.ACTIVE} if parsing fails */ public static PersonnelStatus parseFromString(final String text) { try { return valueOf(text); - } catch (Exception ignored) { - - } + } catch (Exception ignored) {} try { switch (Integer.parseInt(text)) { @@ -320,11 +497,11 @@ public static PersonnelStatus parseFromString(final String text) { default: break; } - } catch (Exception ignored) { + } catch (Exception ignored) {} - } String message = String.format("Unable to parse %s into a PersonnelStatus. Returning ACTIVE.", text); + MMLogger.create(PersonnelStatus.class).error(message); return ACTIVE; } diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java index d328296a06..db526631d2 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomDivorceMethod.java @@ -28,6 +28,15 @@ import static megamek.client.ui.WrapLayout.wordWrap; +/** + * An enumeration representing the available random divorce methods. + *

+ * The {@link RandomDivorceMethod} enum is used to specify the method of randomly generating a divorce. + * It supports two methods: {@code NONE} and {@code DICE_ROLL}. + *

+ * The {@code NONE} method represents no random divorce generation, and the {@code DICE_ROLL} method + * represents randomly generated divorce using dice rolls. + */ public enum RandomDivorceMethod { //region Enum Declarations NONE("RandomDivorceMethod.NONE.text", "RandomDivorceMethod.NONE.toolTipText"), @@ -40,6 +49,13 @@ public enum RandomDivorceMethod { //endregion Variable Declarations //region Constructors + /** + * Constructor for the {@link RandomDivorceMethod} class. + * Initializes the name and toolTipText variables using the specified name and toolTipText resources. + * + * @param name the name resource key used to retrieve the name from the resource bundle + * @param toolTipText the tooltip text resource key used to retrieve the tool tip text from the resource bundle + */ RandomDivorceMethod(final String name, final String toolTipText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); @@ -49,24 +65,40 @@ public enum RandomDivorceMethod { //endregion Constructors //region Getters - @SuppressWarnings(value = "unused") + /** + * @return the tooltip text for the current object + */ public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparisons - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomDivorceMethod} is {@code NONE}. + * + * @return {@code true} if the current {@link RandomDivorceMethod} is {@code NONE}, + * {@code false} otherwise. + */ public boolean isNone() { return this == NONE; } - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomDivorceMethod} is {@code DICE_ROLL}. + * + * @return {@code true} if the current {@link RandomDivorceMethod} is {@code DICE_ROLL}, + * {@code false} otherwise. + */ public boolean isDiceRoll() { return this == DICE_ROLL; } //endregion Boolean Comparisons + /** + * @param options the {@link CampaignOptions} object used to initialize the {@link AbstractDivorce} instance + * @return an instance of {@link AbstractDivorce} based on the {@link RandomDivorceMethod} + */ public AbstractDivorce getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { return new RandomDivorce(options); diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java index 9c8bddbac2..aa9bd9d8dc 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomMarriageMethod.java @@ -28,6 +28,13 @@ import static megamek.client.ui.WrapLayout.wordWrap; +/** + * The {@link RandomMarriageMethod} enum represents different methods of getting random marriages. + *

+ * The available methods are: + * - {@code NONE}: No random marriage method. + * - {@code DICE_ROLL}: Random marriage method using dice roll. + */ public enum RandomMarriageMethod { //region Enum Declarations NONE("RandomMarriageMethod.NONE.text", "RandomMarriageMethod.NONE.toolTipText"), @@ -39,6 +46,13 @@ public enum RandomMarriageMethod { private final String toolTipText; //endregion Variable Declarations + /** + * Constructor for the {@link RandomMarriageMethod} class. + * Initializes the name and toolTipText variables using the specified name and toolTipText resources. + * + * @param name the name resource key used to retrieve the name from the resource bundle + * @param toolTipText the tooltip text resource key used to retrieve the tool tip text from the resource bundle + */ //region Constructors RandomMarriageMethod(final String name, final String toolTipText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", @@ -48,25 +62,41 @@ public enum RandomMarriageMethod { } //endregion Constructors + /** + * @return The tooltip text associated with the current instance of the class. + */ //region Getters - @SuppressWarnings(value = "unused") public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparison Methods - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomMarriageMethod} is {@code NONE}. + * + * @return {@code true} if the current {@link RandomMarriageMethod} is {@code NONE}, + * {@code false} otherwise. + */ public boolean isNone() { return this == NONE; } - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomMarriageMethod} is {@code DICE_ROLL}. + * + * @return {@code true} if the current {@link RandomMarriageMethod} is {@code DICE_ROLL}, + * {@code false} otherwise. + */ public boolean isDiceRoll() { return this == DICE_ROLL; } //endregion Boolean Comparison Methods + /** + * @param options the {@link CampaignOptions} object used to initialize the {@link AbstractMarriage} instance + * @return an instance of {@link AbstractMarriage} based on the {@link RandomMarriageMethod} + */ public AbstractMarriage getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { return new RandomMarriage(options); diff --git a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java index 471bfabc8a..2cef0e7441 100644 --- a/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java +++ b/MekHQ/src/mekhq/campaign/personnel/enums/RandomProcreationMethod.java @@ -28,6 +28,13 @@ import static megamek.client.ui.WrapLayout.wordWrap; +/** + * The {@link RandomProcreationMethod} enum represents different methods of getting random procreation. + *

+ * The available methods are: + * - {@code NONE}: No random procreation method. + * - {@code DICE_ROLL}: Random procreation method using dice roll. + */ public enum RandomProcreationMethod { //region Enum Declarations NONE("RandomProcreationMethod.NONE.text", "RandomProcreationMethod.NONE.toolTipText"), @@ -40,6 +47,13 @@ public enum RandomProcreationMethod { //endregion Variable Declarations //region Constructors + /** + * Constructor for the {@link RandomProcreationMethod} class. + * Initializes the name and toolTipText variables using the specified name and toolTipText resources. + * + * @param name the name resource key used to retrieve the name from the resource bundle + * @param toolTipText the tooltip text resource key used to retrieve the tool tip text from the resource bundle + */ RandomProcreationMethod(final String name, final String toolTipText) { final ResourceBundle resources = ResourceBundle.getBundle("mekhq.resources.Personnel", MekHQ.getMHQOptions().getLocale()); @@ -49,24 +63,40 @@ public enum RandomProcreationMethod { //endregion Constructors //region Getters - @SuppressWarnings(value = "unused") + /** + * @return The tooltip text associated with the current instance of the class. + */ public String getToolTipText() { return toolTipText; } //endregion Getters //region Boolean Comparison Methods - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomProcreationMethod} is {@code NONE}. + * + * @return {@code true} if the current {@link RandomProcreationMethod} is {@code NONE}, + * {@code false} otherwise. + */ public boolean isNone() { return this == NONE; } - @SuppressWarnings(value = "unused") + /** + * Checks if the current {@link RandomProcreationMethod} is {@code DICE_ROLL}. + * + * @return {@code true} if the current {@link RandomProcreationMethod} is {@code DICE_ROLL}, + * {@code false} otherwise. + */ public boolean isDiceRoll() { return this == DICE_ROLL; } //endregion Boolean Comparison Methods + /** + * @param options the {@link CampaignOptions} object used to initialize the {@link AbstractProcreation} instance + * @return an instance of {@link AbstractProcreation} based on the {@link RandomProcreationMethod} + */ public AbstractProcreation getMethod(final CampaignOptions options) { if (this == DICE_ROLL) { return new RandomProcreation(options); diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java index 15e1f24fd0..536434303c 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/AbstractMarriage.java @@ -65,47 +65,38 @@ protected AbstractMarriage(final RandomMarriageMethod method, final CampaignOpti //endregion Constructors //region Getters/Setters - @SuppressWarnings(value = "unused") public RandomMarriageMethod getMethod() { return method; } - @SuppressWarnings(value = "unused") public boolean isUseClanPersonnelMarriages() { return useClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public void setUseClanPersonnelMarriages(final boolean useClanPersonnelMarriages) { this.useClanPersonnelMarriages = useClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public boolean isUsePrisonerMarriages() { return usePrisonerMarriages; } - @SuppressWarnings(value = "unused") public void setUsePrisonerMarriages(final boolean usePrisonerMarriages) { this.usePrisonerMarriages = usePrisonerMarriages; } - @SuppressWarnings(value = "unused") public boolean isUseRandomClanPersonnelMarriages() { return useRandomClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public void setUseRandomClanPersonnelMarriages(final boolean useRandomClanPersonnelMarriages) { this.useRandomClanPersonnelMarriages = useRandomClanPersonnelMarriages; } - @SuppressWarnings(value = "unused") public boolean isUseRandomPrisonerMarriages() { return useRandomPrisonerMarriages; } - @SuppressWarnings(value = "unused") public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriages) { this.useRandomPrisonerMarriages = useRandomPrisonerMarriages; } @@ -113,7 +104,6 @@ public void setUseRandomPrisonerMarriages(final boolean useRandomPrisonerMarriag /** * This is used to determine if a person can marry - * @param campaign the campaign the person is a part of * @param today the current date * @param person the person to determine for * @param randomMarriage if this is for random marriage or manual marriage diff --git a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java index 9b8a3242b9..dbb82764c0 100644 --- a/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java +++ b/MekHQ/src/mekhq/campaign/personnel/marriage/RandomMarriage.java @@ -22,12 +22,23 @@ import mekhq.campaign.CampaignOptions; import mekhq.campaign.personnel.enums.RandomMarriageMethod; +/** + * {@link RandomMarriage} class represents a type of marriage where the result is determined by + * rolling a die. + * It extends the {@link AbstractMarriage} class. + */ public class RandomMarriage extends AbstractMarriage { //region Variable Declarations private int marriageDiceSize; //endregion Variable Declarations //region Constructors + /** + * Constructs a {@link RandomMarriage} object. This object is used to manage randomly determined + * marriages. + * + * @param options the {@link CampaignOptions} object that contains current game campaign settings. + */ public RandomMarriage(final CampaignOptions options) { super(RandomMarriageMethod.DICE_ROLL, options); @@ -36,12 +47,11 @@ public RandomMarriage(final CampaignOptions options) { //endregion Constructors //region Getters/Setters - @SuppressWarnings(value = "unused") - public int getMarriageDiceSize() { - return marriageDiceSize; - } - - @SuppressWarnings(value = "unused") + /** + * Sets the size of the marriage dice used in a random marriage. + * + * @param marriageDiceSize the size of the marriage dice to set + */ public void setMarriageDiceSize(final int marriageDiceSize) { this.marriageDiceSize = marriageDiceSize; } diff --git a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java index 1e78c3142f..8a30e6ecc2 100644 --- a/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java +++ b/MekHQ/src/mekhq/campaign/personnel/procreation/RandomProcreation.java @@ -23,6 +23,9 @@ import mekhq.campaign.personnel.Person; import mekhq.campaign.personnel.enums.RandomProcreationMethod; +/** + * Represents a random procreation method that is based on dice rolls. + */ public class RandomProcreation extends AbstractProcreation { //region Variable Declarations private int relationshipDieSize; @@ -30,6 +33,12 @@ public class RandomProcreation extends AbstractProcreation { //endregion Variable Declarations //region Constructors + /** + * Constructor to create a {@link RandomProcreation} object. This object is used to manage + * randomly determined procreation events within the game's campaign. + * + * @param options the campaign settings. + */ public RandomProcreation(final CampaignOptions options) { super(RandomProcreationMethod.DICE_ROLL, options); setRelationshipDieSize(options.getRandomProcreationRelationshipDiceSize()); @@ -38,22 +47,23 @@ public RandomProcreation(final CampaignOptions options) { //endregion Constructors //region Getters/Setters - @SuppressWarnings(value = "unused") - public double getRelationshipDieSize() { - return relationshipDieSize; - } - - @SuppressWarnings(value = "unused") + /** + * Sets the size of the relationship die. + * The relationship die size determines the probability of procreation for a person who has a spouse. + * + * @param relationshipDieSize the size of the relationship die + */ public void setRelationshipDieSize(final int relationshipDieSize) { this.relationshipDieSize = relationshipDieSize; } - @SuppressWarnings(value = "unused") - public double getRelationshiplessDieSize() { - return relationshiplessDieSize; - } - - @SuppressWarnings(value = "unused") + /** + * Sets the size of the relationshipless die. + * The relationship die size determines the probability of procreation for a person who does not + * have a spouse. + * + * @param relationshiplessDieSize the size of the relationship die + */ public void setRelationshiplessDieSize(final int relationshiplessDieSize) { this.relationshiplessDieSize = relationshiplessDieSize; } diff --git a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java index b2e8a695b3..773a4198c6 100644 --- a/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java +++ b/MekHQ/unittests/mekhq/campaign/personnel/divorce/AbstractDivorceTest.java @@ -54,29 +54,6 @@ public void beforeEach() { lenient().when(mockCampaign.getCampaignOptions()).thenReturn(mockCampaignOptions); } - //region Getters/Setters - @Disabled // FIXME : Windchild : Test Missing - @Test - public void testGettersAndSetters() { -/* - when(mockCampaignOptions.isUseClanPersonnelDivorce()).thenReturn(false); - when(mockCampaignOptions.isUsePrisonerDivorce()).thenReturn(false); - when(mockCampaignOptions.isUseRandomSameSexDivorce()).thenReturn(false); - when(mockCampaignOptions.isUseRandomClanPersonnelDivorce()).thenReturn(false); - when(mockCampaignOptions.isUseRandomPrisonerDivorce()).thenReturn(false); - - final AbstractDivorce disabledDivorce = new DisabledRandomDivorce(mockCampaignOptions); - - assertEquals(RandomDivorceMethod.NONE, disabledDivorce.getMethod()); - assertFalse(disabledDivorce.isUseClanPersonnelDivorce()); - assertFalse(disabledDivorce.isUsePrisonerDivorce()); - assertFalse(disabledDivorce.isUseRandomSameSexDivorce()); - assertFalse(disabledDivorce.isUseRandomClanPersonnelDivorce()); - assertFalse(disabledDivorce.isUseRandomPrisonerDivorce()); -*/ - } - //endregion Getters/Setters - @Disabled // FIXME : Windchild : Test Missing @Test public void testCanDivorce() { From 837b344159361935726f87eaa57acfa65b975414 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Wed, 25 Sep 2024 10:22:54 -0500 Subject: [PATCH 39/41] Enhanced Random-Death Reporting Added color-coded messaging to ensure random death events are highly noticeable to users. Imported necessary utilities and refined new day processing to utilize the enhanced reporting mechanism. --- .../personnel/death/AbstractDeath.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java index 53988dce0b..1a5500bcac 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java @@ -18,18 +18,6 @@ */ package mekhq.campaign.personnel.death; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.time.LocalDate; -import java.util.HashMap; -import java.util.Map; -import java.util.ResourceBundle; - -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - import megamek.Version; import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; @@ -45,6 +33,20 @@ import mekhq.campaign.personnel.enums.RandomDeathMethod; import mekhq.campaign.personnel.enums.TenYearAgeRange; import mekhq.utilities.MHQXMLUtility; +import mekhq.utilities.ReportingUtilities; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.Map; +import java.util.ResourceBundle; + +import static mekhq.utilities.ReportingUtilities.CLOSING_SPAN_TAG; public abstract class AbstractDeath { private static final MMLogger logger = MMLogger.create(AbstractDeath.class); @@ -116,7 +118,7 @@ public Map>> get /** * This is used to determine if a person can die. - * + * * @param person the person to determine for * @param ageGroup the age group of the person in question * @param randomDeath if this is for random death or manual death @@ -144,7 +146,7 @@ public Map>> get // region New Day /** * Processes new day random death for an individual. - * + * * @param campaign the campaign to process * @param today the current day * @param person the person to process @@ -158,6 +160,13 @@ public boolean processNewDay(final Campaign campaign, final LocalDate today, } if (randomlyDies(age, person.getGender())) { + // We double-report here, to make sure the user definitely notices that a random death has occurred. + // Prior to this change, it was exceptionally easy to miss these events. + String color = MekHQ.getMHQOptions().getFontColorNegativeHexColor(); + String formatOpener = ReportingUtilities.spanOpeningWithCustomColor(color); + campaign.addReport(String.format("%s has %sdied%s.", + person.getHyperlinkedFullTitle(), formatOpener, CLOSING_SPAN_TAG)); + person.changeStatus(campaign, today, getCause(person, ageGroup, age)); return person.getStatus().isDead(); } else { From 8619d8ef09e1c8c7899ba6ab7ffaa9326c10c096 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Wed, 25 Sep 2024 10:25:09 -0500 Subject: [PATCH 40/41] Roll-back Accidental Push to Master --- .../personnel/death/AbstractDeath.java | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java b/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java index 1a5500bcac..29ee8487de 100644 --- a/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java +++ b/MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java @@ -18,6 +18,18 @@ */ package mekhq.campaign.personnel.death; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.Map; +import java.util.ResourceBundle; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + import megamek.Version; import megamek.common.annotations.Nullable; import megamek.common.enums.Gender; @@ -33,20 +45,6 @@ import mekhq.campaign.personnel.enums.RandomDeathMethod; import mekhq.campaign.personnel.enums.TenYearAgeRange; import mekhq.utilities.MHQXMLUtility; -import mekhq.utilities.ReportingUtilities; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.time.LocalDate; -import java.util.HashMap; -import java.util.Map; -import java.util.ResourceBundle; - -import static mekhq.utilities.ReportingUtilities.CLOSING_SPAN_TAG; public abstract class AbstractDeath { private static final MMLogger logger = MMLogger.create(AbstractDeath.class); @@ -160,13 +158,6 @@ public boolean processNewDay(final Campaign campaign, final LocalDate today, } if (randomlyDies(age, person.getGender())) { - // We double-report here, to make sure the user definitely notices that a random death has occurred. - // Prior to this change, it was exceptionally easy to miss these events. - String color = MekHQ.getMHQOptions().getFontColorNegativeHexColor(); - String formatOpener = ReportingUtilities.spanOpeningWithCustomColor(color); - campaign.addReport(String.format("%s has %sdied%s.", - person.getHyperlinkedFullTitle(), formatOpener, CLOSING_SPAN_TAG)); - person.changeStatus(campaign, today, getCause(person, ageGroup, age)); return person.getStatus().isDead(); } else { From b42aca49eba95e86c052c86ba6bdaaac64f9c0f3 Mon Sep 17 00:00:00 2001 From: IllianiCBT Date: Wed, 25 Sep 2024 17:30:21 -0500 Subject: [PATCH 41/41] Remove redundant imports in CampaignGUI.java Removed unused imports for PercentageRandomDivorce and PercentageRandomMarriage. This cleanup improves code readability and reduces unnecessary dependencies in the CampaignGUI class. --- MekHQ/src/mekhq/gui/CampaignGUI.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/MekHQ/src/mekhq/gui/CampaignGUI.java b/MekHQ/src/mekhq/gui/CampaignGUI.java index ba5b4d37b5..b7264912a9 100644 --- a/MekHQ/src/mekhq/gui/CampaignGUI.java +++ b/MekHQ/src/mekhq/gui/CampaignGUI.java @@ -54,9 +54,6 @@ import mekhq.campaign.personnel.death.AgeRangeRandomDeath; import mekhq.campaign.personnel.death.ExponentialRandomDeath; import mekhq.campaign.personnel.death.PercentageRandomDeath; -import mekhq.campaign.personnel.divorce.PercentageRandomDivorce; -import mekhq.campaign.personnel.enums.*; -import mekhq.campaign.personnel.marriage.PercentageRandomMarriage; import mekhq.campaign.personnel.divorce.RandomDivorce; import mekhq.campaign.personnel.enums.*; import mekhq.campaign.personnel.marriage.RandomMarriage;