-
Notifications
You must be signed in to change notification settings - Fork 399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add fuel to scrambling #3292
Add fuel to scrambling #3292
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3292 +/- ##
===========================================
- Coverage 21.91% 21.9% -0.02%
- Complexity 5872 5875 +3
===========================================
Files 837 837
Lines 72620 72696 +76
Branches 11852 11865 +13
===========================================
+ Hits 15916 15921 +5
- Misses 54598 54671 +73
+ Partials 2106 2104 -2
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks generally okay. Some of the code is a bit verbose, a refactoring pass could potentially help.
I am a bit concerned that the updates are all in-line for the most part without unit test. Given the existing code it's not too unreasonable the decisions made; I suspect we will often be able to say that as a reason for not unit testing.
I've took a few passes at this now; again looks pretty good overall. Just need to do some additional play testing and I would give this an okay. Anyone else is welcome to approve in the meantime.
final ResourceCollection cost = new ResourceCollection(data); | ||
cost.add(getMovementFuelCostCharge(Collections.singleton(unit), toRoute, player, data)); | ||
cost.add(getFuelCostsAndUnitsChargedFlatFuelCost( | ||
Collections.singleton(unit), returnRoute, player, data, true).getFirst()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noting the APIs, it looks like we could improve it a bit and have more work be done by the 'callee' methods, noting:
getFuelCostsAndUnitsChargedFlatFuelCost(Collections.singleton(unit), returnRoute, player, data, true).getFirst()
In this example we could have the first arg take a unit
directly, avoid the true
parameter by creating a method overload, and could avoid the getFirst
by having the method overload return that directly for us.
That would give something like:
I think there is also a method like computeIfAbsent
that could replace the if/else if structure for the map update. Going that route, if the body of the for loop were extracted to a helper method I think you could break this up into 2 or 3 pretty clean private methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually originally created a method that I think was:
getFuelCostsIgnoringFlatFuel(Unit, Route, PlayerID, GameData)
I ended up not seeing much value in slightly cleaner parameters at the cost of adding misdirection given that the call is to a private method pretty much right below this one. If the call was to a public method then I'd completely agree. I'm open to adding an overloaded method back in if there is a strong consensus/opinion that it improves readability/maintainability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will leave it up to you.
I like the cleaner and reduced parameters as it can make the method a bit more self-descriptive. If you can understand a method by it's name and args, then a person does not need to start hopping down the indirection tree. On the flip side, the boolean parameter being non-indirected requires reverse engineering of its usage to know what it really does.
Second comment/note I'll make, I tend to favor cleaner client code over server ("callee") code. If the client is not clean, then I'll iterate until it is. Then I drop down to the "callee" code and clean that up and it's dependent API's until that is also clean. This way down the whole stack there is no code you can't just read and understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Third and final comment here:
Normally unit tests would be the driving factor in this decision. The biggest benefit of unit testing is for decoupling design, not for catching bugs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to leave as is for now since I'm not really strongly convinced one way is much better than the other. I agree with most of you approach and tend to do something fairly similar. And I think the public API calls of Route involving fuel are pretty decent. Unless you have any more specific questions/asks then I'd like to move forward with it and we can always revisit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finished reviewing 100%
Found 3 nitpicky comments, they're low level. If we disagree in theory it would be an interesting conversation, but otherwise not a blocker - looks good otherwise, approving 🥂
@@ -1268,6 +1309,16 @@ public Component getListCellRendererComponent(final JList<? extends Unit> list, | |||
return selection; | |||
} | |||
|
|||
private JOptionPane getOptionPane(final JComponent parent) { | |||
JOptionPane pane = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A ternary IMO would clean this up quite a bit:
return !(parent instanceof JOptionPane)
? getOptionPane((JComponent) parent.getParent())
: (JOptionPane) parent;
If going with the old pattern, not setting the variable to null
and then marking it final
to ensure (compiler-enforced) that ti would get set in the if/else block is a good practice IMO. It's a signal to reader that the variable would be set, eg: final JOptionPane pane;
.
@@ -302,6 +302,10 @@ private void addToCollection(final Collection<Unit> addTo, final ChooserEntry en | |||
}); | |||
} | |||
|
|||
public void addChangeListener(final ScrollableTextFieldListener listener) { | |||
entries.stream().forEach(entry -> entry.addChangeListener(listener)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List
has a convenience forEach
method attached to it. FYI can simplify a little bit with it:
entries.forEach(entry -> entry.addChangeListener(listener));
@@ -450,6 +454,10 @@ boolean hasMultipleHitPoints() { | |||
return hasMultipleHits; | |||
} | |||
|
|||
void addChangeListener(final ScrollableTextFieldListener listener) { | |||
hitTexts.stream().forEach(field -> field.addChangeListener(listener)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto on simplification to remove stream()
and call forEach
directly on the list.
@DanVanAtta Yep, good catch on those 3. Updated. Not sure that even I could come up with a reasonable argument against those :) |
Merging based on all feedback being addressed. |
I think this change introduced this error when scrambling on the WW2 Pacific Map: java.lang.ClassCastException: java.lang.String cannot be cast to javax.swing.JButton |
@asvitkine Is this a older save game or a lobby game? Do you have a save game that reproduces this? |
This is caused by JOptionPane.UNINITIALIZED_VALUE being returned when a choice hasn't been made yet, which is a String. I'll send a PR to fix. |
Address point 6 on https://forums.triplea-game.org/topic/558/fuel-enhancements
Functional Changes
Testing
Manually edited Global 40 2nd to add this to fighters:
And this property:
Result:
More examples: https://forums.triplea-game.org/topic/558/fuel-enhancements/227