| @@ -24,12 +24,14 @@ | |||
| <handlers xmi:id="_a0tuEGAUEeuNUoCJDLJTzQ" elementId="xyz.veronie.bgg.ui.handler.save" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.handlers.SaveGamelistHandler" command="_lA5t8F9TEeuvNqpgCDWpdQ"/> | |||
| <handlers xmi:id="_xJXjUG3zEeuCP7xCflu8WA" elementId="xyz.veronie.bgg.ui.handler.load" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.handlers.LoadGamelistHandler" command="_qyrHAG3zEeuCP7xCflu8WA"/> | |||
| <handlers xmi:id="_y97SUG7REeutwMlAyj2x8w" elementId="xyz.veronie.bgg.ui.handler.importResultTxt" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.handlers.ImportResultTxtHandler" command="_rkauIG7REeutwMlAyj2x8w"/> | |||
| <handlers xmi:id="_I0EUoHOzEeuMU7Jt9moleA" elementId="xyz.veronie.bgg.ui.handler.export" contributionURI="bundleclass://xyz.veronie.bgg.ui/xyz.veronie.bgg.ui.handlers.ExportResultHandler" command="_OUnzIHOzEeuMU7Jt9moleA"/> | |||
| <menuContributions xmi:id="_AitwEHBeEeuk7d_98DxC5A" elementId="xyz.veronie.bgg.ui.menucontribution.gamelists" accessibilityPhrase="Game Lists" positionInParent="0"> | |||
| <children xsi:type="menu:HandledMenuItem" xmi:id="_JvwHYHBeEeuk7d_98DxC5A" elementId="importResult" label="Import..." tooltip="Import thing list from bgg1tool result.txt file" command="_rkauIG7REeutwMlAyj2x8w"/> | |||
| </menuContributions> | |||
| <commands xmi:id="_lA5t8F9TEeuvNqpgCDWpdQ" elementId="xyz.veronie.bgg.ui.command.save" commandName="Save" description="save game list"/> | |||
| <commands xmi:id="_qyrHAG3zEeuCP7xCflu8WA" elementId="xyz.veronie.bgg.ui.command.load" commandName="Load" description="load game list"/> | |||
| <commands xmi:id="_rkauIG7REeutwMlAyj2x8w" elementId="xyz.veronie.bgg.ui.command.importResultTxt" commandName="ImportResultTxt" description="Import result.txt from bgg1tool"/> | |||
| <commands xmi:id="_OUnzIHOzEeuMU7Jt9moleA" elementId="xyz.veronie.bgg.ui.command.export" commandName="Export" description="export result.txt file"/> | |||
| <addons xmi:id="_Lw_ZsUqSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/> | |||
| <addons xmi:id="_Lw_ZskqSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/> | |||
| <addons xmi:id="_Lw_Zs0qSEeqT5sxfmvJ5Tg" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/> | |||
| @@ -14,6 +14,7 @@ import java.util.List; | |||
| import xyz.veronie.bgg.result.Thing; | |||
| import xyz.veronie.bgg.result.ThingMetaData; | |||
| import xyz.veronie.bgg.result.ThingUserData; | |||
| import xyz.veronie.bgg.ui.helpers.Resources; | |||
| public class SqliteController { | |||
| @@ -89,6 +90,41 @@ public class SqliteController { | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idx1 ON ThingList(Name)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingListToThing (ListId INTEGER, ThingId INTEGER, FOREIGN KEY (ListId) REFERENCES ThingList(ListId), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idx2 ON ThingListToThing(ListId, ThingId)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Artist (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idxArtist ON Artist(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Designer (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idDesigner ON Designer(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Mechanic (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idxMechanic ON Mechanic(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Family (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idxFamily ON Family(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Category (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idxCategory ON Category(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Expansion (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idxExpansion ON Expansion(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Domain (Id INTEGER PRIMARY KEY, Name);"); | |||
| stmt.executeUpdate("CREATE UNIQUE INDEX IF NOT EXISTS idxDomain ON Domain(Id)"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingDetails (" | |||
| + "ThingId INTEGER PRIMARY KEY, name, yearpublished INTEGER, " | |||
| + "minplayers INTEGER, maxplayers INTEGER, playingtime INTEGER, minplaytime INTEGER, maxplaytime INTEGER, " | |||
| + "age INTEGER, usersrated INTEGER, average FLOAT, bayesaverage FLOAT, " | |||
| + "owning INTEGER, trading INTEGER, wanting INTEGER, wishing INTEGER, " | |||
| + "rank INTEGER, rank_wg INTEGER, numcomments INTEGER, numweights INTEGER, " | |||
| + "averageweight FLOAT, stddev FLOAT, median FLOAT, image, comment," | |||
| + "player1,player2,player3,player4,player5,player6,player7,player8,player9,player10," | |||
| + "player11, player12, player13, player14, player15, player16, player17, player18, player19, player20," | |||
| + "description, numplays INTEGER, price FLOAT, age_poll FLOAT);"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToArtist (ThingId INTEGER, ArtistId INTEGER, FOREIGN KEY (ArtistId) REFERENCES Artist(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToDesigner (ThingId INTEGER, DesignerId INTEGER, FOREIGN KEY (DesignerId) REFERENCES Designer(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToMechanic (ThingId INTEGER, MechanicId INTEGER, FOREIGN KEY (MechanicId) REFERENCES Mechanic(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToFamily (ThingId INTEGER, FamilyId INTEGER, FOREIGN KEY (FamilyId) REFERENCES Family(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToCategory (ThingId INTEGER, CategoryId INTEGER, FOREIGN KEY (CategoryId) REFERENCES Category(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToExpansion (ThingId INTEGER, ExpansionId INTEGER, FOREIGN KEY (ExpansionId) REFERENCES Expansion(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingToDomain (ThingId INTEGER, DomainId INTEGER, FOREIGN KEY (DomainId) REFERENCES Domain(Id), FOREIGN KEY (ThingId) REFERENCES Thing(ThingId));"); | |||
| stmt.close(); | |||
| } catch (SQLException e) { | |||
| System.err.println("Couldn't create Schema"); | |||
| @@ -181,10 +217,16 @@ public class SqliteController { | |||
| thingStatement.setString(2, metaData.getName()); | |||
| thingStatement.setString(3, metaData.getImgURL()); | |||
| thingStatement.setString(4, metaData.getThumbURL()); | |||
| thingStatement.setString(5, metaData.getComment()); | |||
| if(metaData.getNumPlays() != null) { | |||
| thingStatement.setInt(6, metaData.getNumPlays()); | |||
| ThingUserData userData = thing.getUserData(); | |||
| if(userData != null) { | |||
| thingStatement.setString(5, userData.getComment()); | |||
| if(userData.getNumPlays() != null) { | |||
| thingStatement.setInt(6, userData.getNumPlays()); | |||
| } else { | |||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | |||
| } | |||
| } else { | |||
| thingStatement.setString(5, ""); | |||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | |||
| } | |||
| thingStatement.execute(); | |||
| @@ -254,10 +296,12 @@ public class SqliteController { | |||
| ThingMetaData metaData = new ThingMetaData(id, | |||
| res.getString(2), | |||
| res.getString(3), | |||
| res.getString(4), | |||
| res.getString(5), | |||
| res.getInt(6)); | |||
| res.getString(4)); | |||
| ThingUserData userData = new ThingUserData(); | |||
| userData.setComment(res.getString(5)); | |||
| userData.setNumPlays(res.getInt(6)); | |||
| Thing thing = new Thing(id, metaData); | |||
| thing.setUserData(userData); | |||
| thingList.add(thing); | |||
| } | |||
| @@ -78,6 +78,21 @@ public class BggApi { | |||
| return getThings(urlStr.toString()); | |||
| } | |||
| public ArrayList<Thing> getThingDetails(Set<Integer> ids) { | |||
| StringBuilder urlStr = new StringBuilder(); | |||
| urlStr.append(BASE_URL + "thing?id="); | |||
| String sep = ""; | |||
| for (Integer integer : ids) { | |||
| urlStr.append(sep + integer.toString()); | |||
| if(sep.isEmpty()) { | |||
| sep = ","; | |||
| } | |||
| } | |||
| return getThings(urlStr.toString()); | |||
| } | |||
| public ArrayList<Thing> getThingsForUser(String user) throws IllegalArgumentException { | |||
| ResultConfig resultConfig = configManager.getResultConfig(); | |||
| @@ -171,7 +186,7 @@ public class BggApi { | |||
| // do something with the content | |||
| System.out.println(content.toString()); | |||
| ArrayList<Thing> output = parseThingMetas(content.toString()); | |||
| ArrayList<Thing> output = parseThings(content.toString()); | |||
| output.sort((thing1, thing2) -> thing1.getMetaData().getName().compareTo(thing2.getMetaData().getName())); | |||
| @@ -198,7 +213,7 @@ public class BggApi { | |||
| private ArrayList<Thing> parseThingMetas(String content) throws IllegalArgumentException { | |||
| private ArrayList<Thing> parseThings(String content) throws IllegalArgumentException { | |||
| ArrayList<Thing> things = new ArrayList<Thing>(); | |||
| DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | |||
| @@ -224,87 +239,20 @@ public class BggApi { | |||
| if( eElement.hasAttribute("objecttype") | |||
| && eElement.getAttribute("objecttype").equals("thing")) | |||
| { | |||
| Integer id = Integer.parseInt(eElement.getAttribute("objectid")); | |||
| if(id != 0) { | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| getValue(eElement, "name"), | |||
| getValue(eElement, "image"), | |||
| getValue(eElement, "thumbnail"), | |||
| getValue(eElement, "comment"), | |||
| Integer.parseInt(getValue(eElement, "numplays")) | |||
| ); | |||
| Thing thing = new Thing(id, tmd); | |||
| things.add(thing); | |||
| } | |||
| extractThingByUser(things, eElement); | |||
| } | |||
| // when fetching things by id, type is boardgame | |||
| else if(eElement.hasAttribute("type") && | |||
| eElement.getAttribute("type").equals("boardgame")) | |||
| { | |||
| Integer id = Integer.parseInt(eElement.getAttribute("id")); | |||
| if(id != 0) { | |||
| String name = ""; | |||
| NodeList nameList = eElement.getElementsByTagName("name"); | |||
| for(int n = 0; n < nameList.getLength(); n++) { | |||
| Node nameNode = nameList.item(n); | |||
| if (nNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element nameElement = (Element) nameNode; | |||
| if(nameElement.hasAttribute("type") | |||
| && nameElement.getAttribute("type").equals("primary")) | |||
| { | |||
| name = nameElement.getAttribute("value"); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| name, | |||
| getValue(eElement, "image"), | |||
| getValue(eElement, "thumbnail"), | |||
| getValue(eElement, "comment"), | |||
| null | |||
| ); | |||
| Thing thing = new Thing(id, tmd); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| extractThingsById(things, nNode, eElement); | |||
| } | |||
| // family has "type" | |||
| else if(eElement.hasAttribute("type") | |||
| && eElement.getAttribute("type").equals("boardgamefamily")) | |||
| { | |||
| // get name and description | |||
| StringBuilder fInfo = new StringBuilder(); | |||
| NodeList nListName = eElement.getElementsByTagName("name"); | |||
| if(nListName.getLength() > 0) { | |||
| fInfo.append(nListName.item(0).getTextContent() + "\r\n"); | |||
| } | |||
| NodeList nListDesc = doc.getElementsByTagName("description"); | |||
| if(nListDesc.getLength() > 0) { | |||
| fInfo.append(nListDesc.item(0).getTextContent()); | |||
| } | |||
| eventBroker.send(EventConstants.TOPIC_FAMILY_INFO, fInfo.toString()); | |||
| NodeList nLinks = eElement.getElementsByTagName("link"); | |||
| for(int l = 0; l < nLinks.getLength(); l++) { | |||
| Node link = nLinks.item(l); | |||
| if (link.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element eLink = (Element) link; | |||
| Integer id = Integer.parseInt(eLink.getAttribute("id")); | |||
| if(id != 0) { | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| eLink.getAttribute("value"), | |||
| "", "", "", null); | |||
| Thing thing = new Thing(id, tmd); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| } | |||
| extractThingByFamily(things, doc, eElement); | |||
| // because of our input, there shouldn't be more than one family in the result | |||
| // but do not iterate over items just to make sure | |||
| @@ -315,35 +263,7 @@ public class BggApi { | |||
| } | |||
| // for geeklist result | |||
| else if(root.getTagName() == "geeklist") { | |||
| StringBuilder gInfo = new StringBuilder(); | |||
| NodeList nListTitle = doc.getElementsByTagName("title"); | |||
| if(nListTitle.getLength() > 0) { | |||
| gInfo.append(nListTitle.item(0).getTextContent() + "\r\n"); | |||
| } | |||
| NodeList nListDesc = doc.getElementsByTagName("description"); | |||
| if(nListDesc.getLength() > 0) { | |||
| gInfo.append(nListDesc.item(0).getTextContent()); | |||
| } | |||
| eventBroker.send(EventConstants.TOPIC_GEEKLIST_INFO, gInfo.toString()); | |||
| NodeList nList = doc.getElementsByTagName("item"); | |||
| for(int i = 0; i < nList.getLength(); i++) { | |||
| Node nNode = nList.item(i); | |||
| if (nNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element eElement = (Element) nNode; | |||
| Integer id = Integer.parseInt(eElement.getAttribute("objectid")); | |||
| if(id != 0) { | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| eElement.getAttribute("objectname"), | |||
| "", "", "", null); | |||
| Thing thing = new Thing(id, tmd); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| } | |||
| extractThingByGeeklist(things, doc); | |||
| } | |||
| return things; | |||
| @@ -361,7 +281,299 @@ public class BggApi { | |||
| return null; | |||
| } | |||
| private void extractThingByGeeklist(ArrayList<Thing> things, Document doc) { | |||
| StringBuilder gInfo = new StringBuilder(); | |||
| NodeList nListTitle = doc.getElementsByTagName("title"); | |||
| if(nListTitle.getLength() > 0) { | |||
| gInfo.append(nListTitle.item(0).getTextContent() + "\r\n"); | |||
| } | |||
| NodeList nListDesc = doc.getElementsByTagName("description"); | |||
| if(nListDesc.getLength() > 0) { | |||
| gInfo.append(nListDesc.item(0).getTextContent()); | |||
| } | |||
| eventBroker.send(EventConstants.TOPIC_GEEKLIST_INFO, gInfo.toString()); | |||
| NodeList nList = doc.getElementsByTagName("item"); | |||
| for(int i = 0; i < nList.getLength(); i++) { | |||
| Node nNode = nList.item(i); | |||
| if (nNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element eElement = (Element) nNode; | |||
| Integer id = Integer.parseInt(eElement.getAttribute("objectid")); | |||
| if(id != 0) { | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| eElement.getAttribute("objectname"), | |||
| "", ""); | |||
| Thing thing = new Thing(id, tmd); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private void extractThingByFamily(ArrayList<Thing> things, Document doc, Element eElement) { | |||
| // get name and description | |||
| StringBuilder fInfo = new StringBuilder(); | |||
| NodeList nListName = eElement.getElementsByTagName("name"); | |||
| if(nListName.getLength() > 0) { | |||
| fInfo.append(nListName.item(0).getTextContent() + "\r\n"); | |||
| } | |||
| NodeList nListDesc = doc.getElementsByTagName("description"); | |||
| if(nListDesc.getLength() > 0) { | |||
| fInfo.append(nListDesc.item(0).getTextContent()); | |||
| } | |||
| eventBroker.send(EventConstants.TOPIC_FAMILY_INFO, fInfo.toString()); | |||
| NodeList nLinks = eElement.getElementsByTagName("link"); | |||
| for(int l = 0; l < nLinks.getLength(); l++) { | |||
| Node link = nLinks.item(l); | |||
| if (link.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element eLink = (Element) link; | |||
| Integer id = Integer.parseInt(eLink.getAttribute("id")); | |||
| if(id != 0) { | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| eLink.getAttribute("value"), | |||
| "", ""); | |||
| Thing thing = new Thing(id, tmd); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private void extractThingsById(ArrayList<Thing> things, Node nNode, Element eElement) { | |||
| Integer id = Integer.parseInt(eElement.getAttribute("id")); | |||
| if(id != 0) { | |||
| String name = ""; | |||
| NodeList nameList = eElement.getElementsByTagName("name"); | |||
| for(int n = 0; n < nameList.getLength(); n++) { | |||
| Node nameNode = nameList.item(n); | |||
| if (nNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element nameElement = (Element) nameNode; | |||
| if(nameElement.hasAttribute("type") | |||
| && nameElement.getAttribute("type").equals("primary")) | |||
| { | |||
| name = nameElement.getAttribute("value"); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| name, | |||
| getValue(eElement, "image"), | |||
| getValue(eElement, "thumbnail")); | |||
| System.out.println("DEBUG: Details for " + id); | |||
| ThingDetails details = new ThingDetails(); | |||
| details.yearpublished = getIntegerFromString(getValueAttribute(eElement, "yearpublished")); | |||
| details.minplayers = getIntegerFromString(getValueAttribute(eElement, "minplayers")); | |||
| details.maxplayers = getIntegerFromString(getValueAttribute(eElement, "maxplayers")); | |||
| details.playingtime = getIntegerFromString(getValueAttribute(eElement, "playingtime")); | |||
| details.minplaytime = getIntegerFromString(getValueAttribute(eElement, "minplaytime")); | |||
| details.maxplaytime = getIntegerFromString(getValueAttribute(eElement, "maxplaytime")); | |||
| details.age = getIntegerFromString(getValueAttribute(eElement, "minage")); | |||
| // number of players recommendations | |||
| // Only saving up to 20 players | |||
| NodeList pollList = eElement.getElementsByTagName("poll"); | |||
| for(int n = 0; n < pollList.getLength(); n++) { | |||
| Node pollNode = pollList.item(n); | |||
| if (pollNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element pollElement = (Element) pollNode; | |||
| if(pollElement.hasAttribute("name")) { | |||
| String pollType = pollElement.getAttribute("name"); | |||
| if(pollType.equals("suggested_numplayers")) { | |||
| for(int p = 0; p < 20; ++p) { | |||
| if(p+1 < details.minplayers || p+1 > details.maxplayers) { | |||
| details.players.add(Recommendation.N); | |||
| } else { | |||
| details.players.add(getMajorityRecommendation(pollElement, p+1)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } // other polls | |||
| } | |||
| NodeList linkList = eElement.getElementsByTagName("link"); | |||
| for(int n = 0; n < linkList.getLength(); n++) { | |||
| Node linkNode = linkList.item(n); | |||
| if (linkNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element linkElement = (Element) linkNode; | |||
| if(linkElement.hasAttribute("type")) { | |||
| String type = linkElement.getAttribute("type"); | |||
| switch(type) { | |||
| case "boardgamecategory": | |||
| details.category.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgamemechanic": | |||
| details.mechanic.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgamefamily": | |||
| details.family.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgamedesigner": | |||
| details.designer.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgameartist": | |||
| details.artist.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgamepublisher": | |||
| details.publisher.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgameexpansion": | |||
| details.expansion.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| case "boardgamedomain": | |||
| details.domain.add(extractLinkFromElement(linkElement)); | |||
| break; | |||
| default: | |||
| System.out.println("WARN: ignoring link element: " + type); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| Thing thing = new Thing(id, tmd); | |||
| thing.setDetails(details); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| private IdString extractLinkFromElement(Element linkElement) { | |||
| if(linkElement.hasAttribute("id") && linkElement.hasAttribute("value")) { | |||
| return new IdString(Integer.valueOf(linkElement.getAttribute("id")), linkElement.getAttribute("value")); | |||
| } | |||
| System.out.println("WARN: Link is missing attributes."); | |||
| return null; | |||
| } | |||
| private Recommendation getMajorityRecommendation(Element pollElement, int i) { | |||
| Recommendation recommendation = null; | |||
| NodeList nodeList = pollElement.getElementsByTagName("results"); | |||
| for(int n = 0; n < nodeList.getLength(); ++n) { | |||
| Element elem = (Element)nodeList.item(n); | |||
| if(elem.hasAttribute("numplayers")) { | |||
| String attr = elem.getAttribute("numplayers"); | |||
| boolean numPlayersDoesMatch = false; | |||
| // numplayers can be X+ where X is the max number of players... | |||
| if(attr.endsWith("+")) { | |||
| attr = attr.substring(0, attr.length()-1); | |||
| if(Integer.valueOf(attr) <= i) { | |||
| numPlayersDoesMatch = true; | |||
| } | |||
| } else { | |||
| numPlayersDoesMatch = Integer.valueOf(attr) == i; | |||
| } | |||
| if(numPlayersDoesMatch) { | |||
| int lastvotes = 0; | |||
| NodeList results = elem.getElementsByTagName("result"); | |||
| for(int r = 0; r < results.getLength(); ++r) { | |||
| Element result = (Element)results.item(r); | |||
| if(result.hasAttribute("value") && result.hasAttribute("numvotes")) { | |||
| Integer numvotes = Integer.valueOf(result.getAttribute("numvotes")); | |||
| if(numvotes > lastvotes) { | |||
| recommendation = recommendationValueToEnum(result.getAttribute("value")); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return recommendation; | |||
| } | |||
| private Recommendation recommendationValueToEnum(String attribute) { | |||
| switch(attribute) { | |||
| case "Best": | |||
| return Recommendation.B; | |||
| case "Recommended": | |||
| return Recommendation.R; | |||
| case "Not Recommended": | |||
| return Recommendation.P; | |||
| default: | |||
| return Recommendation.N; | |||
| } | |||
| } | |||
| private void extractThingByUser(ArrayList<Thing> things, Element eElement) { | |||
| Integer id = Integer.parseInt(eElement.getAttribute("objectid")); | |||
| if(id != 0) { | |||
| ThingMetaData tmd = new ThingMetaData( | |||
| id, | |||
| getValue(eElement, "name"), | |||
| getValue(eElement, "image"), | |||
| getValue(eElement, "thumbnail") | |||
| ); | |||
| ThingUserData tud = new ThingUserData(); | |||
| tud.setNumPlays(Integer.valueOf(getValue(eElement, "numplays"))); | |||
| tud.setComment(getValue(eElement, "comment")); | |||
| // rating | |||
| NodeList statsNodes = eElement.getElementsByTagName("stats"); | |||
| if(statsNodes.getLength() > 0) { | |||
| Node statsNode = statsNodes.item(0); | |||
| NodeList statsChildren = statsNode.getChildNodes(); | |||
| if(statsChildren.getLength() > 0) { | |||
| Element ratingNode = (Element)statsChildren.item(0); | |||
| String ratingValue = ratingNode.getAttribute("value"); | |||
| if(!ratingValue.equals("N/A")) { | |||
| try { | |||
| Float rating = Float.valueOf(ratingValue); | |||
| tud.setRating(rating); | |||
| } | |||
| catch(NumberFormatException e) { | |||
| System.out.println("WARN: rating value is not a float."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| NodeList statusNodes = eElement.getElementsByTagName("status"); | |||
| if(statusNodes.getLength() > 0) { | |||
| Element statusNode = (Element)statusNodes.item(0); | |||
| tud.setOwn(attributeToBoolean(statusNode, "own")); | |||
| tud.setPrevowned(attributeToBoolean(statusNode, "prevowned")); | |||
| tud.setFortrade(attributeToBoolean(statusNode, "fortrade")); | |||
| tud.setWant(attributeToBoolean(statusNode, "want")); | |||
| tud.setWanttoplay(attributeToBoolean(statusNode, "wanttoplay")); | |||
| tud.setWanttobuy(attributeToBoolean(statusNode, "wanttobuy")); | |||
| tud.setWishlist(attributeToBoolean(statusNode, "wishlist")); | |||
| if(statusNode.hasAttribute("wishlistpriority")) { | |||
| tud.setWishlistpriority(Integer.valueOf(statusNode.getAttribute("wishlistpriority"))); | |||
| } | |||
| tud.setPreordered(attributeToBoolean(statusNode, "preordered")); | |||
| tud.setLastmodified(statusNode.getAttribute("lastmodified")); | |||
| } | |||
| Thing thing = new Thing(id, tmd); | |||
| thing.setUserData(tud); | |||
| things.add(thing); | |||
| } | |||
| } | |||
| private Boolean attributeToBoolean(Element statusNode, String attribute) { | |||
| if(statusNode.hasAttribute(attribute)) { | |||
| return statusNode.getAttribute(attribute).equals("0") ? false : true; | |||
| } | |||
| return null; | |||
| } | |||
| private void checkForErrors(Document doc) throws IllegalArgumentException { | |||
| NodeList nList = doc.getElementsByTagName("error"); | |||
| if(nList.getLength() > 0) { | |||
| @@ -374,6 +586,12 @@ public class BggApi { | |||
| } | |||
| } | |||
| private Integer getIntegerFromString(String s) { | |||
| if(s != null && !s.isEmpty()) { | |||
| return Integer.valueOf(s); | |||
| } | |||
| return null; | |||
| } | |||
| private String getValue(Element eElement, String key) { | |||
| Node node = eElement.getElementsByTagName(key).item(0); | |||
| @@ -384,5 +602,15 @@ public class BggApi { | |||
| } | |||
| } | |||
| private String getValueAttribute(Element eElement, String key) { | |||
| Node node = (Element)eElement.getElementsByTagName(key).item(0); | |||
| if (node.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element elem = (Element) node; | |||
| if(elem.hasAttribute("value")) { | |||
| return elem.getAttribute("value"); | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| package xyz.veronie.bgg.result; | |||
| /// Holds an id and its string representation, for example for Family, Extension, Mechanic, or Category. | |||
| public class IdString { | |||
| public int id; | |||
| public String string; | |||
| public IdString(int id, String string) { | |||
| this.id = id; | |||
| this.string = string; | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| package xyz.veronie.bgg.result; | |||
| public enum Recommendation { | |||
| N, // (N)onplayable | |||
| P, // (P)layable, not recommended | |||
| R, // (R)ecommended | |||
| B // (B)est with... | |||
| } | |||
| @@ -14,16 +14,19 @@ import org.eclipse.swt.graphics.Image; | |||
| import org.eclipse.swt.graphics.ImageData; | |||
| import org.eclipse.swt.graphics.ImageLoader; | |||
| import xyz.veronie.bgg.result.internal.OutputResultHelper; | |||
| import xyz.veronie.bgg.ui.helpers.Resources; | |||
| public class Thing { | |||
| private int id; | |||
| private ThingMetaData metaData; | |||
| private ThingUserData userData; | |||
| private ThingDetails details; | |||
| // cache | |||
| private Image thumbImage; | |||
| private Path imagePath; | |||
| public static final String IdHeader = "ID"; | |||
| public static final String ThumbHeader = "Thumbnail"; | |||
| @@ -49,9 +52,19 @@ public class Thing { | |||
| public void setMetaData(ThingMetaData metaData) { | |||
| this.metaData = metaData; | |||
| } | |||
| public void setUserData(ThingUserData userData) { | |||
| this.userData = userData; | |||
| } | |||
| public ThingUserData getUserData() { | |||
| return userData; | |||
| } | |||
| public ThingDetails getDetails() { | |||
| return details; | |||
| } | |||
| public void setDetails(ThingDetails details) { | |||
| this.details = details; | |||
| } | |||
| @@ -63,14 +76,22 @@ public class Thing { | |||
| return thumbImage; | |||
| } | |||
| public String getImagePath() { | |||
| if(imagePath != null) | |||
| return imagePath.toString(); | |||
| else | |||
| return Paths.get(Resources.INSTANCE.getThumbsDir().toString() | |||
| + File.separator + String.valueOf(id) + ".png").toString(); | |||
| } | |||
| private void getThumbImage(int thingId) { | |||
| Path tmpDir = Resources.INSTANCE.getTmpDir(); | |||
| if(tmpDir != null) { | |||
| Path imageFile = Paths.get(Resources.INSTANCE.getThumbsDir().toString() | |||
| imagePath = Paths.get(Resources.INSTANCE.getThumbsDir().toString() | |||
| + File.separator + String.valueOf(thingId) + ".png"); | |||
| if(Files.exists(imageFile, LinkOption.NOFOLLOW_LINKS)) { | |||
| String filename = imageFile.toString().replace("\\","/"); | |||
| if(Files.exists(imagePath, LinkOption.NOFOLLOW_LINKS)) { | |||
| String filename = imagePath.toString().replace("\\","/"); | |||
| thumbImage = Resources.INSTANCE.getResourceManager().createImage( | |||
| ImageDescriptor.createFromFile(null, filename)); | |||
| } else { | |||
| @@ -81,7 +102,7 @@ public class Thing { | |||
| ImageLoader saver = new ImageLoader(); | |||
| saver.data = new ImageData[] { thumbImage.getImageData() }; | |||
| saver.save(imageFile.toString(), SWT.IMAGE_PNG); | |||
| saver.save(imagePath.toString(), SWT.IMAGE_PNG); | |||
| } catch (MalformedURLException e) { | |||
| System.out.println("INFO: Malformed URL for ThingId " + thingId); | |||
| } | |||
| @@ -130,4 +151,60 @@ public class Thing { | |||
| } | |||
| } | |||
| private static String resultHeader() { | |||
| String header = "id,name,image,"; | |||
| return header; | |||
| } | |||
| public static String makeResultHeader() { | |||
| String header = Thing.resultHeader() + ThingUserData.resultHeader() + ThingDetails.resultHeader(); | |||
| return header; | |||
| } | |||
| /// convert the thing into a comma-separated line for a result.txt file | |||
| /** | |||
| * The format is (without line breaks): | |||
| * id,name,designer, | |||
| * | |||
| * owned,trading,wanting,wishing,userrating,comment,numplays,wishpriority | |||
| * | |||
| * designer,publisher,artist,yearpublished,minplayers,maxplayers,playingtime,minplaytime,maxplaytime, | |||
| * age,usersrated,average,bayesaverage,rank,rank_wg,numcomments,numweights,averageweight,stddev,median, | |||
| * category,mechanic, | |||
| * 1player,2player,3player,4player,5player,6player,7player,8player,9player,10player, | |||
| * 11player,12player,13player,14player,15player,16player,17player,18player,19player,20player, | |||
| * description,exp,basegame,reimplement,reimplement_name,reimplemented,reimplemented_name, | |||
| * contains,contains_name,iscontained,iscontained_name,integration,integration_name,price, | |||
| * expansions,domain,family,age_poll | |||
| * | |||
| * @return | |||
| */ | |||
| // TODO: rewrite: order isn't important, column names are | |||
| public String toResultTxtLine() { | |||
| StringBuilder str = new StringBuilder(); | |||
| // id,name,image, | |||
| OutputResultHelper.appendToResult(str, id); | |||
| OutputResultHelper.appendToResult(str, metaData.getName()); | |||
| OutputResultHelper.appendToResult(str, getImagePath()); | |||
| if(userData != null) { | |||
| userData.appendToResult(str); | |||
| } else { | |||
| str.append(ThingUserData.emptyReplacerLine()); | |||
| } | |||
| if(details != null) { | |||
| str.append(details.toResultTextLine()); | |||
| } else { | |||
| str.append(ThingDetails.emptyReplacerLine()); | |||
| } | |||
| return str.toString(); | |||
| } | |||
| } | |||
| @@ -1,17 +1,44 @@ | |||
| package xyz.veronie.bgg.result; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import xyz.veronie.bgg.result.internal.OutputResultHelper; | |||
| public class ThingDetails { | |||
| Integer id; | |||
| String name; | |||
| String designer; | |||
| String publisher; | |||
| String artist; | |||
| String description; | |||
| String image; | |||
| String comment; | |||
| Integer yearpublished; | |||
| Integer minplayers; | |||
| Integer maxplayers; | |||
| List<IdString> designer; | |||
| List<IdString> publisher; | |||
| List<IdString> artist; | |||
| List<IdString> category; | |||
| List<IdString> mechanic; | |||
| List<IdString> expansion; | |||
| List<IdString> domain; | |||
| List<IdString> family; | |||
| Integer playingtime; | |||
| Integer minplaytime; | |||
| Integer maxplaytime; | |||
| // poll suggested_numplayers | |||
| // The index in the list indicates the number of players | |||
| // Recommendation indicates how well it plays based on what the majority thinks | |||
| List<Recommendation> players; | |||
| // poll suggested_playerage | |||
| Float age_poll; | |||
| Integer age; | |||
| Integer usersrated; | |||
| Integer average; | |||
| @@ -23,35 +50,127 @@ public class ThingDetails { | |||
| Float averageweight; | |||
| Float stddev; | |||
| Float median; | |||
| Boolean owned; | |||
| Boolean trading; | |||
| Boolean wanting; | |||
| Boolean wishing; | |||
| Float userrating; | |||
| String image; | |||
| Integer category; | |||
| Integer mechanic; | |||
| String comment; | |||
| Integer[] players; // 1 to 20 | |||
| String description; | |||
| // exp, | |||
| Integer basegameId; | |||
| Integer reimplementId; | |||
| String reimplement_name; | |||
| Integer reimplementedById; | |||
| String reimplementedByName; | |||
| Integer containsId; | |||
| String containsName; | |||
| Integer iscontained; | |||
| String iscontained_name; | |||
| Integer integration; | |||
| String integration_name; | |||
| Integer owning; | |||
| Integer trading; | |||
| Integer wanting; | |||
| Integer wishing; | |||
| // Integer basegameId; | |||
| // Integer reimplementId; | |||
| // String reimplement_name; | |||
| // Integer reimplementedById; | |||
| // String reimplementedByName; | |||
| // Integer containsId; | |||
| // String containsName; | |||
| // Integer iscontained; | |||
| // String iscontained_name; | |||
| // Integer integration; | |||
| // String integration_name; | |||
| Integer numplays; | |||
| Float price; | |||
| Float userweight; | |||
| Integer wishpriority; | |||
| Integer expansions; | |||
| String domain; | |||
| String family; | |||
| Float age_poll; | |||
| public ThingDetails() { | |||
| players = new ArrayList<Recommendation>(); | |||
| designer = new ArrayList<IdString>(); | |||
| publisher = new ArrayList<IdString>(); | |||
| artist = new ArrayList<IdString>(); | |||
| category = new ArrayList<IdString>(); | |||
| mechanic = new ArrayList<IdString>(); | |||
| expansion = new ArrayList<IdString>(); | |||
| domain = new ArrayList<IdString>(); | |||
| family = new ArrayList<IdString>(); | |||
| } | |||
| public String toResultTextLine() { | |||
| StringBuilder str = new StringBuilder(); | |||
| // designer,publisher,artist,yearpublished,minplayers,maxplayers,playingtime,minplaytime,maxplaytime, | |||
| // age,usersrated,average,bayesaverage,rank,rank_wg,numcomments,numweights,averageweight,stddev,median, | |||
| // category,mechanic, | |||
| OutputResultHelper.appendToResult(str, OutputResultHelper.getFirstIdListItem(designer)); | |||
| OutputResultHelper.appendToResult(str, OutputResultHelper.getFirstIdListItem(publisher)); | |||
| OutputResultHelper.appendToResult(str, OutputResultHelper.getFirstIdListItem(artist)); | |||
| OutputResultHelper.appendToResult(str, yearpublished); | |||
| OutputResultHelper.appendToResult(str, minplayers); | |||
| OutputResultHelper.appendToResult(str, maxplayers); | |||
| OutputResultHelper.appendToResult(str, playingtime); | |||
| OutputResultHelper.appendToResult(str, minplaytime); | |||
| OutputResultHelper.appendToResult(str, maxplaytime); | |||
| OutputResultHelper.appendToResult(str, age); | |||
| OutputResultHelper.appendToResult(str, usersrated); | |||
| OutputResultHelper.appendToResult(str, average); | |||
| OutputResultHelper.appendToResult(str, bayesaverage); | |||
| OutputResultHelper.appendToResult(str, rank); | |||
| OutputResultHelper.appendToResult(str, rank_wg); | |||
| OutputResultHelper.appendToResult(str, numcomments); | |||
| OutputResultHelper.appendToResult(str, numweights); | |||
| OutputResultHelper.appendToResult(str, averageweight); | |||
| OutputResultHelper.appendToResult(str, stddev); | |||
| OutputResultHelper.appendToResult(str, median); | |||
| OutputResultHelper.appendToResult(str, category); | |||
| OutputResultHelper.appendToResult(str, mechanic); | |||
| // owned,trading,wanting,wishing | |||
| OutputResultHelper.appendToResult(str, owning); | |||
| OutputResultHelper.appendToResult(str, trading); | |||
| OutputResultHelper.appendToResult(str, wanting); | |||
| OutputResultHelper.appendToResult(str, wishing); | |||
| // 1player,2player,3player,4player,5player,6player,7player,8player,9player,10player, | |||
| // 11player,12player,13player,14player,15player,16player,17player,18player,19player,20player, | |||
| for(int i = 0; i < players.size(); ++i) { | |||
| Recommendation r = players.get(i); | |||
| if(r != null) { | |||
| str.append(r.name()); | |||
| } | |||
| str.append(","); | |||
| } | |||
| // description,exp, | |||
| OutputResultHelper.appendToResult(str, description); | |||
| OutputResultHelper.appendToResult(str, expansion); | |||
| // basegame,reimplement,reimplement_name,reimplemented,reimplemented_name, | |||
| // contains,contains_name,iscontained,iscontained_name,integration,integration_name, | |||
| // TODO: | |||
| // str.append(basegameId).append(","); | |||
| // str.append(reimplementId).append(","); | |||
| // str.append(reimplement_name).append(","); | |||
| // str.append(reimplementedById).append(","); | |||
| // str.append(reimplementedByName).append(","); | |||
| // str.append(containsId).append(","); | |||
| // str.append(containsName).append(","); | |||
| // str.append(iscontained).append(","); | |||
| // str.append(iscontained_name).append(","); | |||
| // str.append(integration).append(","); | |||
| // str.append(integration_name).append(","); | |||
| // str.append("0,,\"\",,\"\",,\"\",,\"\",,\"\""); | |||
| // price,expansions,domain,family,age_poll | |||
| OutputResultHelper.appendToResult(str, price); | |||
| OutputResultHelper.appendToResult(str, expansions); | |||
| OutputResultHelper.appendToResult(str, domain); | |||
| OutputResultHelper.appendToResult(str, family); | |||
| str.append(OutputResultHelper.floatToResult(age_poll)); | |||
| return str.toString(); | |||
| } | |||
| public static String emptyReplacerLine() { | |||
| return ",,,,,,,,,,,0.0,0.0,,,0,0,0.0,0.0,0.0,\"\",\"\",,,,,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,\"\",\"\",0.0,,\"\",\"\",0.0"; | |||
| } | |||
| public static String resultHeader() { | |||
| return "designer,publisher,artist,yearpublished,minplayers,maxplayers,playingtime,minplaytime,maxplaytime,age,usersrated,average,bayesaverage,rank,rank_wg,numcomments,numweights,averageweight,stddev,median,category,mechanic,owned,trading,wanting,wishing,1player,2player,3player,4player,5player,6player,7player,8player,9player,10player,11player,12player,13player,14player,15player,16player,17player,18player,19player,20player,description,exp,price,expansions,domain,family,age_poll"; | |||
| // not doing: basegame,reimplement,reimplement_name,reimplemented,reimplemented_name,contains,contains_name,iscontained,iscontained_name,integration,integration_name, | |||
| } | |||
| } | |||
| @@ -1,74 +0,0 @@ | |||
| package xyz.veronie.bgg.result; | |||
| import java.awt.Label; | |||
| import javax.annotation.PostConstruct; | |||
| import org.eclipse.swt.SWT; | |||
| import org.eclipse.swt.layout.GridData; | |||
| import org.eclipse.swt.layout.GridLayout; | |||
| import org.eclipse.swt.widgets.Composite; | |||
| public class ThingDetailsComposite extends Composite { | |||
| ThingDetails thingDetails; | |||
| private Label nameField; | |||
| private Label designerField; | |||
| private Label publisherField; | |||
| private Label yearField; | |||
| public ThingDetailsComposite(Composite parent, int style) { | |||
| super(parent, style); | |||
| } | |||
| @PostConstruct | |||
| public void create() { | |||
| setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); | |||
| GridLayout layout = new GridLayout(2, false); | |||
| setLayout(layout); | |||
| Label nameLbl = new Label("Name"); | |||
| applyLayout(nameLbl); | |||
| nameField = new Label(""); | |||
| Label designerLbl = new Label("Designer"); | |||
| applyLayout(designerLbl); | |||
| designerField = new Label(""); | |||
| Label publisherLbl = new Label("Publisher"); | |||
| applyLayout(publisherLbl); | |||
| publisherField = new Label(""); | |||
| Label yearLbl = new Label("Publisher"); | |||
| applyLayout(yearLbl); | |||
| yearField = new Label(""); | |||
| this.getParent().layout(); | |||
| } | |||
| private void applyLayout(Label label) { | |||
| label.setAlignment(SWT.RIGHT); | |||
| } | |||
| public void selectedThingChanged(Thing thing) { | |||
| System.out.println("TOPIC_THING_SELECTION: " + thing); | |||
| thingDetails = thing.getDetails(); | |||
| if(thingDetails != null) { | |||
| nameField.setText(thingDetails.name); | |||
| designerField.setText(thingDetails.designer); | |||
| publisherField.setText(thingDetails.publisher); | |||
| yearField.setText(Integer.toString(thingDetails.yearpublished)); | |||
| } else { | |||
| nameField.setText(""); | |||
| designerField.setText(""); | |||
| publisherField.setText(""); | |||
| yearField.setText(""); | |||
| } | |||
| this.getParent().layout(); | |||
| } | |||
| } | |||
| @@ -2,7 +2,6 @@ package xyz.veronie.bgg.result; | |||
| import java.beans.PropertyChangeListener; | |||
| import java.beans.PropertyChangeSupport; | |||
| //import com.google.gson.Gson; | |||
| public class ThingMetaData implements java.io.Serializable { | |||
| private static final long serialVersionUID = -5268898737006538509L; | |||
| @@ -11,21 +10,15 @@ public class ThingMetaData implements java.io.Serializable { | |||
| private String name; | |||
| private String imgURL; | |||
| private String thumbURL; | |||
| private String comment; | |||
| private Integer numPlays; | |||
| private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); | |||
| public ThingMetaData(int id, String name, | |||
| String imgURL, String thumURL, | |||
| String comment, Integer numPlays) { | |||
| String imgURL, String thumURL) { | |||
| this.setId(id); | |||
| this.setName(name); | |||
| this.setImgURL(imgURL); | |||
| this.setThumbURL(thumURL); | |||
| this.setComment(comment); | |||
| this.setNumPlays(numPlays); | |||
| } | |||
| @@ -78,29 +71,9 @@ public class ThingMetaData implements java.io.Serializable { | |||
| this.thumbURL = thumbURL); | |||
| } | |||
| public Integer getNumPlays() { | |||
| return numPlays; | |||
| } | |||
| public void setNumPlays(Integer numPlays) { | |||
| this.numPlays = numPlays; | |||
| } | |||
| public String getComment() { | |||
| return comment; | |||
| } | |||
| public void setComment(String comment) { | |||
| propertyChangeSupport.firePropertyChange("comment", this.comment, | |||
| this.comment = comment); | |||
| } | |||
| @Override | |||
| public String toString() { | |||
| return String.valueOf(id); | |||
| // Gson gson = new Gson(); | |||
| // return gson.toJson(this); | |||
| } | |||
| @@ -2,10 +2,13 @@ package xyz.veronie.bgg.result; | |||
| import java.sql.SQLException; | |||
| import java.util.ArrayList; | |||
| import java.util.HashSet; | |||
| import java.util.List; | |||
| import java.util.Set; | |||
| import java.util.function.Predicate; | |||
| import javax.annotation.PostConstruct; | |||
| import javax.inject.Inject; | |||
| import javax.inject.Singleton; | |||
| import org.eclipse.e4.core.di.annotations.Creatable; | |||
| @@ -15,6 +18,10 @@ import xyz.veronie.bgg.localdb.LocalDbAdapterService; | |||
| @Creatable | |||
| @Singleton | |||
| public class ThingProvider { | |||
| @Inject | |||
| private BggApi bggApi; | |||
| private LocalDbAdapterService localDbAdapterService; | |||
| /// list of things. Each ID is expected to exist exactly once. | |||
| @@ -118,5 +125,21 @@ public class ThingProvider { | |||
| return localDbAdapterService.loadThingListNames(); | |||
| } | |||
| public void fetchDetails() { | |||
| // prepare list of ids to retrieve | |||
| Set<Integer> ids = new HashSet<>(); | |||
| for (Thing thing : things) { | |||
| if(thing.getDetails() == null) { | |||
| ids.add(thing.getId()); | |||
| } | |||
| } | |||
| System.out.println(Thing.makeResultHeader()); | |||
| ArrayList<Thing> thingsWithDetails = bggApi.getThingDetails(ids); | |||
| for (Thing thing : thingsWithDetails) { | |||
| System.out.println(thing.toResultTxtLine()); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,157 @@ | |||
| package xyz.veronie.bgg.result; | |||
| import xyz.veronie.bgg.result.internal.OutputResultHelper; | |||
| public class ThingUserData { | |||
| private Integer numplays; | |||
| private String comment; | |||
| private Float rating; | |||
| private Boolean own; | |||
| private Boolean prevowned; | |||
| private Boolean fortrade; | |||
| private Boolean want; | |||
| private Boolean wanttoplay; | |||
| private Boolean wanttobuy; | |||
| private Boolean wishlist; | |||
| private Integer wishlistpriority; | |||
| private Boolean preordered; | |||
| private String lastmodified; | |||
| //private Float weight; | |||
| public Integer getNumPlays() { | |||
| return numplays; | |||
| } | |||
| public void setNumPlays(Integer numPlays) { | |||
| this.numplays = numPlays; | |||
| } | |||
| public String getComment() { | |||
| return comment; | |||
| } | |||
| public void setComment(String comment) { | |||
| this.comment = comment; | |||
| } | |||
| public Float getRating() { | |||
| return rating; | |||
| } | |||
| public void setRating(Float rating) { | |||
| this.rating = rating; | |||
| } | |||
| public Boolean getOwn() { | |||
| return own; | |||
| } | |||
| public void setOwn(Boolean own) { | |||
| this.own = own; | |||
| } | |||
| public Boolean getPrevowned() { | |||
| return prevowned; | |||
| } | |||
| public void setPrevowned(Boolean prevowned) { | |||
| this.prevowned = prevowned; | |||
| } | |||
| public Boolean getFortrade() { | |||
| return fortrade; | |||
| } | |||
| public void setFortrade(Boolean fortrade) { | |||
| this.fortrade = fortrade; | |||
| } | |||
| public Boolean getWant() { | |||
| return want; | |||
| } | |||
| public void setWant(Boolean want) { | |||
| this.want = want; | |||
| } | |||
| public Boolean getWanttoplay() { | |||
| return wanttoplay; | |||
| } | |||
| public void setWanttoplay(Boolean wanttoplay) { | |||
| this.wanttoplay = wanttoplay; | |||
| } | |||
| public Boolean getWanttobuy() { | |||
| return wanttobuy; | |||
| } | |||
| public void setWanttobuy(Boolean wanttobuy) { | |||
| this.wanttobuy = wanttobuy; | |||
| } | |||
| public Boolean getWishlist() { | |||
| return wishlist; | |||
| } | |||
| public void setWishlist(Boolean wishlist) { | |||
| this.wishlist = wishlist; | |||
| } | |||
| public Integer getWishlistpriority() { | |||
| return wishlistpriority; | |||
| } | |||
| public void setWishlistpriority(Integer wishlistpriority) { | |||
| this.wishlistpriority = wishlistpriority; | |||
| } | |||
| public Boolean getPreordered() { | |||
| return preordered; | |||
| } | |||
| public void setPreordered(Boolean preordered) { | |||
| this.preordered = preordered; | |||
| } | |||
| public String getLastmodified() { | |||
| return lastmodified; | |||
| } | |||
| public void setLastmodified(String lastmodified) { | |||
| this.lastmodified = lastmodified; | |||
| } | |||
| public void appendToResult(StringBuilder str) { | |||
| OutputResultHelper.appendToResult(str, getRating()); | |||
| OutputResultHelper.appendToResult(str, getComment()); | |||
| OutputResultHelper.appendToResult(str, getNumPlays()); | |||
| // TODO: find out how to get userweight... | |||
| } | |||
| public String toString() { | |||
| StringBuilder str = new StringBuilder(); | |||
| appendToResult(str); | |||
| return str.toString(); | |||
| } | |||
| public static String emptyReplacerLine() { | |||
| return "N/A,\"\",0,"; | |||
| } | |||
| public static String resultHeader() { | |||
| return "userrating,comment,numplays,"; | |||
| } | |||
| // public Float getWeight() { | |||
| // return weight; | |||
| // } | |||
| // | |||
| // public void setWeight(Float weight) { | |||
| // this.weight = weight; | |||
| // } | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| package xyz.veronie.bgg.result.internal; | |||
| import java.util.List; | |||
| import xyz.veronie.bgg.result.IdString; | |||
| public class OutputResultHelper { | |||
| public static String floatToResult(Float f) { | |||
| if(f == null) { | |||
| return "N/A"; | |||
| } else { | |||
| return Float.toString(f.floatValue()); | |||
| } | |||
| } | |||
| public static String getFirstIdListItem(List<IdString> list) { | |||
| if(list != null && list.size() > 0) { | |||
| return list.get(0).string; | |||
| } | |||
| return ""; | |||
| } | |||
| public static void appendToResult(StringBuilder str, String string) { | |||
| str.append("\""); | |||
| if(string != null) { | |||
| str.append(string); | |||
| } | |||
| str.append("\","); | |||
| } | |||
| public static void appendToResult(StringBuilder str, Integer i) { | |||
| if(i != null) { | |||
| str.append(Integer.toString(i)); | |||
| } | |||
| str.append(","); | |||
| } | |||
| public static void appendToResult(StringBuilder str, Float f) { | |||
| str.append(OutputResultHelper.floatToResult(f)).append(","); | |||
| } | |||
| public static void appendToResult(StringBuilder str, List<IdString> list) { | |||
| if(list == null) { | |||
| str.append(","); | |||
| return; | |||
| } | |||
| str.append("\""); | |||
| String nanDeckSeparator = ""; | |||
| for (IdString idString : list) { | |||
| str.append(nanDeckSeparator); | |||
| nanDeckSeparator = "\\13\\"; | |||
| str.append(idString.string); | |||
| } | |||
| str.append("\","); | |||
| } | |||
| } | |||
| @@ -106,6 +106,8 @@ public class LoadGameListDialog extends Dialog { | |||
| tableViewer.setInput(thingLists); | |||
| int selection = 0; | |||
| tableViewer.setSelection(new StructuredSelection(tableViewer.getElementAt(selection)), true); | |||
| selectedName = (String)tableViewer.getStructuredSelection().getFirstElement(); | |||
| tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { | |||
| @Override | |||
| @@ -87,7 +87,7 @@ public class BggUserSourceFilter { | |||
| bottomComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); | |||
| Label infoLabel = new Label(bottomComposite, SWT.LEFT); | |||
| infoLabel.setText("Select which flags are used as filter. Filters follow 'AND' rule."); | |||
| infoLabel.setText("Select which flags are used as filter. Filters follow 'AND' rule for each game."); | |||
| GridData gdInfo = new GridData(SWT.FILL, SWT.FILL, true, false); | |||
| gdInfo.horizontalSpan = 2; | |||
| infoLabel.setLayoutData(gdInfo); | |||
| @@ -0,0 +1,41 @@ | |||
| package xyz.veronie.bgg.ui.handlers; | |||
| import org.eclipse.e4.core.di.annotations.Execute; | |||
| import xyz.veronie.bgg.result.BggApi; | |||
| import xyz.veronie.bgg.result.Thing; | |||
| import xyz.veronie.bgg.result.ThingProvider; | |||
| import java.util.ArrayList; | |||
| import java.util.HashSet; | |||
| import java.util.List; | |||
| import java.util.Set; | |||
| import javax.inject.Inject; | |||
| import org.eclipse.e4.core.di.annotations.CanExecute; | |||
| public class ExportResultHandler { | |||
| @Inject | |||
| ThingProvider thingProvider; | |||
| @Inject | |||
| private BggApi bggApi; | |||
| @Execute | |||
| public void execute() { | |||
| thingProvider.fetchDetails(); | |||
| } | |||
| @CanExecute | |||
| public boolean canExecute() { | |||
| return thingProvider != null; | |||
| } | |||
| } | |||
| @@ -148,6 +148,16 @@ public class BatMain { | |||
| btnUndo.setEnabled(false); | |||
| btnExport = new Button(buttonRow, SWT.NONE); | |||
| btnExport.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| public void mouseUp(MouseEvent e) { | |||
| ParameterizedCommand cmd = | |||
| commandService.createCommand("xyz.veronie.bgg.ui.command.export", null); | |||
| if (handlerService.canExecute(cmd)){ | |||
| handlerService.executeHandler(cmd); | |||
| } | |||
| } | |||
| }); | |||
| btnExport.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/export_nandeck_60x60.png")); | |||
| btnExport.setToolTipText("Export for nanDeck"); | |||
| btnExport.setEnabled(false); | |||
| @@ -222,20 +232,7 @@ public class BatMain { | |||
| TableViewerColumn colThumbnail = createTableViewerColumn(Thing.ThumbHeader, 120, 0); | |||
| // colThumbnail.setLabelProvider(new ColumnLabelProvider() { | |||
| // @Override | |||
| // public Image getImage(Object element) { | |||
| // Thing t = (Thing) element; | |||
| // Image img = t.getThumbnail(); | |||
| // return img; | |||
| // } | |||
| // | |||
| // @Override | |||
| // public String getText(Object element) { | |||
| // return ""; | |||
| // } | |||
| // | |||
| // }); | |||
| colThumbnail.setLabelProvider(new OwnerDrawLabelProvider() { | |||
| @Override | |||
| protected void measure(Event event, Object element) { | |||
| @@ -11,12 +11,9 @@ import org.eclipse.swt.layout.GridLayout; | |||
| import org.eclipse.swt.widgets.Composite; | |||
| import xyz.veronie.bgg.result.Thing; | |||
| import xyz.veronie.bgg.result.ThingDetailsComposite; | |||
| import xyz.veronie.bgg.types.EventConstants; | |||
| public class ThingListPart { | |||
| private ThingDetailsComposite thingDetailsComposite; | |||
| @PostConstruct | |||
| public void createControls(Composite parent) { | |||
| Composite main = new Composite(parent, SWT.FILL); | |||
| @@ -24,14 +21,11 @@ public class ThingListPart { | |||
| GridLayout layout = new GridLayout(2, false); | |||
| main.setLayout(layout); | |||
| thingDetailsComposite = new ThingDetailsComposite(main, SWT.BORDER); | |||
| } | |||
| @Inject | |||
| @Optional | |||
| private void selectedThingChanged(@UIEventTopic(EventConstants.TOPIC_THING_SELECTION) Thing thing) { | |||
| thingDetailsComposite.selectedThingChanged(thing); | |||
| } | |||