package polly.rx.httpv2;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import polly.rx.MyPlugin;
import polly.rx.core.SumQueries;
import polly.rx.core.orion.Orion;
import polly.rx.core.orion.model.Production;
import polly.rx.entities.BattleDrop;
import polly.rx.entities.BattleReport;
import polly.rx.entities.BattleTactic;
import polly.rx.entities.RxRessource;
import de.skuzzle.polly.http.api.HttpEvent;
import de.skuzzle.polly.http.api.HttpSession;
import de.skuzzle.polly.sdk.Types.NumberType;
import de.skuzzle.polly.sdk.User;
import de.skuzzle.polly.sdk.httpv2.WebinterfaceManager;
import de.skuzzle.polly.sdk.httpv2.html.HTMLModelListener;
import de.skuzzle.polly.sdk.httpv2.html.HTMLTableModel;
import de.skuzzle.polly.tools.math.MathUtil;
public class StatisticsGatherer implements HTMLModelListener<BattleReport> {
public static class BattleReportStatistics {
public final BattleDrop[] dropSum = new BattleDrop[14];
public final BattleDrop[] dropMax = new BattleDrop[14];
public final BattleDrop[] dropMin = new BattleDrop[14];
public final BattleDrop[] repairCostAttacker = new BattleDrop[7];
public final BattleDrop[] repairCostDefender = new BattleDrop[7];
public final BattleDrop[] dropNetto = new BattleDrop[14];
public double[] dropPrices = new double[14];
public double[] dropPricesAtDropTime = new double[14];
public double[] currentPrices = new double[14];
public double kwAttacker = 0;
public double kwDefender = 0;
public int capiXpSumAttacker = 0;
public int crewXpSumAttacker = 0;
public int capiXpSumDefender = 0;
public int crewXpSumDefender = 0;
public int pzDamageAttacker = 0;
public int pzDamageDefender = 0;
public int artifacts = 0;
public double repairTimeAttacker = 0;
public double repairTimeDefender = 0;
public int dropPriceSum;
public int dropPriceSumAtDropTime;
public double reportSize = 0; // as double for auto casting when calculating avg
public double artifactChance = 0.0;
BattleReportStatistics() {
kwAttacker = 0;
kwDefender = 0;
capiXpSumAttacker = 0;
crewXpSumAttacker = 0;
capiXpSumDefender = 0;
crewXpSumDefender = 0;
pzDamageAttacker = 0;
pzDamageDefender = 0;
artifacts = 0;
repairTimeAttacker = 0;
repairTimeDefender = 0;
reportSize = 0;
artifactChance = 0.0;
dropPriceSum = 0;
dropPriceSumAtDropTime = 0;
BattleDrop.clear(dropSum);
BattleDrop.clear(dropMax);
BattleDrop.clear(dropMin);
Arrays.fill(dropPrices, 0);
Arrays.fill(dropPricesAtDropTime, 0);
}
}
static void calculateNetto(BattleDrop[] dropSum, BattleDrop[] repairCost,
BattleDrop[] result) {
assert dropSum.length == RxRessource.values().length && repairCost.length == 7
&& result.length == dropSum.length;
outer: for (int i = 0; i < dropSum.length; ++i) {
assert dropSum[i] != null;
// find matching repair cost:
for (int j = 0; j < repairCost.length; ++j) {
assert repairCost[j] != null;
if (dropSum[i].getRessource() == repairCost[j].getRessource()) {
result[i] = new BattleDrop(dropSum[i].getRessource(),
dropSum[i].getAmount() - repairCost[j].getAmount());
continue outer;
}
}
// no value for this ress type
result[i] = dropSum[i];
}
}
static double inCr(BattleDrop[] drop, double[] prices, double result[]) {
assert drop.length == prices.length;
double sum = 0;
for (int i = 0; i < drop.length; ++i) {
result[i] = drop[i] != null
? drop[i].getAmount() * prices[i]
: 0;
sum += result[i];
}
return sum;
}
@Override
public void onDataProcessed(HTMLTableModel<BattleReport> source,
List<BattleReport> data, HttpEvent e) {
final HttpSession s = e.getSession();
final User user = (User) s.get(WebinterfaceManager.USER);
final String STATISTIC_KEY = RXController.STATS_PREFIX + user.getName();
final int dockLevel = (int)
((NumberType) user.getAttribute(MyPlugin.DOCK_LEVEL)).getValue();
final BattleReportStatistics stats = new BattleReportStatistics();
s.set(STATISTIC_KEY, stats);
Date youngest = null;
synchronized (stats) {
for (BattleReport report : data) {
// do some filtering according to current sessions filter settings
if (report.getTactic() == BattleTactic.ALIEN) {
report = BattleReport.switchAttacker(report);
}
youngest = youngest == null
? report.getDate()
: MathUtil.max(youngest, report.getDate());
for (int i = 0; i < 14; ++i) {
BattleDrop drop = report.getDrop().get(i);
if (stats.dropSum[i] == null) {
stats.dropSum[i] = new BattleDrop(drop.getRessource(),
drop.getAmount());
stats.dropMin[i] = new BattleDrop(drop.getRessource(),
drop.getAmount());
stats.dropMax[i] = new BattleDrop(drop.getRessource(),
drop.getAmount());
} else {
stats.dropSum[i].incAmout(drop);
stats.dropMin[i].setAmount(Math.min(stats.dropMin[i].getAmount(),
drop.getAmount()));
stats.dropMax[i].setAmount(Math.max(stats.dropMax[i].getAmount(),
drop.getAmount()));
}
}
stats.kwAttacker += report.getAttackerKw() / report.getAttackerBonus();
stats.kwDefender += report.getDefenderKw() / report.getDefenderBonus();
stats.capiXpSumAttacker += report.querySumAttacker(SumQueries.CAPI_XP);
stats.crewXpSumAttacker += report.querySumAttacker(SumQueries.CREW_XP);
stats.capiXpSumDefender+= report.querySumDefender(SumQueries.CAPI_XP);
stats.crewXpSumDefender += report.querySumDefender(SumQueries.CREW_XP);
stats.pzDamageAttacker += report.querySumAttacker(SumQueries.PZ_DAMAGE);
stats.pzDamageDefender += report.querySumDefender(SumQueries.PZ_DAMAGE);
report.calculateRepairTimes();
stats.repairTimeAttacker += report.getAttackerRepairTimeOffset(dockLevel);
stats.repairTimeDefender += report.getDefenderRepairTimeOffset(dockLevel);
BattleDrop.sumUp(stats.repairCostAttacker, report.getAttackerRepairCostOffset());
BattleDrop.sumUp(stats.repairCostDefender, report.getDefenderRepairCostOffset());
stats.artifacts += report.hasArtifact() ? 1 : 0;
}
calculateNetto(stats.dropSum, stats.repairCostAttacker, stats.dropNetto);
stats.reportSize = data.size();
stats.kwAttacker /= data.size();
stats.kwDefender /= data.size();
stats.currentPrices = getPriceArray(null); // null for today
stats.dropPriceSum = (int) inCr(stats.dropNetto, stats.currentPrices, stats.dropPrices);
stats.dropPriceSumAtDropTime = (int) inCr(stats.dropNetto, getPriceArray(youngest), stats.dropPricesAtDropTime);
stats.artifactChance = data.isEmpty()
? 0.0 : (double) stats.artifacts / (double) data.size();
}
}
private static double[] getPriceArray(Date date) {
final double[] result = new double[RxRessource.values().length];
final List<? extends Production> prod = Orion.INSTANCE.getPriceProvider().getAllPrices(date);
int i = 0;
for (final Production p : prod) {
result[i++] = p.getRate();
}
return result;
}
}