/**
* @author Luke Tyler Downey
* Copyright 2011 Glow Interactive
*
* This software contains original work and/or modifications to
* original work, which are redistributed under the following terms.
*
*
* This program 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.
*
* This program 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/>.
*/
/**
* Copyright 2011 Brian Cairns
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.glowinteractive.reforger;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
public final class Character {
private static final String ARMORY_URL = "http://%s.battle.net/wow/en/character/%s/%s/advanced";
private final String _path;
// TODO: Convert item array into a FIFO structure.
private final ArrayList<Item> _items;
private boolean _parsed;
public Character(String region, String realm, String name) {
_path = URLUTF8Encoder.encode(String.format(ARMORY_URL, region, realm, name));
// NOTE: Current maximum number of items possible. This includes shirts and tabards,
// even though those slots are irrelevant as far as we're concerned.
_items = new ArrayList<Item>(24);
_parsed = false;
}
@SuppressWarnings("unchecked")
public synchronized void parse() {
if (_parsed == false) {
URL url = null;
HtmlCleaner parser = new HtmlCleaner();
TagNode root = null;
List<TagNode> nodes = null;
CleanerProperties config = parser.getProperties();
config.setAllowHtmlInsideAttributes(true);
config.setAllowMultiWordAttributes(true);
config.setRecognizeUnicodeChars(true);
// Parse items from the Armory.
try {
url = new URL(_path);
root = parser.clean(url);
} catch (Exception e) {
Debug.fatalError(Character.class.getSimpleName(), e);
}
nodes = Collections.checkedList(root.getElementListByAttValue("class", "slot-contents", true, false), TagNode.class);
assert nodes != null && !nodes.isEmpty(): "Error: unable to download item list.";
for (TagNode inode : nodes) {
int slot = Integer.parseInt(inode.getParent().getParent().getAttributeByName("data-id"));
// Check for empty slots.
// NOTE: We must take care not to discard valid items
// with empty sockets.
TagNode[] children = inode.getChildTags();
if (children.length == 1 && "a".equals(children[0].getName()) &&
"javascript:;".equals(children[0].getAttributeByName("href")) &&
"empty".equals(children[0].getAttributeByName("class")))
continue;
// Ignore tabard and shirt slots.
if (slot == 3 || slot == 18) continue;
Item i = new Item(slot, inode);
_items.add(i);
if (Debug.DEBUG) {
// Parse items serially in debug mode.
i.parse();
} else {
// TODO: Parse items on thread pool.
}
}
_parsed = true;
}
}
public ArrayList<Item> items() {
parse();
return _items;
}
public StatKVMap mutableStats() {
parse();
StatKVMap r = new StatKVMap();
for (Item i : _items) {
r = r.add(i.mutableStats());
}
return r;
}
public StatKVMap immutableStats() {
parse();
StatKVMap r = new StatKVMap();
for (Item i : _items) {
r = r.add(i.immutableStats());
}
return r;
}
// public StatKVMap currentReforging() {
// return _currentReforging;
// }
}