diff --git a/MekHQ/src/mekhq/campaign/CampaignSummary.java b/MekHQ/src/mekhq/campaign/CampaignSummary.java index 93face382c..6093fb8ee5 100644 --- a/MekHQ/src/mekhq/campaign/CampaignSummary.java +++ b/MekHQ/src/mekhq/campaign/CampaignSummary.java @@ -32,6 +32,8 @@ import mekhq.campaign.unit.Unit; import org.apache.commons.lang3.StringUtils; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -274,31 +276,44 @@ public String getMissionSuccessReport() { } /** - * A report that gives capacity and existing tonnage of all cargo + * Generates an HTML report about the current and maximum cargo capacity. + * The current cargo capacity (cargoTons) and maximum cargo capacity (cargoCapacity) are + * rounded to 1 decimal place. The comparison between the current and maximum cargo capacity + * determines the font's color in the report. + * - If the current cargo exceeds the maximum capacity, the color is set to MHQ's defined negative color. + * - If the current cargo equals the maximum capacity, the color is set to MHQ's defined warning color. + * - In other cases, the regular color is used. * - * @return a String of the report + * @return A {@link StringBuilder} object containing the HTML formatted report of cargo usage + * against capacity. */ public StringBuilder getCargoCapacityReport() { - int cargoTonsRounded = (int) Math.round(cargoTons); - int cargoCapacityRounded = (int) Math.round(cargoCapacity); + BigDecimal roundedCargo = new BigDecimal(Double.toString(cargoTons)); + roundedCargo = roundedCargo.setScale(1, RoundingMode.HALF_UP); + + BigDecimal roundedCapacity = new BigDecimal(Double.toString(cargoCapacity)); + roundedCapacity = roundedCapacity.setScale(1, RoundingMode.HALF_UP); + + int comparison = roundedCargo.compareTo(roundedCapacity); + StringBuilder report = new StringBuilder(""); - if (cargoTonsRounded > cargoCapacityRounded) { + if (comparison > 0) { report.append(""); - } else if (cargoTonsRounded == cargoCapacityRounded) { + } else if (comparison == 0) { report.append(""); } - report.append(cargoTonsRounded) + report.append(roundedCargo) .append(" tons (") - .append(cargoCapacityRounded) + .append(roundedCapacity) .append(" tons capacity)"); - if (!report.toString().equals(cargoTonsRounded + " tons (" + cargoCapacityRounded + " tons capacity)")) { + if (!report.toString().equals(roundedCargo + " tons (" + roundedCapacity + " tons capacity)")) { report.append(""); } else { report.append(""); diff --git a/MekHQ/src/mekhq/campaign/unit/Unit.java b/MekHQ/src/mekhq/campaign/unit/Unit.java index 2eb4e33569..97cb430c3c 100644 --- a/MekHQ/src/mekhq/campaign/unit/Unit.java +++ b/MekHQ/src/mekhq/campaign/unit/Unit.java @@ -75,6 +75,8 @@ import java.util.*; import java.util.Map.Entry; import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static mekhq.campaign.parts.enums.PartQuality.*; @@ -1282,19 +1284,48 @@ public Money getSellValue() { return partsValue; } + /** + * Calculates and returns the total cargo capacity of a fully crewed entity. + * If the entity is not fully crewed, the cargo capacity will be returned as 0. + * The capacity is calculated based on the sum capacity of CargoBay and + * StandardSeatCargoBay type Bays in the entity, and from non-damaged + * EquipmentParts (with the 'part name' following the pattern "Cargo (X ton)" or + * "Cargo (X tons)"). Any erroneous cases are logged. + * + * @return The total cargo capacity of the fully crewed entity, + * or 0 if the entity is not fully crewed. + * @throws NumberFormatException If the equipment part named "Cargo (X ton)" or + * "Cargo (X tons)" does not contain a valid number for X. + */ public double getCargoCapacity() { + if (!isFullyCrewed()) { + return 0; + } + double capacity = 0; for (Bay bay : entity.getTransportBays()) { - if (bay instanceof CargoBay) { - capacity += bay.getCapacity(); - } - if (bay instanceof PillionSeatCargoBay) { + if (bay instanceof CargoBay || bay instanceof StandardSeatCargoBay) { capacity += bay.getCapacity(); } - if (bay instanceof StandardSeatCargoBay) { - capacity += bay.getCapacity(); + } + + Pattern cargoPattern = Pattern.compile("Cargo \\((.*) ton(s)?\\)"); + + for (Part part : getParts()) { + if (part instanceof EquipmentPart && !(part.needsFixing() || part.isMountedOnDestroyedLocation())) { + Matcher matcher = cargoPattern.matcher(part.getName()); + + if (matcher.find()) { + try { + double partCapacity = Double.parseDouble(matcher.group(1)); + capacity += partCapacity; + } catch (NumberFormatException e) { + logger.error(String.format("Failed to parse %s as double", matcher.group(1))); + } + } } } + return capacity; }