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/> | <windowImages/> | ||||
| <splash | |||||
| location="xyz.veronie.bgg.ui" /> | |||||
| <launcher> | <launcher> | ||||
| <win useIco="false"> | <win useIco="false"> | ||||
| <bmp/> | <bmp/> | ||||
| @@ -1,12 +1,8 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
| <classpath> | <classpath> | ||||
| <classpathentry exported="true" kind="lib" path="lib/"/> | <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.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="src" path="src"/> | ||||
| <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> | <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> | ||||
| <attributes> | <attributes> | ||||
| @@ -1,27 +1,23 @@ | |||||
| Manifest-Version: 1.0 | Manifest-Version: 1.0 | ||||
| Bundle-ManifestVersion: 2 | Bundle-ManifestVersion: 2 | ||||
| Bundle-Name: Secondtry | |||||
| Bundle-Name: Bgg Tool Khaki Flavor | |||||
| Bundle-SymbolicName: xyz.veronie.bgg.ui;singleton:=true | Bundle-SymbolicName: xyz.veronie.bgg.ui;singleton:=true | ||||
| Bundle-Version: 1.0.0.qualifier | Bundle-Version: 1.0.0.qualifier | ||||
| Bundle-ClassPath: lib/sqlite-jdbc-3.34.0.jar, | Bundle-ClassPath: lib/sqlite-jdbc-3.34.0.jar, | ||||
| swing2swt.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.core.di, | ||||
| org.eclipse.e4.ui.workbench, | org.eclipse.e4.ui.workbench, | ||||
| org.eclipse.e4.ui.di, | org.eclipse.e4.ui.di, | ||||
| org.eclipse.e4.core.di.extensions, | |||||
| javax.annotation, | |||||
| org.eclipse.jface, | 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, | Import-Package: javax.annotation;version="1.0.0";resolution:=optional, | ||||
| javax.inject;version="1.0.0", | javax.inject;version="1.0.0", | ||||
| org.eclipse.e4.core.commands, | 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 | org.eclipse.e4.ui.model.application.ui.basic | ||||
| Automatic-Module-Name: de.wt.secondtry | |||||
| @@ -85,7 +85,7 @@ public class SqliteController { | |||||
| } | } | ||||
| try { | try { | ||||
| Statement stmt = connection.createStatement(); | 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 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 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 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); | int listId = getThingListId(name); | ||||
| PreparedStatement thingStatement = connection | PreparedStatement thingStatement = connection | ||||
| .prepareStatement("INSERT OR REPLACE INTO Thing VALUES (?, ?, ?, ?, ?, ?);"); | |||||
| .prepareStatement("INSERT OR REPLACE INTO Thing VALUES (?, ?, ?, ?, ?, ?, ?);"); | |||||
| PreparedStatement listToThingStatement = connection | PreparedStatement listToThingStatement = connection | ||||
| .prepareStatement("INSERT OR IGNORE INTO ThingListToThing VALUES (?, ?);"); | .prepareStatement("INSERT OR IGNORE INTO ThingListToThing VALUES (?, ?);"); | ||||
| @@ -225,9 +225,15 @@ public class SqliteController { | |||||
| } else { | } else { | ||||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | 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 { | } else { | ||||
| thingStatement.setString(5, ""); | thingStatement.setString(5, ""); | ||||
| thingStatement.setNull(6, java.sql.Types.INTEGER); | thingStatement.setNull(6, java.sql.Types.INTEGER); | ||||
| thingStatement.setNull(7, java.sql.Types.FLOAT); | |||||
| } | } | ||||
| thingStatement.execute(); | thingStatement.execute(); | ||||
| // get generated id | // get generated id | ||||
| @@ -282,7 +288,7 @@ public class SqliteController { | |||||
| stmt = connection.createStatement(); | 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 ThingListToThing tltt on t.ThingId = tltt.ThingId " + | ||||
| "join ThingList tl on tl.ListId = tltt.ListId " + | "join ThingList tl on tl.ListId = tltt.ListId " + | ||||
| "where tl.Name = '" + name + "' order by t.Name asc"; | "where tl.Name = '" + name + "' order by t.Name asc"; | ||||
| @@ -299,7 +305,8 @@ public class SqliteController { | |||||
| res.getString(4)); | res.getString(4)); | ||||
| ThingUserData userData = new ThingUserData(); | ThingUserData userData = new ThingUserData(); | ||||
| userData.setComment(res.getString(5)); | 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 thing = new Thing(id, metaData); | ||||
| thing.setUserData(userData); | thing.setUserData(userData); | ||||
| thingList.add(thing); | thingList.add(thing); | ||||
| @@ -90,6 +90,8 @@ public class BggApi { | |||||
| } | } | ||||
| } | } | ||||
| urlStr.append("&stats=1"); | |||||
| return getThings(urlStr.toString()); | return getThings(urlStr.toString()); | ||||
| } | } | ||||
| @@ -100,6 +102,7 @@ public class BggApi { | |||||
| StringBuilder urlStr = new StringBuilder(); | StringBuilder urlStr = new StringBuilder(); | ||||
| urlStr.append(BASE_URL + COLLECTION | urlStr.append(BASE_URL + COLLECTION | ||||
| + "?username=" + resultConfig.user | + "?username=" + resultConfig.user | ||||
| + "&stats=1" | |||||
| + "&subtype=" + resultConfig.subtype.toApiString() + "&"); | + "&subtype=" + resultConfig.subtype.toApiString() + "&"); | ||||
| if(resultConfig.subtype == Subtype.BOARDGAME) { | if(resultConfig.subtype == Subtype.BOARDGAME) { | ||||
| urlStr.append("excludesubtype=" + Subtype.BGEXPANSION.toApiString() + "&"); | urlStr.append("excludesubtype=" + Subtype.BGEXPANSION.toApiString() + "&"); | ||||
| @@ -381,6 +384,29 @@ public class BggApi { | |||||
| details.maxplaytime = getIntegerFromString(getValueAttribute(eElement, "maxplaytime")); | details.maxplaytime = getIntegerFromString(getValueAttribute(eElement, "maxplaytime")); | ||||
| details.age = getIntegerFromString(getValueAttribute(eElement, "minage")); | 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 | // number of players recommendations | ||||
| // Only saving up to 20 players | // Only saving up to 20 players | ||||
| NodeList pollList = eElement.getElementsByTagName("poll"); | NodeList pollList = eElement.getElementsByTagName("poll"); | ||||
| @@ -527,19 +553,24 @@ public class BggApi { | |||||
| NodeList statsNodes = eElement.getElementsByTagName("stats"); | NodeList statsNodes = eElement.getElementsByTagName("stats"); | ||||
| if(statsNodes.getLength() > 0) { | if(statsNodes.getLength() > 0) { | ||||
| Node statsNode = statsNodes.item(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; | 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) { | private String getValue(Element eElement, String key) { | ||||
| Node node = eElement.getElementsByTagName(key).item(0); | Node node = eElement.getElementsByTagName(key).item(0); | ||||
| if(node == null) { | if(node == null) { | ||||
| @@ -604,7 +642,7 @@ public class BggApi { | |||||
| private String getValueAttribute(Element eElement, String key) { | private String getValueAttribute(Element eElement, String key) { | ||||
| Node node = (Element)eElement.getElementsByTagName(key).item(0); | 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; | Element elem = (Element) node; | ||||
| if(elem.hasAttribute("value")) { | if(elem.hasAttribute("value")) { | ||||
| return elem.getAttribute("value"); | return elem.getAttribute("value"); | ||||
| @@ -41,7 +41,7 @@ public class ThingDetails { | |||||
| Integer age; | Integer age; | ||||
| Integer usersrated; | Integer usersrated; | ||||
| Integer average; | |||||
| Float average; | |||||
| Float bayesaverage; | Float bayesaverage; | ||||
| Integer rank; | Integer rank; | ||||
| Integer rank_wg; | Integer rank_wg; | ||||
| @@ -140,6 +140,8 @@ public class ThingProvider { | |||||
| System.out.println(thing.toResultTxtLine()); | 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 { | public class FetchPart { | ||||
| private static final String BUNDLE_NAME = "xyz.veronie.bgg.ui"; | |||||
| @Inject | @Inject | ||||
| private ResultConfigManager configManager; | private ResultConfigManager configManager; | ||||
| @@ -115,15 +117,15 @@ public class FetchPart { | |||||
| btnBggUser = new Button(buttonRow, SWT.NONE); | btnBggUser = new Button(buttonRow, SWT.NONE); | ||||
| btnBggUser.setToolTipText("Fetch by bgg user"); | 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 = new Button(buttonRow, SWT.NONE); | ||||
| btnFamily.setToolTipText("Fetch by family"); | 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 = new Button(buttonRow, SWT.NONE); | ||||
| btnGeeklist.setToolTipText("Fetch by geeklist"); | 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); | centerComposite = new Composite(main, SWT.NONE); | ||||
| @@ -155,7 +157,7 @@ public class FetchPart { | |||||
| lblResultAction.setText("How do you want to apply the result?"); | lblResultAction.setText("How do you want to apply the result?"); | ||||
| Button btnReplace = new Button(applyComposite, SWT.NONE); | 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.setToolTipText("Replace"); | ||||
| btnReplace.addMouseListener(new MouseAdapter() { | btnReplace.addMouseListener(new MouseAdapter() { | ||||
| @Override | @Override | ||||
| @@ -165,7 +167,7 @@ public class FetchPart { | |||||
| }); | }); | ||||
| Button btnOnlyNew = new Button(applyComposite, SWT.NONE); | 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.setToolTipText("Keep only new"); | ||||
| btnOnlyNew.addMouseListener(new MouseAdapter() { | btnOnlyNew.addMouseListener(new MouseAdapter() { | ||||
| @Override | @Override | ||||
| @@ -175,7 +177,7 @@ public class FetchPart { | |||||
| }); | }); | ||||
| Button btnAdd = new Button(applyComposite, SWT.NONE); | 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.setToolTipText("Add"); | ||||
| btnAdd.addMouseListener(new MouseAdapter() { | btnAdd.addMouseListener(new MouseAdapter() { | ||||
| @Override | @Override | ||||
| @@ -185,7 +187,7 @@ public class FetchPart { | |||||
| }); | }); | ||||
| Button btnIntersect = new Button(applyComposite, SWT.NONE); | 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.setToolTipText("Intersect"); | ||||
| btnIntersect.addMouseListener(new MouseAdapter() { | btnIntersect.addMouseListener(new MouseAdapter() { | ||||
| @Override | @Override | ||||
| @@ -195,7 +197,7 @@ public class FetchPart { | |||||
| }); | }); | ||||
| Button btnSubtract = new Button(applyComposite, SWT.NONE); | 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.setToolTipText("Subtract"); | ||||
| btnSubtract.addMouseListener(new MouseAdapter() { | btnSubtract.addMouseListener(new MouseAdapter() { | ||||
| @Override | @Override | ||||