User rating is now saved in local DB, and loaded when opening local save. Fetching thing details via id now loads ratings and weights from bgg. TODO: join both thing information together and output joined resultpull/21/head
| @@ -15,6 +15,8 @@ | |||
| <windowImages/> | |||
| <splash | |||
| location="xyz.veronie.bgg.ui" /> | |||
| <launcher> | |||
| <win useIco="false"> | |||
| <bmp/> | |||
| @@ -1,12 +1,8 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <classpath> | |||
| <classpathentry exported="true" kind="lib" path="lib/"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> | |||
| <attributes> | |||
| <attribute name="maven.pomderived" value="true"/> | |||
| </attributes> | |||
| </classpathentry> | |||
| <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> | |||
| <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/> | |||
| <classpathentry kind="src" path="src"/> | |||
| <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> | |||
| <attributes> | |||
| @@ -1,27 +1,23 @@ | |||
| Manifest-Version: 1.0 | |||
| Bundle-ManifestVersion: 2 | |||
| Bundle-Name: Secondtry | |||
| Bundle-Name: Bgg Tool Khaki Flavor | |||
| Bundle-SymbolicName: xyz.veronie.bgg.ui;singleton:=true | |||
| Bundle-Version: 1.0.0.qualifier | |||
| Bundle-ClassPath: lib/sqlite-jdbc-3.34.0.jar, | |||
| swing2swt.jar | |||
| Require-Bundle: org.eclipse.core.runtime, | |||
| org.eclipse.swt, | |||
| Require-Bundle: javax.inject, | |||
| javax.annotation, | |||
| org.eclipse.core.runtime, | |||
| org.eclipse.e4.core.services, | |||
| org.eclipse.e4.core.di, | |||
| org.eclipse.e4.ui.workbench, | |||
| org.eclipse.e4.ui.di, | |||
| org.eclipse.e4.core.di.extensions, | |||
| javax.annotation, | |||
| org.eclipse.jface, | |||
| org.eclipse.e4.core.services, | |||
| org.eclipse.osgi.services, | |||
| javax.inject, | |||
| org.eclipse.e4.ui.model.workbench | |||
| Bundle-RequiredExecutionEnvironment: JavaSE-1.8 | |||
| org.eclipse.e4.ui.model.workbench, | |||
| com.ibm.icu | |||
| Bundle-RequiredExecutionEnvironment: JavaSE-11 | |||
| Import-Package: javax.annotation;version="1.0.0";resolution:=optional, | |||
| javax.inject;version="1.0.0", | |||
| org.eclipse.e4.core.commands, | |||
| org.eclipse.e4.core.contexts;version="1.7.0", | |||
| org.eclipse.e4.ui.model.application.descriptor.basic, | |||
| org.eclipse.e4.core.contexts, | |||
| org.eclipse.e4.ui.model.application.ui.basic | |||
| Automatic-Module-Name: de.wt.secondtry | |||
| @@ -85,7 +85,7 @@ public class SqliteController { | |||
| } | |||
| try { | |||
| Statement stmt = connection.createStatement(); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Thing (ThingId INTEGER PRIMARY KEY, Name, ImgUrl, ThumbUrl, Comment, NumPlays);"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS Thing (ThingId INTEGER PRIMARY KEY, Name, ImgUrl, ThumbUrl, Comment, NumPlays, UserRating);"); | |||
| stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ThingList (ListId INTEGER PRIMARY KEY, Name);"); | |||
| 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));"); | |||
| @@ -207,7 +207,7 @@ public class SqliteController { | |||
| int listId = getThingListId(name); | |||
| PreparedStatement thingStatement = connection | |||
| .prepareStatement("INSERT OR REPLACE INTO Thing VALUES (?, ?, ?, ?, ?, ?);"); | |||
| .prepareStatement("INSERT OR REPLACE INTO Thing VALUES (?, ?, ?, ?, ?, ?, ?);"); | |||
| PreparedStatement listToThingStatement = connection | |||
| .prepareStatement("INSERT OR IGNORE INTO ThingListToThing VALUES (?, ?);"); | |||
| @@ -225,9 +225,15 @@ public class SqliteController { | |||
| } else { | |||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | |||
| } | |||
| if(userData.getRating() != null) { | |||
| thingStatement.setFloat(7, userData.getRating()); | |||
| } else { | |||
| thingStatement.setNull(7, java.sql.Types.FLOAT); | |||
| } | |||
| } else { | |||
| thingStatement.setString(5, ""); | |||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | |||
| thingStatement.setNull(7, java.sql.Types.FLOAT); | |||
| } | |||
| thingStatement.execute(); | |||
| // get generated id | |||
| @@ -282,7 +288,7 @@ public class SqliteController { | |||
| stmt = connection.createStatement(); | |||
| String str = "SELECT t.ThingId, t.Name, ImgUrl, ThumbUrl, Comment, NumPlays from Thing t " + | |||
| String str = "SELECT t.ThingId, t.Name, ImgUrl, ThumbUrl, Comment, NumPlays, UserRating from Thing t " + | |||
| "join ThingListToThing tltt on t.ThingId = tltt.ThingId " + | |||
| "join ThingList tl on tl.ListId = tltt.ListId " + | |||
| "where tl.Name = '" + name + "' order by t.Name asc"; | |||
| @@ -299,7 +305,8 @@ public class SqliteController { | |||
| res.getString(4)); | |||
| ThingUserData userData = new ThingUserData(); | |||
| userData.setComment(res.getString(5)); | |||
| userData.setNumPlays(res.getInt(6)); | |||
| userData.setNumPlays(res.getInt(6)); | |||
| userData.setRating(res.getFloat(7)); | |||
| Thing thing = new Thing(id, metaData); | |||
| thing.setUserData(userData); | |||
| thingList.add(thing); | |||
| @@ -90,6 +90,8 @@ public class BggApi { | |||
| } | |||
| } | |||
| urlStr.append("&stats=1"); | |||
| return getThings(urlStr.toString()); | |||
| } | |||
| @@ -100,6 +102,7 @@ public class BggApi { | |||
| StringBuilder urlStr = new StringBuilder(); | |||
| urlStr.append(BASE_URL + COLLECTION | |||
| + "?username=" + resultConfig.user | |||
| + "&stats=1" | |||
| + "&subtype=" + resultConfig.subtype.toApiString() + "&"); | |||
| if(resultConfig.subtype == Subtype.BOARDGAME) { | |||
| urlStr.append("excludesubtype=" + Subtype.BGEXPANSION.toApiString() + "&"); | |||
| @@ -381,6 +384,29 @@ public class BggApi { | |||
| details.maxplaytime = getIntegerFromString(getValueAttribute(eElement, "maxplaytime")); | |||
| details.age = getIntegerFromString(getValueAttribute(eElement, "minage")); | |||
| NodeList statsNodes = eElement.getElementsByTagName("statistics"); | |||
| if(statsNodes.getLength() > 0) { | |||
| Node statsNode = statsNodes.item(0); | |||
| if (statsNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element statsElement = (Element) statsNode; | |||
| NodeList ratingNodes = statsElement.getElementsByTagName("ratings"); | |||
| if(ratingNodes.getLength() > 0) { | |||
| Node ratingNode = ratingNodes.item(0); | |||
| if (ratingNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element ratingElement = (Element)ratingNode; | |||
| details.usersrated = getIntegerFromString(getValueAttribute(ratingElement, "usersrated")); | |||
| details.average = getFloatFromString(getValueAttribute(ratingElement, "average")); | |||
| details.averageweight = getFloatFromString(getValueAttribute(ratingElement, "averageweight")); | |||
| details.stddev = getFloatFromString(getValueAttribute(ratingElement, "stddev")); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // number of players recommendations | |||
| // Only saving up to 20 players | |||
| NodeList pollList = eElement.getElementsByTagName("poll"); | |||
| @@ -527,19 +553,24 @@ public class BggApi { | |||
| 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."); | |||
| if (statsNode.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element statsElement = (Element) statsNode; | |||
| NodeList ratingNodes = statsElement.getElementsByTagName("rating"); | |||
| if(ratingNodes.getLength() > 0) { | |||
| Element ratingNode = (Element)ratingNodes.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."); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -593,6 +624,13 @@ public class BggApi { | |||
| return null; | |||
| } | |||
| private Float getFloatFromString(String s) { | |||
| if(s != null && !s.isEmpty()) { | |||
| return Float.valueOf(s); | |||
| } | |||
| return null; | |||
| } | |||
| private String getValue(Element eElement, String key) { | |||
| Node node = eElement.getElementsByTagName(key).item(0); | |||
| if(node == null) { | |||
| @@ -604,7 +642,7 @@ public class BggApi { | |||
| private String getValueAttribute(Element eElement, String key) { | |||
| Node node = (Element)eElement.getElementsByTagName(key).item(0); | |||
| if (node.getNodeType() == Node.ELEMENT_NODE) { | |||
| if (node != null && node.getNodeType() == Node.ELEMENT_NODE) { | |||
| Element elem = (Element) node; | |||
| if(elem.hasAttribute("value")) { | |||
| return elem.getAttribute("value"); | |||
| @@ -41,7 +41,7 @@ public class ThingDetails { | |||
| Integer age; | |||
| Integer usersrated; | |||
| Integer average; | |||
| Float average; | |||
| Float bayesaverage; | |||
| Integer rank; | |||
| Integer rank_wg; | |||
| @@ -140,6 +140,8 @@ public class ThingProvider { | |||
| System.out.println(thing.toResultTxtLine()); | |||
| } | |||
| // TODO: | |||
| // Now join the details with the things that already contain user data, and output THOSE. | |||
| } | |||
| } | |||
| @@ -47,6 +47,8 @@ import org.eclipse.swt.widgets.Label; | |||
| public class FetchPart { | |||
| private static final String BUNDLE_NAME = "xyz.veronie.bgg.ui"; | |||
| @Inject | |||
| private ResultConfigManager configManager; | |||
| @@ -115,15 +117,15 @@ public class FetchPart { | |||
| btnBggUser = new Button(buttonRow, SWT.NONE); | |||
| btnBggUser.setToolTipText("Fetch by bgg user"); | |||
| btnBggUser.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Meeple_60x60.png")); | |||
| btnBggUser.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/noun_Meeple_60x60.png")); | |||
| btnFamily = new Button(buttonRow, SWT.NONE); | |||
| btnFamily.setToolTipText("Fetch by family"); | |||
| btnFamily.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_Family_60x60.png")); | |||
| btnFamily.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/noun_Family_60x60.png")); | |||
| btnGeeklist = new Button(buttonRow, SWT.NONE); | |||
| btnGeeklist.setToolTipText("Fetch by geeklist"); | |||
| btnGeeklist.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/noun_List_60x60.png")); | |||
| btnGeeklist.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/noun_List_60x60.png")); | |||
| centerComposite = new Composite(main, SWT.NONE); | |||
| @@ -155,7 +157,7 @@ public class FetchPart { | |||
| lblResultAction.setText("How do you want to apply the result?"); | |||
| Button btnReplace = new Button(applyComposite, SWT.NONE); | |||
| btnReplace.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_replace_60x60.png")); | |||
| btnReplace.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/result_replace_60x60.png")); | |||
| btnReplace.setToolTipText("Replace"); | |||
| btnReplace.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| @@ -165,7 +167,7 @@ public class FetchPart { | |||
| }); | |||
| Button btnOnlyNew = new Button(applyComposite, SWT.NONE); | |||
| btnOnlyNew.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/only_new_60x60.png")); | |||
| btnOnlyNew.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/only_new_60x60.png")); | |||
| btnOnlyNew.setToolTipText("Keep only new"); | |||
| btnOnlyNew.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| @@ -175,7 +177,7 @@ public class FetchPart { | |||
| }); | |||
| Button btnAdd = new Button(applyComposite, SWT.NONE); | |||
| btnAdd.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_add_60x60.png")); | |||
| btnAdd.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/result_add_60x60.png")); | |||
| btnAdd.setToolTipText("Add"); | |||
| btnAdd.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| @@ -185,7 +187,7 @@ public class FetchPart { | |||
| }); | |||
| Button btnIntersect = new Button(applyComposite, SWT.NONE); | |||
| btnIntersect.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_intersect_60x60.png")); | |||
| btnIntersect.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/result_intersect_60x60.png")); | |||
| btnIntersect.setToolTipText("Intersect"); | |||
| btnIntersect.addMouseListener(new MouseAdapter() { | |||
| @Override | |||
| @@ -195,7 +197,7 @@ public class FetchPart { | |||
| }); | |||
| Button btnSubtract = new Button(applyComposite, SWT.NONE); | |||
| btnSubtract.setImage(ResourceManager.getPluginImage("xyz.veronie.bgg.ui", "icons/result_subtract_60x60.png")); | |||
| btnSubtract.setImage(ResourceManager.getPluginImage(BUNDLE_NAME, "icons/result_subtract_60x60.png")); | |||
| btnSubtract.setToolTipText("Subtract"); | |||
| btnSubtract.addMouseListener(new MouseAdapter() { | |||
| @Override | |||