plugin.getLog().debug("Calculating new prices...");
// Get trade volume of last day
Map<Job, Double> jobsums = new HashMap<>();
Map<ItemType, Double> itemsums = new HashMap<>();
double totalsum = 0;
//get all transactions
Map<Integer, Double> xitemsums = new HashMap<>();
try (PreparedStatement stmt = plugin.getSQLConnection().getConnection().prepareStatement(
"SELECT item_id, income FROM " + plugin.getConfig().getString("database.table.itemstats")
+ " WHERE DATE(datetime) = DATE(DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 1 DAY))");
ResultSet res = stmt.executeQuery())
{
while(res.next())
{
int itemid = res.getInt("item_id");
double income = res.getDouble("income");
if (ihandler.getById(itemid) == null || jhandler.getJobByItem(ihandler.getById(itemid)) == null)
continue;
if (!xitemsums.containsKey(itemid))
xitemsums.put(itemid, 0d);
xitemsums.put(itemid, xitemsums.get(itemid) + income);
}
}
catch (Exception e)
{
plugin.getLog().error("Failed to calculate prices, cannot load history!");
e.printStackTrace();
return;
}
//get items for ids
xitemsums.forEach((item, income) -> itemsums.put(ihandler.getById(item), income));
//add items that have not been sold since last execution
ihandler.getTypes().stream().filter(e -> !itemsums.containsKey(e)).forEach(e -> itemsums.put(e, 0d));
//calc job sums
itemsums.forEach((type, incomesum) ->
{
Job job = jhandler.getJobByItem(type);
if(job == null)
return;
if (!jobsums.containsKey(job))
jobsums.put(job, 0d);
jobsums.put(job, jobsums.get(job) + incomesum);
});
totalsum = itemsums.values().stream().mapToDouble(e -> e).sum();
//
// for (ItemType type : ihandler.getTypes()) {
// Job job = jhandler.getJobByItem(type);
//
// double tsum = type.getLastDayVolume();
// itemsums.put(type, tsum);
// if (!jobsums.containsKey(job)) {
// jobsums.put(job, 0.0);
// }
// jobsums.put(job, jobsums.get(job) + tsum);
// totalsum += tsum;
// }
plugin.getLog().debug("Total sum last day: " + totalsum);
if (totalsum < 1) {
plugin.getLog().error("Failed to calculate prices, missing old price values!");
return;
}
double averagePerJob = totalsum / jobsums.size();
// Reduce prices in jobs with volumes above average
double updateVolume = 0;
Map<Job, Double> minorJobSums = new HashMap<>();
Map<Job, Double> minorJobUpdates = new HashMap<>();
plugin.getLog().debug("Jobs above average:");
for (Job job : jobsums.keySet()) {
if (jobsums.get(job) > averagePerJob) {
plugin.getLog().debug(" - " + job.getName());
double maxvol = itemsums.keySet().stream().filter(item -> job.has(item)).map(item -> itemsums.get(item)).max(Double::compare).get();
for (ItemType item : itemsums.keySet().stream().filter(item -> job.has(item)).collect(Collectors.toList())) {
double oldprice = item.getPricePerItem();
item.setPricePerItem(oldprice * (1.0 - maxPercent * itemsums.get(item) / maxvol));
updateVolume += oldprice - item.getPricePerItem();
plugin.getLog().debug(" * " + item.getName() + ": " + oldprice + " => " + item.getPricePerItem());
}
} else {
minorJobSums.put(job, itemsums.keySet().stream().filter(item -> job.has(item)).mapToDouble(item -> itemsums.get(item)).sum());
minorJobUpdates.put(job, 0.0);
}
}
// Reduce total sum eventually
double updateVolumebefore = updateVolume;
int reduce = plugin.getConfig().getInt("balancing.reduce");
if (reduce != 0) {
updateVolume -= reduce;
if (updateVolume < 0)
updateVolume = 0;
plugin.getLog().info("Reduced total sum of prices by " + reduce + " BM from " + updateVolumebefore
+ " to " + updateVolume + " BM");
}
double reducepercent = plugin.getConfig().getDouble("balancing.reducepercent");
if (reducepercent > 0) {
updateVolume *= (1 - reducepercent);
if (updateVolume < 0)
updateVolume = 0;
plugin.getLog().info("Reduced total sum of prices by " + reducepercent + " from "
+ updateVolumebefore + " to " + updateVolume + " BM");
}
// Split update money to minor jobs
double minorJobsSum = minorJobSums.values().stream().mapToDouble(val -> val).sum();
for (Job job : minorJobUpdates.keySet()) {
if (minorJobsSum < 1) {
// If all minor jobs did not have any income, just distribute equally
minorJobUpdates.put(job, updateVolume * minorJobSums.get(job) / minorJobUpdates.size());
} else {
minorJobUpdates.put(job, updateVolume * minorJobSums.get(job) / minorJobsSum);
}
}
// Increase prices in jobs with volumes below average
plugin.getLog().debug("Jobs below average:");
for (Job job : minorJobUpdates.keySet()) {
plugin.getLog().debug(" - " + job.getName());
// Get items for job
Map<ItemType, Double> itemsRelative = new HashMap<>();
for (ItemType item : itemsums.keySet().stream().filter(item -> job.has(item)).collect(Collectors.toList())) {
if (minorJobSums.get(job) < 1) {
// Just distribute equally
itemsRelative.put(item, 1.0 - 1 / itemsums.keySet().stream().filter(item2 -> job.has(item2)).collect(Collectors.toList()).size());
} else {
itemsRelative.put(item, 1.0 - (itemsums.get(item) / minorJobSums.get(job)));
}
}
// Update prices
double relativeSum = itemsRelative.values().stream().mapToDouble(val -> val).sum();
for (ItemType item : itemsRelative.keySet()) {
double oldprice = item.getPricePerItem();
item.setPricePerItem(item.getPricePerItem() + minorJobUpdates.get(job) * itemsRelative.get(item) / relativeSum);
plugin.getLog().debug(" * " + item.getName() + ": " + oldprice + " => " + item.getPricePerItem());
}
}