Skip to content

Commit

Permalink
#1886 improve training planning (#1970)
Browse files Browse the repository at this point in the history
* #1962 refactoring PlayerSkill class->enum

* #1962 refactoring PlayerSkill class->enum

* #1962 refactoring PlayerSkill: remove PlayerSkillColumn.getSkill

* #1962 refactoring PlayerSkill: remove HTSkillID

* #1962 refactoring PlayerSkill: remove redundant Skills.getSkillValue

* #1962 refactoring PlayerSkill.toString -> getLanguageString

* #1962 refactoring remove PastSkillChange.java

* hsqldb 2.7.2

* Refactor prepared statement caching logic.

This commit introducts a `StatementCache` that manages the cached
`PreparedStatement`s in a straightforward and consistent manner; the statements in this cache can
easily be cleared out, and the cache can also be disabled.  It also keeps tracks of statistics
about the prepared statements that can be useful for debugging and tracking
commonly used ones.

This also removes some of the ad-hoc attempts at achieving similar
caching (e.g. in `TrainingsTable`, `DBUpdater`, etc.).

Finally, it also deletes the `XMLExporter` class, which has now become obsolete,
per discussion: #1942

* #1886 (wip)

* #1886 merge

* #1886 PlayerDetailPanel loads correct skill training priority

* #1886 fix FuturePlayerTraining.cut (create unit test)

* #1886 fix FuturePlayerTraining.cut (create unit test)

* #1886 delete TrainingPlanPanel.java

* #1886 fix FuturePlayerTrainingTable.storeFuturePlayerTrainings

---------

Co-authored-by: Sébastien Le Callonnec <[email protected]>
  • Loading branch information
