/*******************************************************************************
* Copyright (c) 2014, 2015 Scott Clarke (scott@dawg6.com).
*
* This file is part of Dawg6's Demon Hunter DPS Calculator.
*
* Dawg6's Demon Hunter DPS Calculator is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dawg6's Demon Hunter DPS Calculator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.dawg6.web.dhcalc.client;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
import org.moxieapps.gwt.highcharts.client.AxisTitle;
import org.moxieapps.gwt.highcharts.client.BaseChart;
import org.moxieapps.gwt.highcharts.client.Button.Align;
import org.moxieapps.gwt.highcharts.client.Chart;
import org.moxieapps.gwt.highcharts.client.ContextButton;
import org.moxieapps.gwt.highcharts.client.Exporting;
import org.moxieapps.gwt.highcharts.client.Point;
import org.moxieapps.gwt.highcharts.client.Series;
import org.moxieapps.gwt.highcharts.client.Style;
import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsData;
import org.moxieapps.gwt.highcharts.client.labels.AxisLabelsFormatter;
import org.moxieapps.gwt.highcharts.client.labels.XAxisLabels;
import org.moxieapps.gwt.highcharts.client.labels.YAxisLabels;
import com.dawg6.gwt.client.widgets.SimpleCaptionPanel;
import com.dawg6.web.dhcalc.shared.calculator.Damage;
import com.dawg6.web.dhcalc.shared.calculator.DamageResult;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.SimplePanel;
public class GraphPanel extends Composite {
private Chart chart;
private DamageResult log;
private final CheckBox skills;
private final FlexTable table;
private final CheckBox target;
private final CheckBox dps;
private final CheckBox targetHp;
private final CheckBox hatred;
public GraphPanel() {
SimplePanel panel = new SimplePanel();
this.initWidget(panel);
table = new FlexTable();
panel.setWidget(table);
SimpleCaptionPanel options = new SimpleCaptionPanel("Options");
table.setWidget(1, 0, options);
FlexTable table2 = new FlexTable();
options.setContentWidget(table2);
skills = new CheckBox("Show By Skill");
skills.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
redraw();
}
});
int row = 0;
int column = 0;
table2.setWidget(row, column++, skills);
target = new CheckBox("Show By Target");
table2.setWidget(row, column++, target);
target.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
redraw();
}
});
dps = new CheckBox("Show DPS");
table2.setWidget(row, column++, dps);
dps.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
redraw();
}
});
targetHp = new CheckBox("Show Target HP %");
table2.setWidget(row, column++, targetHp);
targetHp.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
redraw();
}
});
hatred = new CheckBox("Show Hatred");
table2.setWidget(row, column++, hatred);
hatred.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
redraw();
}
});
resetChart();
table.setWidget(0, 0, chart);
}
private void resetChart() {
chart = new Chart();
chart.setType(Series.Type.LINE);
chart.setChartTitleText("Damage Log");
chart.setWidth("800px");
chart.setHeight("600px");
AxisTitle x = new AxisTitle();
x.setText("Time");
x.setStyle(new Style().setColor("black").setFontWeight("bold"));
chart.getXAxis().setAxisTitle(x);
chart.getXAxis().setMin(0);
chart.getXAxis().setLabels(
new XAxisLabels().setStyle(new Style().setColor("black")
.setFontWeight("bold")));
AxisTitle y0 = new AxisTitle();
y0.setText("Damage");
y0.setStyle(new Style().setColor("black").setFontWeight("bold"));
chart.getYAxis(0).setAxisTitle(y0);
chart.getYAxis(0).setLabels(
new YAxisLabels().setFormatter(new AxisLabelsFormatter() {
@Override
public String format(AxisLabelsData axisLabelsData) {
double d = axisLabelsData.getValueAsDouble();
if (d < 1000)
return String.valueOf((long) d);
else if (d < 1000000)
return String.valueOf((long) d / 1000) + "K";
else if (d < 100000000)
return String.valueOf((long) d / 1000000) + "M";
else
return String.valueOf((long) d / 1000000000) + "B";
}
})
.setStyle(
new Style().setColor("black").setFontWeight(
"bold")));
chart.getYAxis(0).setMin(0);
if (this.targetHp.getValue()) {
chart.getYAxis(1).setMin(0);
chart.getYAxis(1).setMax(100.0);
chart.getYAxis(1).setOpposite(true);
AxisTitle y1 = new AxisTitle();
y1.setText("HP Percent");
y1.setStyle(new Style().setColor("green").setFontWeight("bold"));
chart.getYAxis(1).setAxisTitle(y1);
chart.getYAxis(1).setLabels(
new YAxisLabels().setFormatter(new AxisLabelsFormatter() {
@Override
public String format(AxisLabelsData axisLabelsData) {
if (axisLabelsData.getValueAsDouble() > 100)
return "";
else
return axisLabelsData.getValueAsString() + "%";
}
})
.setStyle(
new Style().setColor("green")
.setFontWeight("bold")));
}
if (this.hatred.getValue()) {
chart.getYAxis(2).setMin(0);
AxisTitle y2 = new AxisTitle();
y2.setText("Hatred");
y2.setStyle(new Style().setColor("red").setFontWeight("bold"));
chart.getYAxis(2).setAxisTitle(y2);
chart.getYAxis(2).setOpposite(true);
chart.getYAxis(2).setLabels(
new YAxisLabels().setFormatter(new AxisLabelsFormatter() {
@Override
public String format(AxisLabelsData axisLabelsData) {
return String.valueOf(axisLabelsData
.getValueAsLong());
}
}).setStyle(
new Style().setColor("red").setFontWeight("bold")));
}
ContextButton button = new ContextButton();
button.setAlign(Align.RIGHT);
chart.setExporting(new Exporting().setContextButton(button));
chart.setZoomType(BaseChart.ZoomType.X_AND_Y);
}
public void setLog(DamageResult log) {
this.log = log;
redraw();
}
protected void redraw() {
if (log == null)
return;
resetChart();
boolean showSkills = skills.getValue();
boolean showTarget = target.getValue();
boolean showDps = dps.getValue();
boolean showTargetHp = targetHp.getValue();
boolean showHatred = hatred.getValue();
List<Series> series = new Vector<Series>();
Map<String, Integer> map = new TreeMap<String, Integer>();
List<List<Point>> points = new Vector<List<Point>>();
List<Double> prev = new Vector<Double>();
Series dpsSeries = null;
double totalDamage = 0.0;
List<Point> dpsPoints = new Vector<Point>();
double dpsPrev = -1;
double max[] = { 0.0, 100.0, 125.0 };
if (!showSkills && !showTarget) {
Series s = chart.createSeries();
s.setYAxis(0);
s.setName("Damage Done");
s.setOption("color", "black");
chart.addSeries(s);
series.add(s);
points.add(new Vector<Point>());
prev.add(new Double(-1));
}
if (showDps) {
dpsSeries = chart.createSeries();
dpsSeries.setName("DPS");
dpsSeries.setOption("color", "blue");
chart.addSeries(dpsSeries);
dpsSeries.setYAxis(0);
}
for (Damage d : log.damages) {
{
if (showHatred) {
String source = "Hatred";
Integer index = map.get(source);
if (index == null) {
index = series.size();
map.put(source, index);
Series s = chart.createSeries();
s.setOption("color", "red");
s.setYAxis(2);
s.setName(source);
chart.addSeries(s);
series.add(s);
points.add(new Vector<Point>());
prev.add(new Double(-1));
}
List<Point> pt = points.get(index);
Double pp = prev.get(index);
if (d.time > pp) {
pt.add(new Point(d.time, d.currentHatred));
prev.set(index, d.time);
} else {
int n = pt.size() - 1;
Point p = pt.get(n);
pt.set(n, new Point(p.getX(), d.currentHatred));
}
max[2] = Math.max(max[2], d.currentHatred);
}
}
if (d.damage > 0) {
if (showDps) {
totalDamage += d.damage;
double duration = d.time;
if (duration == 0)
duration = 1.0;
double dps = totalDamage / duration;
max[0] = Math.max(max[0], dps);
if (d.time > dpsPrev) {
dpsPoints.add(new Point(d.time, dps));
} else {
int n = dpsPoints.size();
Point p = dpsPoints.get(n);
dpsPoints.set(n, new Point(p.getX(), dps));
}
}
if (showTargetHp) {
String source = d.target.toString() + " HP (%)";
Integer index = map.get(source);
if (index == null) {
index = series.size();
map.put(source, index);
Series s = chart.createSeries();
s.setOption("color", "green");
s.setYAxis(1);
s.setName(source);
chart.addSeries(s);
series.add(s);
points.add(new Vector<Point>());
prev.add(new Double(-1));
}
List<Point> pt = points.get(index);
Double pp = prev.get(index);
if (d.time > pp) {
pt.add(new Point(d.time, d.targetHpPercent * 100.0));
prev.set(index, d.time);
} else {
int n = pt.size() - 1;
Point p = pt.get(n);
pt.set(n,
new Point(p.getX(), d.targetHpPercent * 100.0));
}
}
{
Integer index = 0;
if (showSkills || showTarget) {
StringBuffer buf = new StringBuffer();
if (showTarget)
buf.append(d.target.toString());
if (showSkills) {
if (showTarget)
buf.append("-");
buf.append(d.source.getName());
}
String source = buf.toString();
index = map.get(source);
if (index == null) {
index = series.size();
map.put(source, index);
Series s = chart.createSeries();
s.setYAxis(0);
s.setName(source);
chart.addSeries(s);
series.add(s);
points.add(new Vector<Point>());
prev.add(new Double(-1));
}
}
List<Point> pt = points.get(index);
Double pp = prev.get(index);
if (d.time > pp) {
pt.add(new Point(d.time, d.damage));
prev.set(index, d.time);
max[0] = Math.max(max[0], d.damage);
} else {
int n = pt.size() - 1;
Point p = pt.get(n);
double dd = p.getY().doubleValue() + d.damage;
pt.set(n, new Point(p.getX(), dd));
max[0] = Math.max(max[0], dd);
}
}
}
}
if (showDps)
dpsSeries.setPoints(dpsPoints.toArray(new Point[0]));
for (int i = 0; i < series.size(); i++) {
series.get(i).setPoints(points.get(i).toArray(new Point[0]));
}
for (int i = 0; i < max.length; i++) {
if ((i == 0) || ((i == 1) && showTargetHp)
|| ((i == 2) && showHatred)) {
chart.getYAxis(i).setExtremes(0, max[i], false, false);
}
}
table.setWidget(0, 0, chart);
}
}