Skip to content

#2363 Calculate player's recovery#2450

Open
wsbrenk wants to merge 24 commits into
ho-dev:masterfrom
wsbrenk:#2363
Open

#2363 Calculate player's recovery#2450
wsbrenk wants to merge 24 commits into
ho-dev:masterfrom
wsbrenk:#2363

Conversation

@wsbrenk
Copy link
Copy Markdown
Collaborator

@wsbrenk wsbrenk commented May 31, 2026

  1. changes proposed in this pull request:

  2. src/main/resources/release_notes.md ...

  • has been updated
  • does not require update

@wsbrenk wsbrenk requested a review from sgcr May 31, 2026 14:52
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Player.java
Comment thread src/main/java/core/model/XtraData.java Outdated
var ret = new ArrayList<HODateTime>();
for (HODateTime dailyUpdate : getDailyUpdates()) {
while (dailyUpdate.isAfter(from)) {
dailyUpdate = dailyUpdate.minus(7, ChronoUnit.DAYS);
Copy link
Copy Markdown
Collaborator

@sgcr sgcr Jun 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a constant for the 7 instead of using a "magic number".
And and use it in every place where this is meant.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: what is magic in writing Minus(7 days) ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I commented on the literal value 7 because it is a so-called “magic number”.

A magic number is a numeric value that appears directly in the source code without explaining its meaning. Even if the value itself is obvious mathematically, the intention behind it may not be immediately clear from the surrounding code.

For example, 7 could mean “days per week”, but it could also represent some business-specific limit, an offset, a retry count, or something else. By extracting it into a named constant, the code becomes more self-explanatory:

private static final int DAYS_PER_WEEK = 7;

Using a constant improves readability, makes the intention explicit, and avoids repeating the same unexplained value in multiple places. It also makes future changes easier, because the value only has to be changed in one place if the business rule ever changes.

So the point is not that the number 7 is hard to understand, but that the code should communicate why this value is used in this specific context.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reasons i don't understand the ChronoUnit.Weeks is not supported. Would you program .minus(ONE weeks) and define

private static final int ONE = 1;

I don't think so....

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason is, that Instant is a point in time as defined seconds after or before 1970-01-01T00:00:00Z.
ChronoUnit means the calendar system and that system has summer and winter time depending on the timezone you are living in.

It is not clear by definition when you say "7 days after an Instant" if you meant 604.800 seconds after the Instant.
Or, if the Instant is for the 2026-03-29T00:00:00 (Germany) then you have the UTC+1 (winter time) as the start point.
604.800 after that Instant is very clear,
but 7 days are that Instant could mean 2026-04-05T00:00:00 (summer time UTC+2) or maybe 2026-04-05T01:00:00 (summer time UTC+2).

Anyway, I found it also very interesting that the API of Java here is very "restricted". :-)

I think for your calculations calendar days are meant, because Hattrick is calendar based for all match days and so on.

HODateTime uses internal an Instant and this might have been a ZonedDateTime with a specific ZoneId.

But I think that is a major refactoring...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you program .minus(ONE weeks) and define

private static final int ONE = 1;

I don't think so....

For a 1 I would write 1 for sure.

But sometimes it may be important to read it explicitly and then I would use:

NumberUtils.INTEGER_ONE or NumberUtils.LONG_ONE from package org.apache.commons.lang3.math.
BigDecimal.ONE also exists.

We have that constants available in our project.

/**
* Health calculation based on Schum formula (<a href="https://www82.hattrick.org/Forum/Read.aspx?t=17404127&n=6&v=0&mr=0">...</a>)
*/
public class Injury {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about providing a test for that class?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea - will be done soon...

Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Injury.java Outdated
Comment thread src/main/java/core/model/player/Player.java
Comment thread src/main/java/core/model/XtraData.java Outdated
Comment thread src/main/java/core/model/XtraData.java Outdated
Copy link
Copy Markdown
Collaborator

@sgcr sgcr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please have a look at my comments.

@wsbrenk
Copy link
Copy Markdown
Collaborator Author

wsbrenk commented Jun 2, 2026

Thanks - Almost all comments have been incorporated

return whenSlightlyInjured;
}

public boolean getIsInvalid() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isInvalid

* Date is null if player is healthy
*/
private HODateTime whenHealthy;
/**
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide a blank line.

return getInjury().getTypeOfEstimate();
}

public Boolean isInvalid() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boolean

private static double calcMedicianFactor(int doctorLevel) {
double x1Factor = 0.2124;
double x0Factor = 1;
return (x1Factor * (double) doctorLevel + x0Factor) / (x0Factor + 5 * x1Factor);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(double) cast not necessary

private static double calcMedicianFactor(int doctorLevel) {
double x1Factor = 0.2124;
double x0Factor = 1;
return (x1Factor * (double) doctorLevel + x0Factor) / (x0Factor + 5 * x1Factor);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 should be a constant instead of magic number.

/**
* Health calculation based on Schum formula (<a href="https://www82.hattrick.org/Forum/Read.aspx?t=17404127&n=6&v=0&mr=0">...</a>)
*/
public class Injury {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class should be package private if the sole constructor is also package private.

*/
private boolean isInvalid = false;

public enum TypeOfEstimate {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When Injury is only the calculation and all values are delegated to Getters in Player then this enum should be a general public enum outside that implementation class. Maybe InjuryEstimationType

public enum TypeOfEstimate {
REALISTIC_ESTIMATE,
OPTIMISTIC_ESTIMATE,
PESSIMISTIC_ESTIMATE,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about "no injury"?

PESSIMISTIC_ESTIMATE,
}

private TypeOfEstimate typeOfEstimate = TypeOfEstimate.REALISTIC_ESTIMATE;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why that default?

return regainerFactor * calcAgeFactor(player.getAgeAtDate(dateTime).toDouble()) * calcMedicianFactor(doctorLevel);
}

private void calculateRecovery(Player player) {
Copy link
Copy Markdown
Collaborator

@sgcr sgcr Jun 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method is very long: Could it be separated in parts of different sub functions?

/**
* True if the player is an invalid (no recovery possible)
*/
private boolean isInvalid = false;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: chronicInvalid as a name because invalid is very general and could be a state of the class instance itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants