Skip to content

Commit

Permalink
Merge pull request #4888 from IllianiCBT/maintenance_partsReport
Browse files Browse the repository at this point in the history
Added 'Part Quality Report' Dialog
  • Loading branch information
HammerGS authored Sep 25, 2024
2 parents ddbe027 + 5173607 commit 1341ebe
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 41 deletions.
4 changes: 4 additions & 0 deletions MekHQ/resources/mekhq/resources/GUI.properties
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@ HangarReportDialog.title=Hangar Report
MaintenanceReportDialog.title=Maintenance Report
MaintenanceReportDialog.Unit.title=Maintenance Report for %s

### PartsReportDialog Class
PartQualityReportDialog.title=Part Quality Report
PartQualityReportDialog.Unit.title=Parts Quality Report for %s

### MonthlyUnitCostReportDialog Class
MonthlyUnitCostReportDialog.title=Monthly Cost Report
MonthlyUnitCostReportDialog.Unit.title=Monthly Cost Report for %s
Expand Down
4 changes: 2 additions & 2 deletions MekHQ/src/mekhq/campaign/personnel/death/AbstractDeath.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public Map<Gender, Map<TenYearAgeRange, WeightedDoubleMap<PersonnelStatus>>> 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
Expand Down Expand Up @@ -144,7 +144,7 @@ public Map<Gender, Map<TenYearAgeRange, WeightedDoubleMap<PersonnelStatus>>> 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
Expand Down
64 changes: 25 additions & 39 deletions MekHQ/src/mekhq/gui/adapter/UnitTableMouseAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,6 @@
*/
package mekhq.gui.adapter;

import static megamek.client.ui.WrapLayout.wordWrap;

import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.UUID;
import java.util.Vector;
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.ui.dialogs.BVDisplayDialog;
import megamek.client.ui.dialogs.CamoChooserDialog;
import megamek.client.ui.swing.UnitEditorDialog;
Expand All @@ -65,33 +41,33 @@
import mekhq.campaign.parts.equipment.AmmoBin;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.unit.Unit;
import mekhq.campaign.unit.actions.ActivateUnitAction;
import mekhq.campaign.unit.actions.CancelMothballUnitAction;
import mekhq.campaign.unit.actions.HirePersonnelUnitAction;
import mekhq.campaign.unit.actions.IUnitAction;
import mekhq.campaign.unit.actions.MothballUnitAction;
import mekhq.campaign.unit.actions.RestoreUnitAction;
import mekhq.campaign.unit.actions.StripUnitAction;
import mekhq.campaign.unit.actions.SwapAmmoTypeAction;
import mekhq.campaign.unit.actions.*;
import mekhq.gui.CampaignGUI;
import mekhq.gui.HangarTab;
import mekhq.gui.MekLabTab;
import mekhq.gui.dialog.BombsDialog;
import mekhq.gui.dialog.ChooseRefitDialog;
import mekhq.gui.dialog.LargeCraftAmmoSwapDialog;
import mekhq.gui.dialog.MarkdownEditorDialog;
import mekhq.gui.dialog.MassMothballDialog;
import mekhq.gui.dialog.QuirksDialog;
import mekhq.gui.dialog.SmallSVAmmoSwapDialog;
import mekhq.gui.dialog.*;
import mekhq.gui.dialog.reportDialogs.MaintenanceReportDialog;
import mekhq.gui.dialog.reportDialogs.MonthlyUnitCostReportDialog;
import mekhq.gui.dialog.reportDialogs.PartQualityReportDialog;
import mekhq.gui.enums.MHQTabType;
import mekhq.gui.menus.AssignUnitToPersonMenu;
import mekhq.gui.menus.ExportUnitSpriteMenu;
import mekhq.gui.model.UnitTableModel;
import mekhq.gui.utilities.JMenuHelpers;
import mekhq.gui.utilities.StaticChecks;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.*;
import java.util.stream.Stream;

import static megamek.client.ui.WrapLayout.wordWrap;

