• new
  • Powered by GeSHi
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());
                    }
                }