Skip to content

Commit

Permalink
Merge pull request #4848 from IllianiCBT/unit_crewStatus
Browse files Browse the repository at this point in the history
Added Tooltip for Crew Requirements in Hangar Tab Display
  • Loading branch information
HammerGS authored Sep 25, 2024
2 parents 0abb733 + 233f975 commit d2e230e
Show file tree
Hide file tree
Showing 2 changed files with 218 additions and 9 deletions.
90 changes: 81 additions & 9 deletions MekHQ/src/mekhq/gui/model/UnitTableModel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* 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.
*
Expand Down Expand Up @@ -97,7 +97,7 @@ public String getColumnName(int column) {
case COL_FORCE -> "Force";
case COL_CREW -> "Crew";
case COL_TECH_CRW -> "Tech Crew";
case COL_MAINTAIN -> "Maintenance Costs";
case COL_MAINTAIN -> "Maintenance";
case COL_BV -> "BV";
case COL_REPAIR -> "# Repairs";
case COL_PARTS -> "# Parts";
Expand All @@ -112,7 +112,8 @@ public int getColumnWidth(final int columnId) {
return switch (columnId) {
case COL_NAME, COL_TECH, COL_PILOT, COL_FORCE, COL_TECH_CRW -> 150;
case COL_TYPE, COL_WCLASS, COL_SITE -> 50;
case COL_COST, COL_STATUS, COL_RSTATUS -> 40;
case COL_COST, COL_STATUS, COL_RSTATUS, COL_CREW -> 40;
case COL_PARTS -> 10;
default -> 20;
};
}
Expand All @@ -125,16 +126,87 @@ public int getAlignment(int col) {
};
}