wsbrenk and tychobrailleur authored Dec 3, 2023
1 parent 0c1b3fb commit 73214a3
Show file tree
Hide file tree
Showing 19 changed files with 469 additions and 240 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repositories {
dependencies {
implementation 'com.install4j:install4j-runtime:10.0.6'
implementation 'com.github.scribejava:scribejava-core:8.3.3'
implementation 'org.hsqldb:hsqldb:2.7.1'
implementation 'org.hsqldb:hsqldb:2.7.2'
implementation 'com.google.code.gson:gson:2.10'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'com.squareup.okhttp3:okhttp-tls:4.10.0'
Expand Down
30 changes: 13 additions & 17 deletions src/main/java/core/db/DBManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
import core.gui.theme.TeamLogoInfo;
import core.model.*;
import core.model.Tournament.TournamentDetails;
import core.model.enums.DBDataSource;
import core.model.enums.MatchType;
import core.model.match.*;
import core.model.misc.Basics;
import core.model.misc.Economy;
import core.model.misc.Verein;
import core.model.player.Player;
import core.model.player.Skillup;
import core.training.FuturePlayerSkillTraining;
import core.util.HODateTime;
import module.matches.MatchLocation;
import module.nthrf.NtTeamDetails;
Expand All @@ -46,7 +46,6 @@
import org.jetbrains.annotations.Nullable;
import tool.arenasizer.Stadium;
import java.io.File;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
Expand Down Expand Up @@ -265,6 +264,7 @@ private void initAllTables() {
tables.put(MatchHighlightsTable.TABLENAME, new MatchHighlightsTable(connectionManager));
tables.put(TrainingsTable.TABLENAME, new TrainingsTable(connectionManager));
tables.put(FutureTrainingTable.TABLENAME, new FutureTrainingTable(connectionManager));
tables.put(FuturePlayerSkillTrainingTable.TABLENAME, new FuturePlayerSkillTrainingTable(connectionManager));
tables.put(UserConfigurationTable.TABLENAME,new UserConfigurationTable(connectionManager));
tables.put(SkillupTable.TABLENAME, new SkillupTable(connectionManager));
tables.put(StaffTable.TABLENAME, new StaffTable(connectionManager));
Expand Down Expand Up @@ -357,19 +357,6 @@ private boolean checkIfDBExists() {
return exists;
}


/**
* get the date of the last level increase of given player
*
* @param skill integer code for the skill
* @param spielerId player ID
* @return [0] = Time of change [1] = Boolean: false=no skill change found
*/
public Skillup getLastLevelUp(PlayerSkill skill, int spielerId) {
return ((SkillupTable) getTable(SkillupTable.TABLENAME))
.getLastLevelUp(skill, spielerId);
}

/**
* liefert das Datum des letzen LevelAufstiegs für den angeforderten Skill
* Vector filled with Skillup Objects
Expand Down Expand Up @@ -2178,11 +2165,12 @@ public List<FuturePlayerTraining> getFuturePlayerTrainings(int playerId) {
/**
* Store future player trainings.
*
* @param playerId Player id (used to delete old trainings)
* @param futurePlayerTrainings the future player trainings
*/
public void storeFuturePlayerTrainings(List<FuturePlayerTraining> futurePlayerTrainings) {
public void storeFuturePlayerTrainings(int playerId, List<FuturePlayerTraining> futurePlayerTrainings) {
((FuturePlayerTrainingTable) getTable(FuturePlayerTrainingTable.TABLENAME))
.storeFuturePlayerTrainings(futurePlayerTrainings);
.storeFuturePlayerTrainings(playerId, futurePlayerTrainings);

}

Expand Down Expand Up @@ -2412,4 +2400,12 @@ public void storeSquadInfo(SquadInfo squadInfo) {
public List<SquadInfo> loadSquadInfo(int teamId) {
return ((SquadInfoTable)getTable(SquadInfoTable.TABLENAME)).loadSquadInfo(teamId);
}

public List<FuturePlayerSkillTraining> loadFuturePlayerSkillTrainings(int playerId) {
return ((FuturePlayerSkillTrainingTable)getTable(FuturePlayerSkillTrainingTable.TABLENAME)).loadFuturePlayerSkillTraining(playerId);
}

public void storeFuturePlayerSkillTrainings(int playerId, List<FuturePlayerSkillTraining> futurePlayerSkillTrainings) {
((FuturePlayerSkillTrainingTable)getTable(FuturePlayerSkillTrainingTable.TABLENAME)).storeFuturePlayerSkillTraining(playerId, futurePlayerSkillTrainings);
}
}
4 changes: 4 additions & 0 deletions src/main/java/core/db/DBUpdater.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ void updateDB(int DBVersion) {
}

private void updateDBv800(int dbVersion) throws SQLException {
if (!tableExists(FuturePlayerSkillTrainingTable.TABLENAME)) {
dbManager.getTable(FuturePlayerSkillTrainingTable.TABLENAME).createTable();
}

var playerTable = dbManager.getTable(SpielerTable.TABLENAME);
playerTable.tryAddColumn("LineupDisabled", "BOOLEAN");
playerTable.tryAddColumn("ContractDate", "VARCHAR(100)");
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/core/db/FuturePlayerSkillTrainingTable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package core.db;


import core.constants.player.PlayerSkill;
import core.training.FuturePlayerSkillTraining;
import core.training.FuturePlayerTraining;

import java.sql.Types;
import java.util.List;

public class FuturePlayerSkillTrainingTable extends AbstractTable {

public final static String TABLENAME = "FUTUREPLAYERSKILLTRAINING";

/**
* constructor
*/
public FuturePlayerSkillTrainingTable(ConnectionManager adapter) {
super(TABLENAME, adapter);
}

@Override
protected void initColumns() {
columns = new ColumnDescriptor[]{
ColumnDescriptor.Builder.newInstance()
.setColumnName("playerId")
.setGetter((o) -> ((FuturePlayerSkillTraining) o).getPlayerId())
.setSetter((o, v) -> ((FuturePlayerSkillTraining) o).setPlayerId((int) v))
.setType(Types.INTEGER)
.isNullable(false)
.build(),
ColumnDescriptor.Builder.newInstance()
.setColumnName("skillId")
.setGetter((o) -> ((FuturePlayerSkillTraining) o).getSkillId().toInt())
.setSetter((o, v) -> ((FuturePlayerSkillTraining) o).setSkillId(PlayerSkill.fromInteger((int) v)))
.setType(Types.INTEGER)
.isNullable(false)
.build(),
ColumnDescriptor.Builder.newInstance()
.setColumnName("prio")
.setGetter((o) -> FuturePlayerSkillTraining.getPriorityAsInteger((FuturePlayerSkillTraining)o))
.setSetter((o, v) -> ((FuturePlayerSkillTraining) o).setPriority(FuturePlayerTraining.Priority.valueOf((Integer) v)))
.setType(Types.INTEGER)
.isNullable(true)
.build()
};
}

List<FuturePlayerSkillTraining> loadFuturePlayerSkillTraining(int playerId) {
return load(FuturePlayerSkillTraining.class, playerId);
}

public void storeFuturePlayerSkillTraining(int playerId, List<FuturePlayerSkillTraining> futurePlayerTrainings) {
executePreparedDelete(playerId);
for (var t : futurePlayerTrainings) {
store(t);
}
}
}
3 changes: 2 additions & 1 deletion src/main/java/core/db/FuturePlayerTrainingTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ List<FuturePlayerTraining> getFuturePlayerTrainingPlan(int playerId) {
return load(FuturePlayerTraining.class, playerId);
}

public void storeFuturePlayerTrainings(List<FuturePlayerTraining> futurePlayerTrainings) {
public void storeFuturePlayerTrainings(int playerId, List<FuturePlayerTraining> futurePlayerTrainings) {
executePreparedDelete(playerId);
for (var t : futurePlayerTrainings) {
store(t);
}
Expand Down
6 changes: 0 additions & 6 deletions src/main/java/core/db/SkillupTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,10 @@ private void storeSkillup(Skillup skillup) {
store(skillup);
}

private final String loadLastLevelUpSql = createSelectStatement("WHERE SPIELERID=? AND SKILL = ? ORDER BY Datum DESC LIMIT 1");
Skillup getLastLevelUp(PlayerSkill skillCode, int spielerId) {
return loadOne(Skillup.class, this.connectionManager.executePreparedQuery(loadLastLevelUpSql, spielerId, PlayerSkill.toInteger(skillCode)));
}

List<Skillup> getAllLevelUp(PlayerSkill skillCode, int spielerId) {
return load(Skillup.class, spielerId, PlayerSkill.toInteger(skillCode));
}


void importNewSkillup(HOModel homodel) {
List<Player> players = homodel.getCurrentPlayers();
for (Player nPlayer : players) {
Expand Down
85 changes: 61 additions & 24 deletions src/main/java/core/model/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ public void setContractDate(String contractDate) {
* future training priorities planed by the user
*/
private List<FuturePlayerTraining> futurePlayerTrainings;
private List<FuturePlayerSkillTraining> futurePlayerSkillTrainings;

private Integer motherClubId;
private String motherClubName;
Expand Down Expand Up @@ -938,21 +939,6 @@ public int getInternalMatches() {
return internationalMatches;
}

private final HashMap<PlayerSkill, Skillup> lastSkillups = new HashMap<>();

/**
* liefert das Datum des letzen LevelAufstiegs für den angeforderten Skill [0] = Time der
* Änderung [1] = Boolean: false=Keine Änderung gefunden
*/
public Skillup getLastLevelUp(PlayerSkill skill) {
if (lastSkillups.containsKey(skill)) {
return lastSkillups.get(skill);
}
var ret = DBManager.instance().getLastLevelUp(skill, spielerId);
lastSkillups.put(skill, ret);
return ret;
}

private final HashMap<PlayerSkill, List<Skillup>> allSkillUps = new HashMap<>();

/**
Expand All @@ -968,7 +954,6 @@ public List<Skillup> getAllLevelUp(PlayerSkill skill) {
}

public void resetSkillUpInformation() {
lastSkillups.clear();
allSkillUps.clear();
}

Expand Down Expand Up @@ -1828,13 +1813,20 @@ public List<FuturePlayerTraining> getFuturePlayerTrainings() {
* @param trainingDate the training week
* @return the training priority
*/
public FuturePlayerTraining.Priority getTrainingPriority(WeeklyTrainingType wt, HODateTime trainingDate) {
public FuturePlayerTraining.Priority getFuturePlayerTrainingPriority(WeeklyTrainingType wt, HODateTime trainingDate) {
for (var t : getFuturePlayerTrainings()) {
if (t.contains(trainingDate)) {
return t.getPriority();
}
}

// get training from skill settings
for (var futureSkillTraining : getFuturePlayerSkillTrainings()){
if (wt.isTraining(futureSkillTraining.getSkillId())){
return futureSkillTraining.getPriority();
}
}

// get Prio from best position
int position = HelperWrapper.instance().getPosition(this.getIdealPosition());

Expand Down Expand Up @@ -1867,18 +1859,19 @@ public FuturePlayerTraining.Priority getTrainingPriority(WeeklyTrainingType wt,
* @param to last week with new training priority, null means open end
*/
public void setFutureTraining(FuturePlayerTraining.Priority prio, HODateTime from, HODateTime to) {
var removeIntervals = new ArrayList<FuturePlayerTraining>();
var newFuturePlayerTrainings = new ArrayList<FuturePlayerTraining>();
for (var t : getFuturePlayerTrainings()) {
if (t.cut(from, to) ||
t.cut(HODateTime.HT_START, HOVerwaltung.instance().getModel().getBasics().getHattrickWeek())) {
removeIntervals.add(t);
var tmpList = t.cut(from, to);
for (var ft : tmpList){
// cut the past
newFuturePlayerTrainings.addAll(ft.cut(HODateTime.HT_START, HOVerwaltung.instance().getModel().getBasics().getHattrickWeek()));
}
}
futurePlayerTrainings.removeAll(removeIntervals);
if (prio != null) {
futurePlayerTrainings.add(new FuturePlayerTraining(this.getPlayerId(), prio, from, to));
newFuturePlayerTrainings.add(new FuturePlayerTraining(this.getPlayerId(), prio, from, to));
}
DBManager.instance().storeFuturePlayerTrainings(futurePlayerTrainings);
futurePlayerTrainings = newFuturePlayerTrainings;
DBManager.instance().storeFuturePlayerTrainings(getPlayerId(), futurePlayerTrainings);
}

public String getBestPositionInfo() {
Expand All @@ -1888,6 +1881,50 @@ public String getBestPositionInfo() {
+ ")";
}

public FuturePlayerTraining.Priority getFuturePlayerSkillTrainingPriority(PlayerSkill skillIndex) {
var s = getFuturePlayerSkillTraining(skillIndex);
if ( s != null){
return s.getPriority();
}
return null;
}

public List <FuturePlayerSkillTraining> getFuturePlayerSkillTrainings() {
if ( futurePlayerSkillTrainings == null){
futurePlayerSkillTrainings = DBManager.instance().loadFuturePlayerSkillTrainings(getPlayerId());
}
return futurePlayerSkillTrainings;
}

public boolean setFutureSkillTrainingPriority(int playerId, PlayerSkill skillIndex, FuturePlayerTraining.Priority prio) {
var futureSkillTraining = getFuturePlayerSkillTraining(skillIndex);
if (futureSkillTraining == null) {
if ( prio != null) {
futureSkillTraining = new FuturePlayerSkillTraining(getPlayerId(), prio, skillIndex);
futurePlayerSkillTrainings.add(futureSkillTraining);
}
else {
return false; // nothing changed
}
} else if ( prio == null ) {
futurePlayerSkillTrainings.remove(futureSkillTraining);
}
else if (!prio.equals(futureSkillTraining.getPriority())){
futureSkillTraining.setPriority(prio);
}
else {
return false; // nothing changed
}
DBManager.instance().storeFuturePlayerSkillTrainings(playerId, futurePlayerSkillTrainings);
return true;
}

private FuturePlayerSkillTraining getFuturePlayerSkillTraining(PlayerSkill skillIndex) {
var skillTrainingPlans = getFuturePlayerSkillTrainings();
return skillTrainingPlans.stream().filter(e->e.getSkillId()==skillIndex).findAny().orElse(null);
}


/**
* training priority information of the training panel
*
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/core/training/FuturePlayerSkillTraining.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package core.training;

import core.constants.player.PlayerSkill;
import core.db.AbstractTable;
import core.training.FuturePlayerTraining.Priority;

public class FuturePlayerSkillTraining extends AbstractTable.Storable {

/**
* Player Id
*/
private int playerId;

public static Integer getPriorityAsInteger(FuturePlayerSkillTraining o) {
if (o != null && o.getPriority() != null) {
return o.getPriority().getValue();
}
return null;
}

public PlayerSkill getSkillId() {
return skillId;
}

public void setSkillId(PlayerSkill skillId) {
this.skillId = skillId;
}

private PlayerSkill skillId;

/**
* priority of the training
*/
private Priority priority;

public FuturePlayerSkillTraining(int playerId, Priority prio, PlayerSkill skill) {
this.playerId = playerId;
this.priority = prio;
this.skillId = skill;
}

/**
* constructor is used by AbstractTable.load
*/
public FuturePlayerSkillTraining(){}

public Priority getPriority() {
return priority;
}

public void setPriority(Priority prio) {
this.priority = prio;
}

public int getPlayerId() {
return this.playerId;
}

public void setPlayerId(int playerId) {
this.playerId = playerId;
}

}
Loading

0 comments on commit 73214a3

Please sign in to comment.