/*******************************************************************************
* 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.server;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.dawg6.d3api.shared.ApiData;
import com.dawg6.d3api.shared.CareerProfile;
import com.dawg6.d3api.shared.Follower;
import com.dawg6.d3api.shared.HeroProfile;
import com.dawg6.d3api.shared.ItemInformation;
import com.dawg6.d3api.shared.Leaderboard;
import com.dawg6.d3api.shared.Realm;
import com.dawg6.d3api.shared.SeasonIndex;
import com.dawg6.web.dhcalc.client.DHCalcService;
import com.dawg6.web.dhcalc.server.db.couchdb.CouchDBDHCalcDatabase;
import com.dawg6.web.dhcalc.server.db.couchdb.CouchDBDHCalcParameters;
import com.dawg6.web.dhcalc.server.db.couchdb.NewsDocument;
import com.dawg6.web.dhcalc.shared.calculator.ExportData;
import com.dawg6.web.dhcalc.shared.calculator.FormData;
import com.dawg6.web.dhcalc.shared.calculator.NewsItem;
import com.dawg6.web.dhcalc.shared.calculator.Util;
import com.dawg6.web.dhcalc.shared.calculator.Version;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* The server-side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class DHCalcServiceImpl extends RemoteServiceServlet implements
DHCalcService {
// private final static Object lock = new Object();
// private final static ThreadPool pool = new ThreadPool(20);
private static final Logger log = Logger.getLogger(DHCalcServiceImpl.class
.getName());
public static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat(
"#,###.####");
{
Util.getInstance().setFormatter(new Util.Formatter() {
@Override
public String format(double d) {
return DECIMAL_FORMAT.format(d);
}
});
}
// private final Gson gson = new Gson();
@Override
public CareerProfile getProfile(final Realm realm, String profile, final int tag) {
try {
profile = URLEncoder.encode(profile, "UTF-8");
log.info("getProfile(" + realm.getDisplayName() + "," + profile
+ "-" + tag + ")");
CareerProfile career = IO.getInstance().readCareerProfile(realm,
profile, tag);
// log.info("Career: " + gson.toJson(career));
if (career == null) {
career = new CareerProfile();
career.code = "Timeout";
career.reason = "Timeout";
}
if (career.code != null)
log.info(realm.getDisplayName() + "/" + profile + "-" + tag
+ " Code: " + career.code + ", Reason: "
+ career.reason);
// else {
//
// final CareerProfile c2 = career;
// final String p2 = profile;
//
// pool.add(new Runnable(){
//
// @Override
// public void run() {
// scanHeroes(realm, p2, tag, c2);
// }});
//
// }
return career;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Getting Profile", e);
return null;
}
}
// private static Set<AccountDocument> accountLock = new HashSet<AccountDocument>();
// private void scanHeroes(Realm realm, String profile, int tag, CareerProfile career) {
//
// AccountDocument a = new AccountDocument();
// a.setRealm(realm);
// a.setProfile(profile.toLowerCase());
// a.setTag(tag);
// long now = System.currentTimeMillis();
// long old = now - (1000L * 60L * 60L * 4L);
//
// try {
// synchronized (accountLock) {
// if (accountLock.contains(a)) {
// return;
// } else {
// accountLock.add(a);
// }
// }
//
// List<AccountDocument> accounts = CouchDBDHCalcDatabase.getInstance().findAll(AccountDocument.class);
//
// boolean changed = false;
//
// for (AccountDocument ad : accounts) {
// if (ad.equals(a)) {
//
// if (ad.getLastChecked() >= old)
// return;
//
// a = ad;
// break;
// }
// }
//
// changed = true;
// a.setLastChecked(now);
//
// if (a.getHeroes() == null)
// a.setHeroes(new TreeSet<Integer>());
//
// if ((career.heroes != null) && (career.heroes.length > 0)) {
// Set<Integer> set = a.getHeroes();
//
// for (Hero h : career.heroes) {
//
// if ((h != null) && (h.clazz != null) && (h.clazz.equals(Const.CLASS_DEMONHUNTER))) {
// if (!set.contains(h.id)) {
// set.add(h.id);
// changed = true;
// }
//
// HeroProfile hero = getHero(realm, profile, tag, h.id, false);
//
// if ((hero.code != null) && (hero.code.equals(Const.NOT_FOUND))) {
// set.remove(h.id);
// changed = true;
// }
// }
// }
// } else if (!a.getHeroes().isEmpty()) {
// a.setHeroes(new TreeSet<Integer>());
// changed = true;
// }
//
// if (changed) {
// if (a.getRevision() == null)
// log.info("Creating account " + a);
// else
// log.info("Updating account " + a);
//
// CouchDBDHCalcDatabase.getInstance().persist(a);
// }
// }
// finally {
// synchronized (accountLock) {
// accountLock.remove(a);
// }
// }
// }
@Override
public ItemInformation getItem(Realm realm, String item) {
try {
// log.info("getItem(" + realm.getDisplayName() + "," + item + ")");
ItemInformation result = IO.getInstance().readItemInformation(realm,
item);
// log.info("Item: " + gson.toJson(result));
if (result == null) {
result = new ItemInformation();
result.code = "Timeout";
result.reason = "Timeout";
}
if (result.code != null)
log.info(realm.getDisplayName() + "/" + item + " Code: " + result.code + ", Reason: "
+ result.reason);
return result;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Getting Profile", e);
return null;
}
}
@Override
public HeroProfile getHero(Realm realm, String profile, int tag, int id) {
return getHero(realm, profile, tag, id, true);
}
public HeroProfile getHero(final Realm realm, String profile, final int tag, int id, boolean updateAccount) {
// if (updateAccount) {
//
// final String p2 = profile;
//
// new Thread(new Runnable(){
//
// @Override
// public void run() {
// getProfile(realm, p2, tag);
// }}).start();
// }
try {
profile = URLEncoder.encode(profile, "UTF-8");
log.info("getHero(" + realm.getDisplayName() + "," + profile + "-"
+ tag + "/" + id + ")");
HeroProfile hero = IO.getInstance().readHeroProfile(realm,
profile, tag, id);
if (hero == null) {
hero = new HeroProfile();
hero.code = "Timeout";
hero.reason = "Timeout";
}
if (hero.code != null)
log.warning(realm.getDisplayName() + "/" + profile + "-" + tag
+ " Code: " + hero.code + ", Reason: " + hero.reason);
if (hero.items != null) {
Map<String, ItemInformation> items = new TreeMap<String, ItemInformation>();
for (Map.Entry<String, ItemInformation> e : hero.items
.entrySet()) {
ItemInformation item = getItemNoLog(realm,
e.getValue().tooltipParams);
if (item != null) {
items.put(e.getKey(), item);
}
}
hero.items = items;
}
if (hero.followers != null) {
Follower[] flist = { hero.followers.templar, hero.followers.enchantress, hero.followers.scoundrel };
for (Follower f : flist) {
if ((f != null) && f.items != null) {
ItemInformation[] ilist = { f.items.leftFinger, f.items.rightFinger, f.items.neck, f.items.mainHand,
f.items.offHand, f.items.special };
int n = 0;
for (ItemInformation i : ilist) {
if ((i != null) && (i.tooltipParams != null)) {
ItemInformation item = getItemNoLog(realm,
i.tooltipParams);
if (item != null) {
ilist[n] = item;
}
}
n++;
}
n = 0;
f.items.leftFinger = ilist[n++];
f.items.rightFinger = ilist[n++];
f.items.neck = ilist[n++];
f.items.mainHand = ilist[n++];
f.items.offHand = ilist[n++];
f.items.special = ilist[n++];
}
}
}
return hero;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Getting Hero", e);
return null;
}
}
private ItemInformation getItemNoLog(Realm realm, String tooltipParams)
throws JsonParseException, IOException {
return IO.getInstance().readItemInformation(realm, tooltipParams);
}
public String serializeFormData(FormData data) {
try {
String key = String.valueOf(Math.random() + "." + Math.random()
+ ".FormData");
ObjectMapper mapper = new ObjectMapper();
String result = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(data);
ClientBuffer.getInstance().put(key, result.getBytes());
return key;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Serializing Form Data", e);
return null;
}
}
@Override
public FormData getClientData(String client) {
String key = client + ".FormData";
Object value = ClientBuffer.getInstance().get(key);
if (value == null) {
try {
Thread.sleep(1000);
} catch (Exception ignore) {
}
return null;
}
try {
return (FormData) value;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Deserializing Form Data", e);
return null;
}
}
@Override
public String exportData(ExportData data) {
ExportExcel excel = new ExportExcel(data);
try {
String key = String.valueOf(Math.random() + "." + Math.random()
+ ".Excel");
byte[] bytes = excel.export();
ClientBuffer.getInstance().put(key, bytes);
return key;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Exporting Excel data", e);
return null;
}
}
@Override
public Version getVersion() {
return Version.getVersion();
}
public String toJson(ApiData object) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
String str = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(object);
return str;
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Serializing Object", e);
return null;
}
}
public ApiData fromJson(String json, String type) {
try {
ObjectMapper mapper = new ObjectMapper();
return (ApiData) mapper.readValue(json, Class.forName(type));
} catch (Exception e) {
log.log(Level.SEVERE, "Exception Deserializing JSON", e);
return null;
}
}
// @Override
// public void logData(final CharacterData data) {
//
// new Thread(new Runnable() {
//
// @Override
// public void run() {
// data.setDefaults();
//
// log.info("Logging data for " + data.getProfile() + "-"
// + data.getTag() + "(" + data.getRealm().name() + ")/"
// + data.getHero());
//
// DpsTableEntry entry = calculateDps(data);
//
// CouchDBDHCalcDatabase.getInstance().logDps(entry);
// }
// }).start();
//
// }
// public DpsTableEntry calculateDps(CharacterData data) {
//
// Build build = new Build();
// build.setSkills(data.getSkills());
//
// DpsTableEntry entry = new DpsTableEntry();
//
// data.setDefaults();
// ProfileHelper.updateWeaponDamage(data);
// ProfileHelper.updateCdr(data);
// data.setDefaults();
//
// entry.setBattletag(data.getProfile() + "-" + data.getTag() + "/"
// + data.getHero());
// entry.setRealm(data.getRealm());
// entry.setBuild(build);
// entry.setParagon_dex(data.getParagonDexterity());
// entry.setParagon_cc(data.getParagonCC());
// entry.setParagon_cdr(data.getParagonCDR());
// entry.setParagon_chd(data.getParagonCHD());
// entry.setParagon_ias(data.getParagonIAS());
// entry.setParagon_hatred(data.getParagonHatred());
// entry.setParagon_rcr(data.getParagonRCR());
// entry.setParagon(data.getParagon());
// entry.setProfile(data.getProfile());
// entry.setTag(data.getTag());
// entry.setHeroId(data.getHero());
// entry.setHeroName(data.getHeroName());
// entry.setPlayerAps(data.getAps());
// entry.setSeasonal(data.isSeasonal());
// entry.setHardcore(data.isHardcore());
// entry.setDead(data.isDead());
// entry.setSheetDps(data.getSheetDps());
// entry.setLevel(data.getLevel());
//
// data.setNumAdditional(0);
// calculateDamage(data, entry);
// data.setNumAdditional(10);
// calculateDamage(data, entry);
//
// entry.setWhen(System.currentTimeMillis());
//
// return entry;
// }
//
// private void calculateDamage(CharacterData data, DpsTableEntry entry) {
//
// DamageResult damage = FiringData.calculateDamages(data);
//
// double total = 0.0;
// double totalElite = 0.0;
// double e = 1.0 + data.getTotalEliteDamage();
//
// for (Damage d : damage.damages) {
// total += d.actualDamage;
// // System.out.println(d.log);
// }
//
// total = total / damage.duration;
//
// totalElite = total * e;
//
// if (data.getNumAdditional() == 0) {
// entry.setSingle(total);
// entry.setSingle_elite(totalElite);
// } else {
// entry.setMultiple(total);
// entry.setMultiple_elite(totalElite);
// }
// }
//
// @Override
// public DBStatistics getStats(Rune sentryRune, ActiveSkill[] skills,
// Rune[] runes) {
// return CouchDBDHCalcDatabase.getInstance().getStatistics(sentryRune, skills, runes);
// }
@Override
public SeasonIndex getSeasonEraIndex(Realm realm) {
try {
SeasonIndex seasons = IO.getInstance().readSeasonIndex(realm);
SeasonIndex eras = IO.getInstance().readEraIndex(realm);
seasons.eras = eras.eras;
seasons.current_era = eras.current_era;
return seasons;
} catch (RuntimeException e) {
log.log(Level.SEVERE, "Exception", e);
throw e;
} catch (Exception e2) {
log.log(Level.SEVERE, "Exception", e2);
throw new RuntimeException(e2);
}
}
@Override
public Leaderboard getLeaderboard(Realm realm, int seasonEra,
boolean isEra, String which) {
try {
Leaderboard lb = null;
if (isEra) {
lb = IO.getInstance().readEraLeaderboard(realm, seasonEra, which);
} else {
lb = IO.getInstance().readSeasonLeaderboard(realm, seasonEra, which);
}
// Gson gson = new GsonBuilder().setPrettyPrinting().create();
//
// FileOutputStream os = new FileOutputStream("C:\\code\\out.json");
// PrintWriter writer = new PrintWriter(os);
// writer.println(gson.toJson(lb));
// writer.flush();
// writer.close();
return lb;
} catch (RuntimeException e) {
log.log(Level.SEVERE, "Exception", e);
throw e;
} catch (Exception e2) {
log.log(Level.SEVERE, "Exception", e2);
throw new RuntimeException(e2);
}
}
@Override
public NewsItem[] getNews() {
try {
List<NewsDocument> news = CouchDBDHCalcDatabase.getInstance().getNews();
List<NewsItem> result = new Vector<NewsItem>(news.size());
for (NewsDocument doc : news) {
result.add(new NewsItem(doc.getText()));
}
return result.toArray(new NewsItem[0]);
} catch (RuntimeException e) {
log.log(Level.SEVERE, "Exception", e);
throw e;
} catch (Exception e2) {
log.log(Level.SEVERE, "Exception", e2);
throw new RuntimeException(e2);
}
}
public static void terminate() {
log.info("terminate");
}
public static void initialize() {
log.info("initialize()");
CouchDBDHCalcDatabase.getInstance();
CouchDBDHCalcParameters.getInstance();
}
public static void main(String[] args) {
DHCalcServiceImpl.initialize();
DHCalcServiceImpl i = new DHCalcServiceImpl();
HeroProfile p = i.getHero(Realm.US, "dawg6", 1416, 72386632);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
log.info(gson.toJson(p));
}
}