/******************************************************************************* * 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.Map; import java.util.TreeMap; import com.dawg6.gwt.client.widgets.SimpleCaptionPanel; import com.dawg6.web.dhcalc.shared.calculator.ActiveSkill; import com.dawg6.web.dhcalc.shared.calculator.AttributeData; import com.dawg6.web.dhcalc.shared.calculator.GemLevel; import com.dawg6.web.dhcalc.shared.calculator.ItemHolder; import com.dawg6.web.dhcalc.shared.calculator.ItemSet; import com.dawg6.web.dhcalc.shared.calculator.Rune; import com.dawg6.web.dhcalc.shared.calculator.Slot; import com.dawg6.web.dhcalc.shared.calculator.SpecialItemType; import com.dawg6.web.dhcalc.shared.calculator.Util; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; public class CDRPanel extends Composite { private final ListBox diamond; private final NumberSpinner shoulders; private final NumberSpinner gloves; private final NumberSpinner amulet; private final NumberSpinner ring1; private final NumberSpinner ring2; private final NumberSpinner belt; private final NumberSpinner weapon; private final NumberSpinner quiver; private final Label effCDR; private Map<ActiveSkill, Rune> skills; private double cdr = 0.0; private final int skillRow = 11; private final FlexTable flexTable; private Map<Slot, ItemHolder> items; private Map<String, Integer> sets; public CDRPanel() { SimpleCaptionPanel cptnpnlCooldownReduction = new SimpleCaptionPanel( "Cooldown Reduction"); initWidget(cptnpnlCooldownReduction); flexTable = new FlexTable(); flexTable.setCellPadding(2); cptnpnlCooldownReduction.setContentWidget(flexTable); Label lblNewLabel = new Label("Helm (Diamond):"); lblNewLabel.setStyleName("boldText"); lblNewLabel.setWordWrap(false); flexTable.setWidget(0, 0, lblNewLabel); diamond = new ListBox(); flexTable.setWidget(0, 2, diamond); HorizontalPanel row = new HorizontalPanel(); row.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); row.setSpacing(5); flexTable.setWidget(1, 0, row); Label lblShoulders = new Label("Shoulders (%):"); lblShoulders.setWordWrap(false); lblShoulders.setStyleName("boldText"); flexTable.setWidget(2, 0, lblShoulders); shoulders = new NumberSpinner(); shoulders.setVisibleLength(4); flexTable.setWidget(2, 2, shoulders); Label lblGloves = new Label("Gloves (%):"); lblGloves.setWordWrap(false); lblGloves.setStyleName("boldText"); flexTable.setWidget(3, 0, lblGloves); gloves = new NumberSpinner(); gloves.setVisibleLength(4); flexTable.setWidget(3, 2, gloves); Label lblAmulet = new Label("Amulet (%):"); lblAmulet.setWordWrap(false); lblAmulet.setStyleName("boldText"); flexTable.setWidget(4, 0, lblAmulet); amulet = new NumberSpinner(); amulet.setVisibleLength(4); flexTable.setWidget(4, 2, amulet); Label lblRing = new Label("Ring 1 (%):"); lblRing.setWordWrap(false); lblRing.setStyleName("boldText"); flexTable.setWidget(5, 0, lblRing); ring1 = new NumberSpinner(); ring1.setVisibleLength(4); flexTable.setWidget(5, 2, ring1); Label lblRing_1 = new Label("Ring 2 (%):"); lblRing_1.setWordWrap(false); lblRing_1.setStyleName("boldText"); flexTable.setWidget(6, 0, lblRing_1); ring2 = new NumberSpinner(); ring2.setVisibleLength(4); flexTable.setWidget(6, 2, ring2); Label lblBelt = new Label("Belt (%):"); lblBelt.setWordWrap(false); lblBelt.setStyleName("boldText"); flexTable.setWidget(7, 0, lblBelt); belt = new NumberSpinner(); belt.setVisibleLength(4); flexTable.setWidget(7, 2, belt); Label lblWeapon = new Label("Main Hand (%):"); lblWeapon.setWordWrap(false); lblWeapon.setStyleName("boldText"); flexTable.setWidget(8, 0, lblWeapon); weapon = new NumberSpinner(); weapon.setVisibleLength(4); flexTable.setWidget(8, 2, weapon); Label lblQuiver = new Label("Off Hand (%):"); lblQuiver.setWordWrap(false); lblQuiver.setStyleName("boldText"); flexTable.setWidget(9, 0, lblQuiver); quiver = new NumberSpinner(); quiver.setVisibleLength(4); flexTable.setWidget(9, 2, quiver); for (GemLevel l : GemLevel.values()) { this.diamond.addItem(l.getDisplayName(), l.name()); } diamond.setSelectedIndex(0); this.shoulders.setMax(8); this.gloves.setMax(8); this.ring1.setMax(8); this.ring2.setMax(8); this.belt.setMax(8); this.weapon.setMax(10); this.quiver.setMax(10); this.amulet.setMax(8); Label l10 = new Label("Effective CDR:"); l10.addStyleName("boldText"); l10.setWordWrap(false); flexTable.setWidget(10, 0, l10); this.effCDR = new Label("0.0%"); this.effCDR.addStyleName("boldText"); flexTable.setWidget(10, 2, effCDR); this.skills = new TreeMap<ActiveSkill, Rune>(); this.items = new TreeMap<Slot, ItemHolder>(); this.cdr = 0.0; updateSkills(); } public ListBox getDiamond() { return diamond; } public NumberSpinner getShoulders() { return shoulders; } public NumberSpinner getGloves() { return gloves; } public NumberSpinner getAmulet() { return amulet; } public NumberSpinner getRing1() { return ring1; } public NumberSpinner getRing2() { return ring2; } public NumberSpinner getBelt() { return belt; } public NumberSpinner getWeapon() { return weapon; } public NumberSpinner getQuiver() { return quiver; } public GemLevel getSelectedDiamond() { int i = this.diamond.getSelectedIndex(); String value = this.diamond.getValue(i); return GemLevel.valueOf(value); } public void setDiamond(GemLevel diamond) { for (int i = 0; i < this.diamond.getItemCount(); i++) { String value = this.diamond.getValue(i); if (value.equals(diamond.name())) { this.diamond.setSelectedIndex(i); return; } } this.diamond.setSelectedIndex(0); } public Map<String, Integer> getData() { Map<String, Integer> map = new TreeMap<String, Integer>(); map.put(Slot.Shoulders.name(), shoulders.getValue()); map.put(Slot.Hands.name(), gloves.getValue()); map.put(Slot.Necklace.name(), amulet.getValue()); map.put(Slot.Ring1.name(), ring1.getValue()); map.put(Slot.Ring2.name(), ring2.getValue()); map.put(Slot.Waist.name(), belt.getValue()); map.put(Slot.MainHand.name(), weapon.getValue()); map.put(Slot.OffHand.name(), quiver.getValue()); return map; } public void setEffectiveCdr(double cdr) { this.cdr = cdr; this.effCDR.setText(Util.format(Math.round(cdr * 10000.0) / 100.0) + "%"); updateSkills(); } public void setSkills(Map<ActiveSkill, Rune> skills, Map<Slot, ItemHolder> items, Map<String, Integer> sets) { this.skills = skills; this.items = items; this.sets = sets; updateSkills(); } private void updateSkills() { while (flexTable.getRowCount() > this.skillRow) { flexTable.removeRow(this.skillRow); } int row = skillRow; for (Map.Entry<ActiveSkill, Rune> e : skills.entrySet()) { ActiveSkill skill = e.getKey(); Rune rune = e.getValue(); if ((skill == ActiveSkill.Companion) && (rune != Rune.Wolf) && (this.getSetCount(ItemSet.Marauders.getSlug()) >= 2)) rune = Rune.Wolf; double cd = skill.getCooldown(rune); if (cd > 0) { double duration = skill.getDuration(rune); Anchor a = new Anchor(skill.getLongName() + "/" + rune.getLongName()); a.setHref(skill.getUrl(rune)); flexTable.setWidget(row, 0, a); cd = cd * (1.0 - this.cdr); if ((skill == ActiveSkill.Vengeance) && this.isItem(SpecialItemType.Dawn)) { double d = this.getItemAttribute(SpecialItemType.Dawn, SpecialItemType.PERCENT); cd = cd * (1.0 - d); } double uptime; double downtime; if (cd <= duration) { uptime = 1.0; downtime = 0.0; } else { uptime = duration / cd; downtime = cd - duration; } Label l = new Label("Cooldown " + Util.format(Math.round(cd * 100.0) / 100.0) + "s"); flexTable.setWidget(row, 2, l); if (duration == 0) { flexTable.setWidget(row, 3, new Label("Uptime N/A")); flexTable.setWidget(row, 4, new Label("Downtime N/A")); } else { Label l2 = new Label("Uptime " + Util.format(Math.round(uptime * 10000.0) / 100.0) + "%"); Label l3 = new Label("Downtime " + Util.format(Math.round(downtime * 100.0) / 100.0) + " sec"); flexTable.setWidget(row, 3, l2); flexTable.setWidget(row, 4, l3); } row++; } } } private boolean isItem(SpecialItemType item) { for (ItemHolder i : items.values()) { if (i.getType() == item) return true; } return false; } public AttributeData getItemAttributes(SpecialItemType item) { for (ItemHolder i : items.values()) { if (i.getType() == item) return i.getAttributes(); } return null; } public double getItemAttribute(SpecialItemType item, String label) { AttributeData data = getItemAttributes(item); double value = 0.0; if (data != null) { Integer i = data.get(label); if (i != null) { for (SpecialItemType.Attribute a : item.getAttributes()) { if (a.getLabel().equals(label)) { value = a.getRawAttributeValue(i); } } } } return value; } public int getSetCount(String slug) { Integer i = sets.get(slug); if (i != null) { if ((i >= 2) && (this.isItem(SpecialItemType.RoyalRing))) i++; } else { i = 0; } return i; } }