public @Nullable String getTooltip(int row, int col) {
Unit u = getUnit(row);
return switch (col) {
case COL_STATUS -> u.isRefitting() ? u.getRefit().getDesc() : null;
case COL_CREW_STATE -> u.getCrewState().getToolTipText();
case COL_QUIRKS -> u.getQuirksList();
/**
* Returns the tooltip for the specified row and column.
*
* @param rowIndex the index of the row
* @param columnIndex the index of the column
* @return the tooltip for the specified row and column, or {@code null} if no tooltip is available
*/
public @Nullable String getTooltip(int rowIndex, int columnIndex) {
Unit unit = getUnit(rowIndex);

if (unit == null) {
return null;
}

return switch (columnIndex) {
case COL_STATUS -> unit.isRefitting() ? unit.getRefit().getDesc() : null;
case COL_CREW_STATE -> unit.getCrewState().getToolTipText();
case COL_CREW -> getCrewTooltip(unit);
case COL_QUIRKS -> unit.getQuirksList();
default -> null;
};
}

/**
* Returns the tooltip for the crew status of a given unit.
*
* @param unit the unit for which to get the crew tooltip
* @return the crew tooltip as an HTML string
*/
static String getCrewTooltip(Unit unit) {
int gunnersNeeded = unit.getTotalGunnerNeeds();
int gunnersAssigned = unit.getGunners().size();

int driversNeeded = unit.getTotalDriverNeeds();
int driversAssigned = unit.getDrivers().size();

Entity entity = unit.getEntity();
int navigatorsNeeded = entity instanceof Jumpship && !(entity instanceof SpaceStation) ? 1 : 0;
int navigatorsAssigned = unit.getNavigator() == null ? 0 : 1;

int crewNeeded = unit.getTotalCrewNeeds();
int crewAssigned = unit.getCrew().size() - (gunnersAssigned + driversAssigned + navigatorsAssigned);

StringBuilder report = new StringBuilder("<html>");

if (driversNeeded > 0) {
appendReport(report, "Drivers", driversAssigned, driversNeeded);
}

if (gunnersNeeded > 0) {
report.append("<br>");
appendReport(report, "Gunners", gunnersAssigned, gunnersNeeded);
}

if (crewNeeded > 0) {
report.append("<br>");
appendReport(report, "Crew", crewAssigned, crewNeeded);
}

if (navigatorsNeeded > 0) {
report.append("<br>");
appendReport(report, "Navigator", navigatorsAssigned, navigatorsNeeded);
}

report.append("</html>");

return report.toString();
}

/**
* Appends a crew report line to the provided StringBuilder.
*
* @param report the {@link StringBuilder} to append to
* @param title the title of the crew role (e.g., "Driver", "Gunner")
* @param assigned the number of crew members assigned to the role
* @param needed the number of crew members needed for the role
*/
private static void appendReport(StringBuilder report, String title, int assigned, int needed) {
report.append(String.format("<b>%s: </b>%d/%d", title, assigned, needed));
}

@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
Expand Down
137 changes: 137 additions & 0 deletions MekHQ/unittests/mekhq/gui/model/UnitTableModelTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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.model;

import megamek.common.Entity;
import megamek.common.Jumpship;
import megamek.common.SpaceStation;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.unit.Unit;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* This class contains test cases for the {@link UnitTableModel} class.
* It tests the different combinations of crew requirements and verifies the behavior of the
* {@code getCrewTooltip()} method.
*/
@ExtendWith(value = MockitoExtension.class)
public class UnitTableModelTest {
@Mock
private Unit unit;
@Mock
private Person crewMember;

/**
* Sets the crew of a unit with the given parameters.
*
* @param driverCount The number of drivers in the unit.
* @param totalDriverNeeds The total number of drivers needed for the unit.
* @param gunnerCount The number of gunners in the unit.
* @param totalGunnerNeeds The total number of gunners needed for the unit.
* @param crewCount The number of crew members (excluding drivers and gunners) in the unit.
* @param totalCrewNeeds The total number of crew members needed for the unit.
* @param hasNavigator Indicates whether the unit has a navigator.
* @param entity The entity associated with the unit.
* @param expected The expected result for the crew tooltip.
*/
private void setCrew(int driverCount, int totalDriverNeeds,
int gunnerCount, int totalGunnerNeeds,
int crewCount, int totalCrewNeeds,
boolean hasNavigator, Entity entity,
String expected) {
List<Person> drivers = Collections.nCopies(driverCount, crewMember);
List<Person> gunners = Collections.nCopies(gunnerCount, crewMember);
List<Person> crew = Collections.nCopies(crewCount + drivers.size() + gunners.size()
+ (hasNavigator ? 1 : 0), crewMember);

when(unit.getDrivers()).thenReturn(drivers);
when(unit.getTotalDriverNeeds()).thenReturn(totalDriverNeeds);

when(unit.getGunners()).thenReturn(gunners);
when(unit.getTotalGunnerNeeds()).thenReturn(totalGunnerNeeds);

when(unit.getCrew()).thenReturn(crew);
when(unit.getTotalCrewNeeds()).thenReturn(totalCrewNeeds);

when(unit.getEntity()).thenReturn(entity);
Person navigator = hasNavigator ? mock(Person.class) : null;
when(unit.getNavigator()).thenReturn(navigator);

String result = UnitTableModel.getCrewTooltip(unit);
assertEquals(expected, result);
}

// In the following tests the getCrewTooltip() method is called, and its responses are checked
// against expected behavior

@Test
public void noCrewNeeded() {
setCrew(0, 0,
0, 0,
0, 0,
true, mock(SpaceStation.class),
"<html></html>");
}

@Test
public void fullyCrewed() {
setCrew(1, 1,
2, 2,
3, 3,
true, mock(Jumpship.class),
"<html><b>Drivers: </b>1/1<br><b>Gunners: </b>2/2<br><b>Crew: </b>3/3<br><b>Navigator: </b>1/1</html>");
}

@Test
public void partiallyCrewed() {
setCrew(0, 1,
1, 2,
2, 3,
false, mock(Jumpship.class),
"<html><b>Drivers: </b>0/1<br><b>Gunners: </b>1/2<br><b>Crew: </b>2/3<br><b>Navigator: </b>0/1</html>");
}

@Test
public void excessCrew() {
setCrew(2, 1,
4, 2,
6, 5,
true, mock(SpaceStation.class),
"<html><b>Drivers: </b>2/1<br><b>Gunners: </b>4/2<br><b>Crew: </b>6/5</html>");
}

@Test
public void noAssignedCrew() {
setCrew(0, 1,
0, 1,
0, 1,
false, mock(Jumpship.class),
"<html><b>Drivers: </b>0/1<br><b>Gunners: </b>0/1<br><b>Crew: </b>0/1<br><b>Navigator: </b>0/1</html>");
}
}

0 comments on commit d2e230e

Please sign in to comment.