public class UnitTableMouseAdapter extends JPopupMenuAdapter {
private static final MMLogger logger = MMLogger.create(UnitTableMouseAdapter.class);

Expand Down Expand Up @@ -129,6 +105,7 @@ public class UnitTableMouseAdapter extends JPopupMenuAdapter {
public static final String COMMAND_QUIRKS = "QUIRKS";
public static final String COMMAND_BOMBS = "BOMBS";
public static final String COMMAND_SUPPLY_COST = "SUPPLY_COST";
public static final String COMMAND_PARTS_REPORT = "PARTS_REPORT";
public static final String COMMAND_TAG_CUSTOM = "TAG_CUSTOM";
public static final String COMMAND_INDI_CAMO = "INDI_CAMO";
public static final String COMMAND_REMOVE_INDI_CAMO = "REMOVE_INDI_CAMO";
Expand Down Expand Up @@ -205,6 +182,8 @@ public void actionPerformed(ActionEvent action) {
new MaintenanceReportDialog(gui.getFrame(), selectedUnit).setVisible(true);
} else if (command.equals(COMMAND_SUPPLY_COST)) { // Single Unit only
new MonthlyUnitCostReportDialog(gui.getFrame(), selectedUnit).setVisible(true);
} else if (command.equals(COMMAND_PARTS_REPORT)) { // Single Unit only
new PartQualityReportDialog(gui.getFrame(), selectedUnit).setVisible(true);
} else if (command.equals(COMMAND_SET_QUALITY)) {
// TODO : Duplicated in PartsTableMouseAdapter#actionPerformed
int q = -1;
Expand Down Expand Up @@ -819,6 +798,13 @@ protected Optional<JPopupMenu> createPopupMenu() {
popup.add(menuItem);
}

if (oneSelected && gui.getCampaign().getCampaignOptions().isCheckMaintenance()) {
menuItem = new JMenuItem("Show Part Quality Report");
menuItem.setActionCommand(COMMAND_PARTS_REPORT);
menuItem.addActionListener(this);
popup.add(menuItem);
}

if (areAllConventionalInfantry) {
menuItem = new JMenuItem("Disband");
menuItem.setActionCommand(COMMAND_DISBAND);
Expand Down
167 changes: 167 additions & 0 deletions MekHQ/src/mekhq/gui/dialog/reportDialogs/PartQualityReportDialog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2024 - 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 <http://www.gnu.org/licenses/>.
*/
package mekhq.gui.dialog.reportDialogs;

import mekhq.MekHQ;
import mekhq.campaign.parts.Part;
import mekhq.campaign.unit.Unit;
import mekhq.utilities.ReportingUtilities;

import javax.swing.*;
import java.util.*;

import static mekhq.campaign.parts.Part.QUALITY_A;
import static mekhq.campaign.parts.Part.QUALITY_B;
import static mekhq.campaign.parts.Part.QUALITY_E;
import static mekhq.campaign.parts.Part.QUALITY_F;
import static mekhq.utilities.ReportingUtilities.CLOSING_SPAN_TAG;

/**
* Represents a dialog for generating a part quality report.
* Extends the {@link AbstractReportDialog} class.
*/
public class PartQualityReportDialog extends AbstractReportDialog {
//region Variable Declarations
private final Unit unit;
//endregion Variable Declarations

//region Constructors
/**
* Constructs a new instance of {@link PartQualityReportDialog}.
*
* @param frame the parent {@link JFrame}
* @param unit the unit for which the parts quality report is being generated
*/
public PartQualityReportDialog(final JFrame frame, final Unit unit) {
super(frame, "PartQualityReportDialog", "PartQualityReportDialog.title");
this.unit = unit;
setTitle(String.format(resources.getString("PartQualityReportDialog.Unit.title"),
unit.getName()));
initialize();
}
//endregion Constructors

//region Getters
/**
* @return the unit associated with this object
*/
public Unit getUnit() {
return unit;
}

@Override
protected JTextPane createTxtReport() {
final JTextPane txtReport = new JTextPane();
txtReport.setContentType("text/html");
txtReport.setText(getPartsReport(getUnit()));
txtReport.setName("txtReport");
txtReport.setEditable(false);
txtReport.setCaretPosition(0);
return txtReport;
}
//endregion Getters

/**
* Produces a Part Quality report for the given unit. The report includes each part's location,
* name, and quality.
*
* @param unit The unit to generate a report for.
* @return An HTML string displaying the status of each part in the unit.
*/
private String getPartsReport(Unit unit) {
// This map will hold part lists, keyed by the location on the unit.
Map<String, List<Part>> reportMap = new HashMap<>();

// Iterate over parts, assigning each to its location in the map.
for (Part part : unit.getParts()) {
String location = part.getLocationName() != null ? part.getLocationName() : unit.getName();
reportMap.computeIfAbsent(location, k -> new ArrayList<>()).add(part);
}

// Create a sorted list of locations, excluding the unit's name.
List<String> locations = new ArrayList<>();
for (String location : reportMap.keySet()) {
if (!location.equals(unit.getName())) {
locations.add(location);
}
}
Collections.sort(locations);

// Add the unit's name to the start of the sorted locations list.
locations.add(0, unit.getName());

// Begin the HTML report.
StringBuilder report = new StringBuilder("<html>");

// For each location, add reported details about that location's parts.
for (String location : locations) {
report.append("<b>");
if (location.equals(unit.getName())) {
String colorCode = getColorCode(unit.getQuality());

// Add the location and its colored quality rating to the report.
report.append("<span style=\"font-size: 18px;\">")
.append(location)
.append(" - ");
report.append("<span style=\"color: ")
.append(colorCode)
.append(";\">")
.append(unit.getQualityName())
.append("</span>");
report.append("</span>");
} else {
report.append("<span style=\"font-size: 12px;\">").append(location).append("</span>");
}
report.append("</b><br>");

// For each part in the current location, add it to the report.
for (Part part : reportMap.get(location)) {
report.append(part.getName()).append(" - ");

int qualityLevel = part.getQuality();
String colorCode = getColorCode(qualityLevel);

report.append(ReportingUtilities.spanOpeningWithCustomColor(colorCode))
.append(part.getQualityName()).append(CLOSING_SPAN_TAG).append("<br>");
}

// Add a line break between locations.
report.append("<br>");
}

// Finish the HTML report.
report.append("</html>");

return report.toString();
}

/**
* Returns the color code associated with the given quality level.
*
* @param qualityLevel The quality level for which to retrieve the color code.
* @return The color code associated with the quality level.
*/
private static String getColorCode(int qualityLevel) {
return switch (qualityLevel) {
case QUALITY_A, QUALITY_B -> MekHQ.getMHQOptions().getFontColorNegativeHexColor();
case QUALITY_E, QUALITY_F -> MekHQ.getMHQOptions().getFontColorPositiveHexColor();
default -> MekHQ.getMHQOptions().getFontColorWarningHexColor();
};
}
}

0 comments on commit 1341ebe

Please sign in to comment.