Skip to content

Commit

Permalink
Refactored strategic formation calculation.
Browse files Browse the repository at this point in the history
Revised the `recalculateStrategicFormations` method to improve clarity and efficiency by adding separate sub-force calculations. Updated campaign processing to ensure strategic formation status is recalculated consistently. Integrated logging for better traceability of strategic formation eligibility and status updates.
  • Loading branch information
IllianiCBT committed Dec 1, 2024
1 parent 2b8958b commit 675526d
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 5 deletions.
8 changes: 8 additions & 0 deletions MekHQ/src/mekhq/campaign/Campaign.java
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,13 @@ public Hashtable<Integer, StrategicFormation> getStrategicFormations() {
for (StrategicFormation strategicFormation : strategicFormations.values()) {
if (!strategicFormation.isEligible(this)) {
formationsToSanitize.add(strategicFormation.getForceId());
try {
Force force = getForce(strategicFormation.getForceId());
force.setStrategicFormation(false);
} catch (Exception ex) {
// We're not too worried if we can't find the associated Force,
// as this just means it has been deleted at some point and not removed correctly.
}
}
}

Expand Down Expand Up @@ -4333,6 +4340,7 @@ public void processNewDayUnits() {
private void processNewDayForces() {
// update formation levels
Force.populateFormationLevelsFromOrigin(this);
recalculateStrategicFormations(this);

// Update the force icons based on the end-of-day unit status if desired
if (MekHQ.getMHQOptions().getNewDayForceIconOperationalStatus()) {
Expand Down
4 changes: 1 addition & 3 deletions MekHQ/src/mekhq/campaign/force/Force.java
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,7 @@ public Vector<UUID> getAllUnits(boolean combatForcesOnly) {
}

for (Force force : subForces) {
if (force.getOverrideStrategicFormation() != STRATEGIC_FORMATION_OVERRIDE_FALSE) {
allUnits.addAll(force.getAllUnits(combatForcesOnly));
}
allUnits.addAll(force.getAllUnits(combatForcesOnly));
}

return allUnits;
Expand Down
40 changes: 38 additions & 2 deletions MekHQ/src/mekhq/campaign/force/StrategicFormation.java
Original file line number Diff line number Diff line change
Expand Up @@ -622,16 +622,52 @@ public static double calculateTotalWeight(Campaign campaign, int forceId) {
*/
public static void recalculateStrategicFormations(Campaign campaign) {
campaign.setStrategicFormations(new Hashtable<>());
for (Force force : campaign.getAllForces()) {
force.setStrategicFormation(false);
}

Force originNode = campaign.getForce(0);
for (Force force : originNode.getAllSubForces()) {

StrategicFormation strategicFormation = new StrategicFormation(0, campaign);
boolean isEligible = strategicFormation.isEligible(campaign);

if (isEligible) {
originNode.setStrategicFormation(true);
campaign.importStrategicFormation(strategicFormation);
}

MekHQ.triggerEvent(new OrganizationChangedEvent(originNode));

recalculateSubForceStrategicStatus(campaign, originNode);
}

/**
* This method is used to update the strategic formations for the campaign working downwards
* from a specified node, through all of its sub-forces.
* It creates a new {@link StrategicFormation} for each sub-force and checks its eligibility.
* Eligible formations are imported into the campaign, and the strategic formation status of
* the respective force is set to {@code true}.
* After every force is processed, an 'OrganizationChangedEvent' is triggered.
* This function runs recursively on each sub-force, effectively traversing the complete TO&E.
*
* @param campaign the current {@link Campaign}.
* @param workingNode the {@link Force} node from which the method starts working down through
* all its sub-forces.
*/
private static void recalculateSubForceStrategicStatus(Campaign campaign, Force workingNode) {
for (Force force : workingNode.getSubForces()) {
StrategicFormation strategicFormation = new StrategicFormation(force.getId(), campaign);

if (strategicFormation.isEligible(campaign)) {
boolean isEligible = strategicFormation.isEligible(campaign);

if (isEligible) {
campaign.importStrategicFormation(strategicFormation);
force.setStrategicFormation(true);
}

MekHQ.triggerEvent(new OrganizationChangedEvent(force));

recalculateSubForceStrategicStatus(campaign, force);
}
}
}
2 changes: 2 additions & 0 deletions MekHQ/src/mekhq/campaign/io/CampaignXmlParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
import java.util.*;
import java.util.Map.Entry;

import static mekhq.campaign.force.StrategicFormation.recalculateStrategicFormations;
import static org.apache.commons.lang3.ObjectUtils.firstNonNull;


Expand Down Expand Up @@ -854,6 +855,7 @@ private static void processForces(Campaign retVal, Node wn, Version version) {
}
}

recalculateStrategicFormations(retVal);
logger.info("Load of Force Organization complete!");
}

Expand Down
8 changes: 8 additions & 0 deletions MekHQ/src/mekhq/gui/adapter/TOEMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,14 @@ public void actionPerformed(ActionEvent action) {
singleForce.setStrategicFormation(!formationState);
singleForce.setOverrideStrategicFormation(formationState ? STRATEGIC_FORMATION_OVERRIDE_FALSE : STRATEGIC_FORMATION_OVERRIDE_TRUE);

for (Force childForce : singleForce.getAllSubForces()) {
childForce.setOverrideStrategicFormation(STRATEGIC_FORMATION_OVERRIDE_NONE);
}

for (Force parentForce : singleForce.getAllParents()) {
parentForce.setOverrideStrategicFormation(STRATEGIC_FORMATION_OVERRIDE_NONE);
}

recalculateStrategicFormations(gui.getCampaign());
} else if (command.contains(REMOVE_STRATEGIC_FORCE_OVERRIDE)) {
if (singleForce == null) {
Expand Down
3 changes: 3 additions & 0 deletions MekHQ/src/mekhq/gui/panes/CampaignOptionsPane.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
import java.util.stream.IntStream;

import static megamek.client.ui.WrapLayout.wordWrap;
import static mekhq.campaign.force.StrategicFormation.recalculateStrategicFormations;

/**
* @author Justin 'Windchild' Bowen
Expand Down Expand Up @@ -9570,6 +9571,8 @@ public void updateOptions() {

campaign.setCampaignOptions(options);

recalculateStrategicFormations(campaign);

MekHQ.triggerEvent(new OptionsChangedEvent(campaign, options));
} catch (Exception ex) {
logger.error(ex, "Campaign Options update failure, please check the logs for the exception reason.",
Expand Down

0 comments on commit 675526d

Please sign in to comment.