[LIB-2] Add snooker-score-api source files
authorgotty <gotty@fb0bcced-7025-49ed-a12f-f98bce993226>
Sat, 21 Jan 2017 01:57:01 +0000 (01:57 +0000)
committergotty <gotty@fb0bcced-7025-49ed-a12f-f98bce993226>
Sat, 21 Jan 2017 01:57:01 +0000 (01:57 +0000)
git-svn-id: https://svn.hedgecode.org/lib/snooker-score-api/trunk@98 fb0bcced-7025-49ed-a12f-f98bce993226

99 files changed:
src/main/java/org/hedgecode/snooker/Snooker.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/SnookerScoreApp.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/APIException.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/CollectionEntity.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Event.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Events.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/IdEntity.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Match.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Matches.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/OngoingMatch.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/OngoingMatches.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Player.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/PlayerCategory.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Players.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Ranking.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/RankingType.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Rankings.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/Season.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/api/SnookerScoreAPI.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/CacheSnookerScore.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/CacheCollectionAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/CacheIdAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/CollectionAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/EventAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/EventsAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/IdAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/MatchAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/MatchesAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/RankingAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/cache/assign/RankingsAssigner.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/compare/EventComparators.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/compare/MatchComparators.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/compare/PlayerComparators.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/compare/RankingComparators.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/gson/SnookerGsonBuilder.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonCollectionEntity.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonEvent.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonEvents.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonIdEntity.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonMatch.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonMatches.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonOngoingMatch.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonOngoingMatches.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonPlayer.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonPlayers.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonRanking.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonRankings.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonSerializable.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonSnookerScore.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/json/JsonStringToken.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/AbstractRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/EventMatchesRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/EventPlayersRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/EventRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/MatchRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/OngoingMatchesRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/PlayerMatchesRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/PlayerRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/RankingRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/RequestException.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/RequestParams.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/RequestType.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/Requester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/SeasonEventsRequester.java [new file with mode: 0644]
src/main/java/org/hedgecode/snooker/request/SeasonPlayersRequester.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/api/SeasonTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/AbstractJsonTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonEventTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonEventsTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonMatchTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonMatchesTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchesTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonPlayerTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonPlayersTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonRankingTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonRankingsTest.java [new file with mode: 0644]
src/test/java/org/hedgecode/snooker/json/JsonStringTokenTest.java [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonEventTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonEventTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.ser [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.json [new file with mode: 0644]
src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.ser [new file with mode: 0644]

diff --git a/src/main/java/org/hedgecode/snooker/Snooker.java b/src/main/java/org/hedgecode/snooker/Snooker.java
new file mode 100644 (file)
index 0000000..d133db6
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker;
+
+import org.hedgecode.snooker.api.SnookerScoreAPI;
+import org.hedgecode.snooker.cache.CacheSnookerScore;
+import org.hedgecode.snooker.json.JsonSnookerScore;
+
+/**
+ * Snooker Score Common Class for API access.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class Snooker {
+
+    private static final SnookerScoreAPI JSON_API = JsonSnookerScore.getInstance();
+    private static final SnookerScoreAPI CACHED_API = CacheSnookerScore.getInstance();
+
+    public static SnookerScoreAPI API() {
+        return CACHED_API;
+    }
+
+    public static SnookerScoreAPI API(boolean useCache) {
+        return useCache ? CACHED_API : JSON_API;
+    }
+
+    public static SnookerScoreAPI uncachedAPI() {
+        return JSON_API;
+    }
+
+    public static SnookerScoreAPI cachedAPI() {
+        return CACHED_API;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/SnookerScoreApp.java b/src/main/java/org/hedgecode/snooker/SnookerScoreApp.java
new file mode 100644 (file)
index 0000000..e81bc6e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker;
+
+import java.text.SimpleDateFormat;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Snooker Score Main Application.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class SnookerScoreApp {
+
+    private static final String EMPTY = "";
+    private static final String DELIMITER =
+            "********************************************************************************";
+    private static final String[] WELCOME = {
+            "                    Welcome to Hedgecode Snooker Score API!                     ",
+            "                -----------------------------------------------                 ",
+            "         It is an API library for portal snooker.org, which contains            ",
+            "      the results of snooker competitions and other snooker information.        ",
+            "    This library provides a set of entity objects that can be used in client    ",
+            "    applications (to inform about the results of snooker), developed in Java.   "
+    };
+    private static final String CURRENT_EVENTS = "  Current Snooker Events:  ";
+    private static final String UPCOMING_EVENTS = "  Upcoming Snooker Events:  ";
+    private static final String INDENT = "     ";
+
+    private static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy");
+
+    private static final int UPCOMING_COUNT = 5;
+
+    public static void main(String[] args) throws APIException
+    {
+        System.out.println(EMPTY);
+        System.out.println(DELIMITER);
+        for (String line : WELCOME) {
+            System.out.println(line);
+        }
+
+        Events events = Snooker.uncachedAPI().getSeasonEvents(
+                Season.CURRENT_SEASON
+        );
+        events.sortByDate();
+
+        Events currentEvents = events.current();
+        if (!currentEvents.isEmpty()) {
+            System.out.println(DELIMITER);
+            System.out.println(CURRENT_EVENTS);
+        }
+        for (Event currentEvent : currentEvents) {
+            printEvent(currentEvent);
+        }
+
+        System.out.println(DELIMITER);
+        System.out.println(UPCOMING_EVENTS);
+
+        int count = 0;
+        Events upcomingEvents = events.upcoming();
+        for (Event upcomingEvent : upcomingEvents) {
+            printEvent(upcomingEvent);
+            ++count;
+            if (count >= UPCOMING_COUNT) break;
+        }
+        System.out.println(DELIMITER);
+        System.out.println(EMPTY);
+    }
+
+    private static void printEvent(Event event) {
+        System.out.println(
+                INDENT  + event.name()
+                        + " [" + DATE_FORMAT.format(event.startDate())
+                        + " - " + DATE_FORMAT.format(event.endDate()) + "]"
+                        + " (" + event.country() + ", " + event.city() + ")"
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/APIException.java b/src/main/java/org/hedgecode/snooker/api/APIException.java
new file mode 100644 (file)
index 0000000..6a87e07
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * API Exception for information about different types of errors.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class APIException extends Exception {
+
+    public static enum Type {
+        INFO,
+        REQUEST
+    }
+
+    private Type exceptionType;
+
+    public APIException(Type exceptionType, String message) {
+        super(message);
+        this.exceptionType = exceptionType;
+    }
+
+    public Type getType() {
+        return exceptionType;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/CollectionEntity.java b/src/main/java/org/hedgecode/snooker/api/CollectionEntity.java
new file mode 100644 (file)
index 0000000..25a0234
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Abstract Collection of Entities API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface CollectionEntity<E extends IdEntity> extends Iterable<E> {
+
+    E byId(int id);
+
+    int size();
+
+    boolean isEmpty();
+
+    void sortById();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Event.java b/src/main/java/org/hedgecode/snooker/api/Event.java
new file mode 100644 (file)
index 0000000..45b50b5
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+import java.util.Date;
+
+/**
+ * Event Entity API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Event extends IdEntity {
+
+    int eventId();
+
+    String name();
+
+    Date startDate();
+
+    Date endDate();
+
+    String sponsor();
+
+    Season season();
+
+    String type();
+
+    int num();
+
+    String venue();
+
+    String city();
+
+    String country();
+
+    String discipline();
+
+    int mainEventId();
+
+    Event mainEvent();
+
+    String sex();
+
+    String ageGroup();
+
+    String url();
+
+    String related();
+
+    String stage();
+
+    String valueType();
+
+    String shortName();
+
+    int worldSnookerId();
+
+    String rankingType();
+
+    int eventPredictionId();
+
+    boolean team();
+
+    int format();
+
+    String twitter();
+
+    String hashTag();
+
+    float conversionRate();
+
+    boolean allRoundsAdded();
+
+    String photoUrls();
+
+    int numCompetitors();
+
+    int numUpcoming();
+
+    int numActive();
+
+    int numResults();
+
+    String note();
+
+    String commonNote();
+
+    int defendingChampion();
+
+    int previousEdition();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Events.java b/src/main/java/org/hedgecode/snooker/api/Events.java
new file mode 100644 (file)
index 0000000..675c3f9
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Events Entity (set of {@link Event}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Events extends CollectionEntity<Event> {
+
+    Events bySeason(Season season);
+
+    Events byType(String type);
+    Events byCity(String city);
+    Events byCountry(String country);
+    Events bySex(String sex);
+    Events byStage(String stage);
+    Events byValueType(String valueType);
+
+    Events bySnookerId(int worldSnookerId);
+
+    Events ended();
+    Events current();
+    Events upcoming();
+
+    void sortByDate();
+    void sortBySnookerId();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/IdEntity.java b/src/main/java/org/hedgecode/snooker/api/IdEntity.java
new file mode 100644 (file)
index 0000000..699ea8f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Abstract Entity with ID API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface IdEntity {
+
+    int getId();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Match.java b/src/main/java/org/hedgecode/snooker/api/Match.java
new file mode 100644 (file)
index 0000000..b006c32
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+import java.util.Date;
+
+/**
+ * Match Entity API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Match extends IdEntity {
+
+    int matchId();
+
+    int eventId();
+
+    Event event();
+
+    int round();
+
+    int number();
+
+    int player1Id();
+
+    Player player1();
+
+    int score1();
+
+    boolean walkover1();
+
+    int player2Id();
+
+    Player player2();
+
+    int score2();
+
+    boolean walkover2();
+
+    int winnerId();
+
+    Player winner();
+
+    boolean unfinished();
+
+    boolean onBreak();
+
+    int worldSnookerId();
+
+    String liveUrl();
+
+    String detailsUrl();
+
+    boolean pointsDropped();
+
+    boolean showCommonNote();
+
+    boolean estimated();
+
+    int type();
+
+    int tableNo();
+
+    String videoURL();
+
+    Date initDate();
+
+    Date modDate();
+
+    Date startDate();
+
+    Date endDate();
+
+    Date scheduledDate();
+
+    String frameScores();
+
+    String sessions();
+
+    String note();
+
+    String extendedNote();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Matches.java b/src/main/java/org/hedgecode/snooker/api/Matches.java
new file mode 100644 (file)
index 0000000..1777cef
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Matches Entity (set of {@link Match}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Matches extends CollectionEntity<Match> {
+
+    Matches byEvent(int eventId);
+    Matches byRound(int eventId, int round);
+    Matches byPlayer(int playerId);
+
+    Matches ended();
+    Matches current();
+    Matches upcoming();
+
+    void sortByNumber();
+    void sortByEvent();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/OngoingMatch.java b/src/main/java/org/hedgecode/snooker/api/OngoingMatch.java
new file mode 100644 (file)
index 0000000..688df16
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Ongoing Match Entity API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface OngoingMatch extends Match {
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/OngoingMatches.java b/src/main/java/org/hedgecode/snooker/api/OngoingMatches.java
new file mode 100644 (file)
index 0000000..ed26c21
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Ongoing Matches Entity (set of {@link OngoingMatch}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface OngoingMatches extends CollectionEntity<OngoingMatch> {
+
+    OngoingMatch byNumber(int number);
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Player.java b/src/main/java/org/hedgecode/snooker/api/Player.java
new file mode 100644 (file)
index 0000000..9c6c7ea
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+import java.util.Date;
+
+/**
+ * Player Entity API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Player extends IdEntity {
+
+    int playerId();
+
+    int type();
+
+    String firstName();
+
+    String middleName();
+
+    String lastName();
+
+    String teamName();
+
+    int teamNumber();
+
+    int teamSeason();
+
+    String shortName();
+
+    String nationality();
+
+    String sex();
+
+    String bioPage();
+
+    Date born();
+
+    String twitter();
+
+    boolean surnameFirst();
+
+    String license();
+
+    String club();
+
+    String url();
+
+    String photo();
+
+    String info();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/PlayerCategory.java b/src/main/java/org/hedgecode/snooker/api/PlayerCategory.java
new file mode 100644 (file)
index 0000000..b99be6f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Categories of Players Entity.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum PlayerCategory {
+
+    PRO ("p"),
+    ALL ("a"); // todo
+
+    private String letter;
+
+    PlayerCategory(String letter) {
+        this.letter = letter;
+    }
+
+    public String letter() {
+        return letter;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Players.java b/src/main/java/org/hedgecode/snooker/api/Players.java
new file mode 100644 (file)
index 0000000..c4be2ab
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Players Entity (set of {@link Player}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Players extends CollectionEntity<Player> {
+
+    Players byType(int type);
+    Players byName(String name);
+    Players byNationality(String nationality);
+    Players bySex(String sex);
+
+    void sortByName();
+    void sortByAge();
+    void sortByAgeDesc();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Ranking.java b/src/main/java/org/hedgecode/snooker/api/Ranking.java
new file mode 100644 (file)
index 0000000..a0e921e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Ranking Entity API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Ranking extends IdEntity {
+
+    int rankingId();
+
+    int position();
+
+    int playerId();
+
+    Player player();
+
+    Season season();
+
+    long sum();
+
+    RankingType rankingType();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/RankingType.java b/src/main/java/org/hedgecode/snooker/api/RankingType.java
new file mode 100644 (file)
index 0000000..699b706
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Types of Ranking Entity.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum RankingType {
+
+    MoneyRankings (2013, Season.CURRENT_YEAR),
+    OneYearMoneyRankings (2013, Season.CURRENT_YEAR),
+
+    ProjectedMoneyRankings (2013, Season.CURRENT_YEAR),
+    ProjectedMoneySeedings (2013, Season.CURRENT_YEAR),
+    ProvOneYearMoneyRankings (2013, Season.CURRENT_YEAR),
+    ProjectedEndOfSeasonMoneySeedings (2014, Season.CURRENT_YEAR),
+    ProjectedGrandPrixMoneyRankings (2014, Season.CURRENT_YEAR),
+
+    PrevMoneyRankings (Season.CURRENT_YEAR - 1, Season.CURRENT_YEAR),
+    PrevMoneySeedings (Season.CURRENT_YEAR - 1, Season.CURRENT_YEAR),
+    PrevOneYearMoneyRankings (Season.CURRENT_YEAR - 1, Season.CURRENT_YEAR),
+    PrevOrderOfMerit (Season.CURRENT_YEAR - 1, Season.CURRENT_YEAR),
+
+    WorldGrandPrix2015Rankings (2014, 2014),
+    WorldGrandPrix2016Rankings (2015, 2015),
+
+    CombinedOrderofMerit2013 (2013, 2013),
+    CombinedOrderOfMerit2014 (2014, 2014),
+    CombinedOrderOfMerit2016 (2015, 2015),
+
+    Rankings (2010, 2013),
+    Seedings (2010, 2013),
+    OneYearRankings (2009, 2013),
+
+    OrderOfMerit (2010, 2015),
+    APTC (2012, 2015),
+    CombinedOrderofMerit (2013, 2015),
+
+    SeedingsAfterPTC6 (2011, 2011),
+    SeedingsAfterPTC12 (2011, 2011),
+    SeedingsAfterWelsh2012 (2011, 2011),
+    SeedingsAfterWorld2012 (2012, 2012),
+    SeedingsAfterUKPTC22012 (2012, 2012),
+    SeedingsAfterInternational2012 (2012, 2012),
+    ProjectedSeedings (2012, 2012),
+    SeedingsAfterWorld2013 (2012, 2012),
+    SeedingsAfterEPTC22013 (2013, 2013),
+    SeedingsAfterShanghaiMasters2013 (2013, 2013),
+    SeedingsAfterInternationalChampionship2013 (2013, 2013),
+    SeedingsAfterUKChampionship2013 (2013, 2013),
+    SeedingsAfterGermanMasters2014 (2013, 2013),
+    SeedingsAfterPTCFinals2014 (2013, 2013),
+    SeedingsAfterAustralian2014 (2014, 2014),
+    SeedingsAfterShanghai2014 (2014, 2014),
+    SeedingsAfterInternationalChampionship2014 (2014, 2014),
+    SeedingsAfterUKChampionship2014 (2014, 2014),
+    SeedingsAfterAPTC32015 (2014, 2014),
+    SeedingsAfterGermanMasters2015 (2014, 2014),
+    SeedingsAfterChinaOpen2015 (2014, 2014),
+    SeedingsAfterAustralian2015 (2015, 2015),
+    SeedingsAfterShanghai2015 (2015, 2015),
+    SeedingsAfterInternational2015 (2015, 2015),
+    SeedingsAfterUK2015 (2015, 2015),
+    SeedingsAfterEPTC52015 (2015, 2015),
+    SeedingsAfterGerman2016 (2015, 2015),
+    SeedingsAfterChina2016 (2015, 2015),
+    SeedingsAfterWorld2016 (2015, 2015),
+
+    OrderOfMeritAfterPTC4 (2011, 2011),
+    OrderOfMeritAfterPTC8 (2011, 2011),
+    OrderOfMeritAfterPTC12 (2011, 2011),
+    OrderOfMeritAfterEPTC12012 (2012, 2012),
+    OrderOfMeritAfterEPTC32012 (2012, 2012),
+    OrderOfMeritAfterEPTC42012 (2012, 2012),
+    OrderOfMeritAfterEPTC12013 (2013, 2013),
+    OrderOfMeritAfterEPTC22013 (2013, 2013),
+    OrderOfMeritAfterEPTC42013 (2013, 2013),
+    OrderOfMeritAfterEPTC52013 (2013, 2013),
+    OrderOfMeritAfterEPTC62013 (2013, 2013),
+    OrderOfMeritAfterEPTC72013 (2013, 2013),
+    OrderOfMeritAfterEPTC82014 (2013, 2013),
+    OrderOfMeritAfterEPTC12014 (2014, 2014),
+    OrderOfMeritAfterEPTC22014 (2014, 2014),
+    OrderOfMeritAfterEPTC32014 (2014, 2014),
+    OrderOfMeritAfterEPTC42014 (2014, 2014),
+    OrderOfMeritAfterEPTC52014 (2014, 2014),
+    OrderOfMeritAfterEPTC12015 (2015, 2015),
+    OrderOfMeritAfterEPTC22015 (2015, 2015),
+    OrderOfMeritAfterEPTC32015 (2015, 2015),
+    OrderOfMeritAfterEPTC42015 (2015, 2015),
+    OrderOfMeritAfterEPTC52015 (2015, 2015),
+
+    APTCOrderOfMeritAfterAPTC22012 (2012, 2012),
+    APTCOrderOfMeritAfterAPTC12013 (2013, 2013),
+    APTCOrderOfMeritAfterAPTC22013 (2013, 2013),
+    APTCOrderOfMeritAfterAPTC32013 (2013, 2013),
+    APTCOrderOfMeritAfterAPTC12014 (2014, 2014),
+    APTCOrderOfMeritAfterAPTC22014 (2014, 2014),
+    APTCOrderOfMeritAfterAPTC12015 (2014, 2014);
+
+
+    private int startYear;
+    private int endYear;
+
+    RankingType(int startYear, int endYear) {
+        this.startYear = startYear;
+        this.endYear = endYear;
+    }
+
+    public static RankingType byName(String name) {
+        for (RankingType type : RankingType.values()) {
+            if (type.name().equals(name))
+                return type;
+        }
+        return null;
+    }
+
+    public static RankingType byNameAndYear(String name, int year) {
+        for (RankingType type : RankingType.values()) {
+            if (type.name().equals(name))
+                return type.isCorrectYear(year) ? type : null;
+        }
+        return null;
+    }
+
+    public boolean isCorrectYear(int year) {
+        return year >= startYear && year <= endYear;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Rankings.java b/src/main/java/org/hedgecode/snooker/api/Rankings.java
new file mode 100644 (file)
index 0000000..07e4e1b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Rankings Entity (set of {@link Ranking}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Rankings extends CollectionEntity<Ranking> {
+
+    Ranking byPlayer(int playerId);
+    Rankings bySum(long minSum, long maxSum);
+
+    void sortByPosition();
+    void sortBySum();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/Season.java b/src/main/java/org/hedgecode/snooker/api/Season.java
new file mode 100644 (file)
index 0000000..73ee53a
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+import java.util.Calendar;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Season Entity.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class Season {
+
+    private static final Calendar CURRENT_CALENDAR = Calendar.getInstance();
+
+    public static final int BEGIN_YEAR = 2005;
+    public static final int CURRENT_YEAR =
+            CURRENT_CALENDAR.get(Calendar.MONTH) >= 6
+                    ? CURRENT_CALENDAR.get(Calendar.YEAR)
+                    : CURRENT_CALENDAR.get(Calendar.YEAR) - 1;
+
+    private static final int ALL_SEASONS = -1;
+
+    public static final Season ALL = new Season(ALL_SEASONS);
+    public static final Season CURRENT_SEASON = new Season(CURRENT_YEAR);
+
+    public static Map<Integer, Season> SEASONS = new LinkedHashMap<>();
+
+    static {
+        for (int year = BEGIN_YEAR; year < CURRENT_YEAR; ++year) {
+            SEASONS.put(year, new Season(year));
+        }
+        SEASONS.put(CURRENT_YEAR, CURRENT_SEASON);
+        SEASONS.put(ALL_SEASONS, ALL);
+    }
+
+    private int year;
+
+    private Season(int year) {
+        this.year = year;
+    }
+
+    public static Season getSeason(int year) {
+        return SEASONS.get(year);
+    }
+
+    public int getYear() {
+        return year;
+    }
+
+    @Override
+    public String toString() {
+        return year == ALL_SEASONS ? "All Seasons" : year + "/" + (year + 1);
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/api/SnookerScoreAPI.java b/src/main/java/org/hedgecode/snooker/api/SnookerScoreAPI.java
new file mode 100644 (file)
index 0000000..787f9fd
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+/**
+ * Snooker Score API for external applications.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface SnookerScoreAPI {
+
+    Event getEvent(int eventId) throws APIException;
+
+    Match getMatch(int eventId, int roundId, int matchNumber) throws APIException;
+
+    Player getPlayer(int playerId) throws APIException;
+
+    Events getSeasonEvents(Season season) throws APIException;
+
+    Matches getEventMatches(int eventId) throws APIException;
+
+    OngoingMatches getOngoingMatches() throws APIException;
+
+    Matches getPlayerMatches(int playerId, Season season) throws APIException;
+
+    Players getEventPlayers(int eventId) throws APIException;
+
+    Players getPlayers(Season season, PlayerCategory category) throws APIException;
+
+    Rankings getRankings(Season season, RankingType type) throws APIException;
+
+    void setCurrentSeason(Season season) throws APIException;
+
+    Season currentSeason() throws APIException;
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/CacheSnookerScore.java b/src/main/java/org/hedgecode/snooker/cache/CacheSnookerScore.java
new file mode 100644 (file)
index 0000000..df72b51
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Matches;
+import org.hedgecode.snooker.api.OngoingMatches;
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.api.PlayerCategory;
+import org.hedgecode.snooker.api.Players;
+import org.hedgecode.snooker.api.RankingType;
+import org.hedgecode.snooker.api.Rankings;
+import org.hedgecode.snooker.api.Season;
+import org.hedgecode.snooker.api.SnookerScoreAPI;
+import org.hedgecode.snooker.cache.assign.EventAssigner;
+import org.hedgecode.snooker.cache.assign.EventsAssigner;
+import org.hedgecode.snooker.cache.assign.MatchAssigner;
+import org.hedgecode.snooker.cache.assign.MatchesAssigner;
+import org.hedgecode.snooker.cache.assign.RankingsAssigner;
+import org.hedgecode.snooker.json.JsonSnookerScore;
+
+/**
+ * Implementation of Interface {@link SnookerScoreAPI}
+ * with caching {@link Players} and {@link Events}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class CacheSnookerScore extends JsonSnookerScore implements SnookerScoreAPI {
+
+    private Season currentSeason;
+
+    private Players playersCache;
+    private Events eventsCache;
+
+    private Player unknownPlayer;
+
+    private final EventsAssigner eventsAssigner = EventsAssigner.getInstance();
+    private final MatchesAssigner matchesAssigner = MatchesAssigner.getInstance();
+    private final RankingsAssigner rankingsAssigner = RankingsAssigner.getInstance();
+
+    private static CacheSnookerScore _instance;
+
+    public static CacheSnookerScore getInstance() {
+        if (_instance == null)
+            _instance= new CacheSnookerScore();
+        return _instance;
+    }
+
+    private CacheSnookerScore() {
+        currentSeason = Season.CURRENT_SEASON;
+    }
+
+    @Override
+    public void setCurrentSeason(Season season) throws APIException {
+        if (season == null)
+            throw new APIException(
+                    APIException.Type.INFO, "Current season can not be null"
+            );
+        currentSeason = season;
+        initPlayersCache();
+        initEventsCache();
+    }
+
+    @Override
+    public Season currentSeason() throws APIException {
+        return currentSeason;
+    }
+
+    private void initPlayersCache() throws APIException {
+        playersCache = super.getPlayers(
+                currentSeason,
+                PlayerCategory.PRO
+        );
+        unknownPlayer = playersCache.byId(UNKNOWN_PLAYER_ID);
+        if (unknownPlayer == null)
+            unknownPlayer = super.getPlayer(UNKNOWN_PLAYER_ID);
+    }
+
+    private void initEventsCache() throws APIException {
+        eventsCache = super.getSeasonEvents(
+                currentSeason
+        );
+        eventsAssigner.assign(eventsCache);
+    }
+
+    @Override
+    public Event getEvent(int eventId) throws APIException {
+        Event event = getCachedEvent(eventId);
+        if (event == null) {
+            event = super.getEvent(eventId);
+            EventAssigner.getInstance().assign(event);
+        }
+        return event;
+    }
+
+    public Event getCachedEvent(int eventId) throws APIException {
+        if (eventsCache == null)
+            initEventsCache();
+        return eventsCache.byId(eventId);
+    }
+
+    @Override
+    public Match getMatch(int eventId, int roundId, int matchNumber) throws APIException {
+        Match match = super.getMatch(eventId, roundId, matchNumber);
+        MatchAssigner.getInstance().assign(match);
+        return match;
+    }
+
+    @Override
+    public Player getPlayer(int playerId) throws APIException {
+        Player player = getCachedPlayer(playerId);
+        return player != null
+                ? player
+                : super.getPlayer(playerId);
+    }
+
+    public Player getCachedPlayer(int playerId) throws APIException {
+        if (playersCache == null)
+            initPlayersCache();
+        if (playerId == UNKNOWN_PLAYER_ID)
+            return unknownPlayer;
+        return playersCache.byId(playerId);
+    }
+
+    @Override
+    public Events getSeasonEvents(Season season) throws APIException {
+        if (eventsCache == null)
+            initEventsCache();
+        Events events;
+        if (currentSeason.equals(season) || currentSeason.equals(Season.ALL)) {
+            events = eventsCache.bySeason(season);
+        } else {
+            events = super.getSeasonEvents(season);
+            eventsAssigner.assign(events);
+        }
+        return events;
+    }
+
+    @Override
+    public Matches getEventMatches(int eventId) throws APIException {
+        Matches matches = super.getEventMatches(eventId);
+        matchesAssigner.assign(matches);
+        return matches;
+    }
+
+    @Override
+    public OngoingMatches getOngoingMatches() throws APIException {
+        OngoingMatches matches = super.getOngoingMatches();
+        matchesAssigner.assign(matches);
+        return matches;
+    }
+
+    @Override
+    public Matches getPlayerMatches(int playerId, Season season) throws APIException {
+        Matches matches = super.getPlayerMatches(playerId, season);
+        matchesAssigner.assign(matches);
+        return matches;
+    }
+
+    @Override
+    public Rankings getRankings(Season season, RankingType type) throws APIException {
+        Rankings rankings = super.getRankings(season, type);
+        rankingsAssigner.assign(rankings);
+        return rankings;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/CacheCollectionAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/CacheCollectionAssigner.java
new file mode 100644 (file)
index 0000000..571acdf
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.CollectionEntity;
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Abstract Assigner for Collections of Entities.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class CacheCollectionAssigner
+        <T extends IdEntity, E extends CollectionEntity<T>, A extends IdAssigner<T>>
+        implements CollectionAssigner<E>
+{
+    private A entityAsssigner;
+
+    protected CacheCollectionAssigner(A entityAsssigner) {
+        this.entityAsssigner = entityAsssigner;
+    }
+
+    public A assigner() {
+        return entityAsssigner;
+    }
+
+    @Override
+    public void assign(E entities) throws APIException {
+        for (T entity : entities) {
+            entityAsssigner.assign(
+                    entity
+            );
+        }
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/CacheIdAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/CacheIdAssigner.java
new file mode 100644 (file)
index 0000000..8a5d0d8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.IdEntity;
+import org.hedgecode.snooker.cache.CacheSnookerScore;
+
+/**
+ * Abstract Assigner for Entities.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class CacheIdAssigner<E extends IdEntity> implements IdAssigner<E> {
+
+    protected static final CacheSnookerScore cacheScore = CacheSnookerScore.getInstance();
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/CollectionAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/CollectionAssigner.java
new file mode 100644 (file)
index 0000000..b3ee8d5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.CollectionEntity;
+
+/**
+ * Assigner for Collections Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface CollectionAssigner<E extends CollectionEntity> {
+
+    void assign(E entity) throws APIException;
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/EventAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/EventAssigner.java
new file mode 100644 (file)
index 0000000..8c2cc8b
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.json.JsonEvent;
+
+/**
+ * Assigner for Entity fields of {@link Event}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventAssigner extends CacheIdAssigner<Event> {
+
+    private static EventAssigner _instance;
+
+    private EventAssigner() {
+    }
+
+    public static EventAssigner getInstance() {
+        if (_instance == null)
+            _instance = new EventAssigner();
+        return _instance;
+    }
+
+    @Override
+    public void assign(Event event) throws APIException {
+        if (event.mainEventId() != event.eventId() && event.mainEventId() > 0) {
+            JsonEvent jsonEvent = (JsonEvent) event;
+            jsonEvent.setMainEvent(
+                    cacheScore.getCachedEvent(
+                            event.mainEventId()
+                    )
+            );
+        }
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/EventsAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/EventsAssigner.java
new file mode 100644 (file)
index 0000000..d959a95
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+
+/**
+ * Assigner for Collections of Entities {@link Event}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventsAssigner
+        extends CacheCollectionAssigner<Event, Events, EventAssigner>
+{
+    private static EventsAssigner _instance;
+
+    private EventsAssigner() {
+        super(
+                EventAssigner.getInstance()
+        );
+    }
+
+    public static EventsAssigner getInstance() {
+        if (_instance == null)
+            _instance = new EventsAssigner();
+        return _instance;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/IdAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/IdAssigner.java
new file mode 100644 (file)
index 0000000..4bfd4d6
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Assigner for Entities Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface IdAssigner<E extends IdEntity> {
+
+    void assign(E entity) throws APIException;
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/MatchAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/MatchAssigner.java
new file mode 100644 (file)
index 0000000..5c2ac85
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.json.JsonMatch;
+
+/**
+ * Assigner for Entity fields of {@link Match}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class MatchAssigner extends CacheIdAssigner<Match> {
+
+    private static MatchAssigner _instance;
+
+    private MatchAssigner() {
+    }
+
+    public static MatchAssigner getInstance() {
+        if (_instance == null)
+            _instance = new MatchAssigner();
+        return _instance;
+    }
+
+    @Override
+    public void assign(Match match) throws APIException {
+        JsonMatch jsonMatch = (JsonMatch) match;
+        jsonMatch.setEvent(
+                cacheScore.getCachedEvent(
+                        match.eventId()
+                )
+        );
+        Player player1 = cacheScore.getCachedPlayer(
+                match.player1Id()
+        );
+        Player player2 = cacheScore.getCachedPlayer(
+                match.player2Id()
+        );
+        jsonMatch.setPlayer1(player1);
+        jsonMatch.setPlayer2(player2);
+        jsonMatch.setWinner(
+                match.winnerId() == match.player1Id()
+                        ? player1
+                        : match.winnerId() == match.player2Id()
+                        ? player2
+                        : null
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/MatchesAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/MatchesAssigner.java
new file mode 100644 (file)
index 0000000..e0a1323
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Matches;
+import org.hedgecode.snooker.api.OngoingMatch;
+import org.hedgecode.snooker.api.OngoingMatches;
+
+/**
+ * Assigner for Collections of Entities {@link Match}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class MatchesAssigner
+        extends CacheCollectionAssigner<Match, Matches, MatchAssigner>
+{
+    private static MatchesAssigner _instance;
+
+    private MatchesAssigner() {
+        super(
+                MatchAssigner.getInstance()
+        );
+    }
+
+    public static MatchesAssigner getInstance() {
+        if (_instance == null)
+            _instance =  new MatchesAssigner();
+        return _instance;
+    }
+
+    public void assign(OngoingMatches matches) throws APIException {
+        for (OngoingMatch match : matches) {
+            assigner().assign(
+                    match
+            );
+        }
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/RankingAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/RankingAssigner.java
new file mode 100644 (file)
index 0000000..bfe84cd
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.json.JsonRanking;
+
+/**
+ * Assigner for Entity fields of {@link Ranking}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RankingAssigner extends CacheIdAssigner<Ranking> {
+
+    private static RankingAssigner _instance;
+
+    private RankingAssigner() {
+    }
+
+    public static RankingAssigner getInstance() {
+        if (_instance == null)
+            _instance = new RankingAssigner();
+        return _instance;
+    }
+
+    @Override
+    public void assign(Ranking ranking) throws APIException {
+        JsonRanking jsonRanking = (JsonRanking) ranking;
+        jsonRanking.setPlayer(
+                cacheScore.getCachedPlayer(
+                        ranking.playerId()
+                )
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/cache/assign/RankingsAssigner.java b/src/main/java/org/hedgecode/snooker/cache/assign/RankingsAssigner.java
new file mode 100644 (file)
index 0000000..d3751dd
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.api.Rankings;
+
+/**
+ * Assigner for Collections of Entities {@link Ranking}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RankingsAssigner
+        extends CacheCollectionAssigner<Ranking, Rankings, RankingAssigner>
+{
+    private static RankingsAssigner _instance;
+
+    private RankingsAssigner() {
+        super(
+                RankingAssigner.getInstance()
+        );
+    }
+
+    public static RankingsAssigner getInstance() {
+        if (_instance == null)
+            _instance = new RankingsAssigner();
+        return _instance;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/compare/EventComparators.java b/src/main/java/org/hedgecode/snooker/compare/EventComparators.java
new file mode 100644 (file)
index 0000000..481435d
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Event;
+
+/**
+ * Set of Comparators for {@link Event}.
+ * 1. Sorting by Date {@link DateComparator};
+ * 2. Sorting by WorldSnookerId {@link SnookerIdComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum EventComparators {
+
+    DATE       ( new DateComparator() ),
+    SNOOKER_ID ( new SnookerIdComparator() );
+
+    private Comparator<Event> comparator;
+
+    EventComparators(Comparator<Event> comparator) {
+        this.comparator = comparator;
+    }
+
+    public Comparator<Event> comparator() {
+        return comparator;
+    }
+
+    static class DateComparator implements Comparator<Event> {
+
+        @Override
+        public int compare(Event event1, Event event2) {
+            return event1.startDate().compareTo(event2.startDate());
+        }
+
+    }
+
+    static class SnookerIdComparator implements Comparator<Event> {
+
+        @Override
+        public int compare(Event event1, Event event2) {
+            return event1.worldSnookerId() - event2.worldSnookerId();
+        }
+
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/compare/MatchComparators.java b/src/main/java/org/hedgecode/snooker/compare/MatchComparators.java
new file mode 100644 (file)
index 0000000..939b1bc
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Match;
+
+/**
+ * Set of Comparators for {@link Match}.
+ * 1. Sorting by Round and Number of Match {@link RoundNumberComparator};
+ * 2. Sorting by Event {@link EventComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum MatchComparators {
+
+    ROUND_NUMBER ( new RoundNumberComparator() ),
+    EVENT        ( new EventComparator() );
+
+    private Comparator<Match> comparator;
+
+    MatchComparators(Comparator<Match> comparator) {
+        this.comparator = comparator;
+    }
+
+    public Comparator<Match> comparator() {
+        return comparator;
+    }
+
+    static class RoundNumberComparator implements Comparator<Match> {
+
+        @Override
+        public int compare(Match match1, Match match2) {
+            return match1.round() == match2.round()
+                    ? match1.number() - match2.round()
+                    : match2.round() - match1.round();
+        }
+
+    }
+
+    static class EventComparator implements Comparator<Match> {
+
+        @Override
+        public int compare(Match match1, Match match2) {
+            return match1.eventId() - match2.eventId();
+        }
+
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/compare/PlayerComparators.java b/src/main/java/org/hedgecode/snooker/compare/PlayerComparators.java
new file mode 100644 (file)
index 0000000..834f2e7
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Player;
+
+/**
+ * Set of Comparators for {@link Player}.
+ * 1. Sorting by Last Name of Player {@link NameComparator};
+ * 2. Sorting by Age of Player {@link AgeComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum PlayerComparators {
+
+    NAME ( new NameComparator() ),
+    AGE  ( new AgeComparator() );
+
+    private Comparator<Player> comparator;
+
+    PlayerComparators(Comparator<Player> comparator) {
+        this.comparator = comparator;
+    }
+
+    public Comparator<Player> comparator() {
+        return comparator;
+    }
+
+    static class NameComparator implements Comparator<Player> {
+
+        @Override
+        public int compare(Player player1, Player player2) {
+            return player1.lastName().compareTo(player2.lastName());
+        }
+
+    }
+
+    static class AgeComparator implements Comparator<Player> {
+
+        @Override
+        public int compare(Player player1, Player player2) {
+            return player1.born().compareTo(player2.born());
+        }
+
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/compare/RankingComparators.java b/src/main/java/org/hedgecode/snooker/compare/RankingComparators.java
new file mode 100644 (file)
index 0000000..f7551e0
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Ranking;
+
+/**
+ * Set of Comparators for {@link Ranking}.
+ * 1. Sorting by Player Position {@link PositionComparator};
+ * 2. Sorting by Player Earned Money {@link SumComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum RankingComparators {
+
+    POSITION ( new PositionComparator() ),
+    SUM      ( new SumComparator() );
+
+    private Comparator<Ranking> comparator;
+
+    RankingComparators(Comparator<Ranking> comparator) {
+        this.comparator = comparator;
+    }
+
+    public Comparator<Ranking> comparator() {
+        return comparator;
+    }
+
+    static class PositionComparator implements Comparator<Ranking> {
+
+        @Override
+        public int compare(Ranking ranking1, Ranking ranking2) {
+            return ranking1.position() - ranking2.position();
+        }
+
+    }
+
+    static class SumComparator implements Comparator<Ranking> {
+
+        @Override
+        public int compare(Ranking ranking1, Ranking ranking2) {
+            return ranking1.sum() < ranking2.sum()
+                    ? 1 : ranking1.sum() > ranking2.sum()? -1 : 0;
+        }
+
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java b/src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java
new file mode 100644 (file)
index 0000000..5c625c5
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.gson;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.internal.bind.util.ISO8601Utils;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * GSON Adapter for Date including a check for an empty string.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class EmptyDateTypeAdapter extends TypeAdapter<Date> {
+
+    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
+        @SuppressWarnings("unchecked")
+        @Override
+        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
+            return typeToken.getRawType() == Date.class
+                    ? (TypeAdapter<T>) new EmptyDateTypeAdapter()
+                    : null;
+        }
+    };
+
+    private final DateFormat enUsFormat =
+            DateFormat.getDateTimeInstance(
+                    DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US
+            );
+    private final DateFormat localFormat =
+            DateFormat.getDateTimeInstance(
+                    DateFormat.DEFAULT, DateFormat.DEFAULT
+            );
+
+    @Override
+    public Date read(JsonReader in) throws IOException {
+        if (in.peek() == JsonToken.NULL) {
+            in.nextNull();
+            return null;
+        }
+        return deserializeToDate(in.nextString());
+    }
+
+    private synchronized Date deserializeToDate(String json) {
+        if (json.isEmpty())
+            return null;
+        try {
+            return localFormat.parse(json);
+        } catch (ParseException ignored) {
+        }
+        try {
+            return enUsFormat.parse(json);
+        } catch (ParseException ignored) {
+        }
+        try {
+            return ISO8601Utils.parse(json, new ParsePosition(0));
+        } catch (ParseException ignored) {
+        }
+        try {
+            return new Date(Long.parseLong(json));
+        } catch (Exception e) {
+            throw new JsonSyntaxException(json, e);
+        }
+    }
+
+    @Override
+    public synchronized void write(JsonWriter out, Date value) throws IOException {
+        if (value == null) {
+            out.nullValue();
+        } else {
+            String dateFormatAsString = enUsFormat.format(value);
+            out.value(dateFormatAsString);
+        }
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/gson/SnookerGsonBuilder.java b/src/main/java/org/hedgecode/snooker/gson/SnookerGsonBuilder.java
new file mode 100644 (file)
index 0000000..07718fb
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.gson;
+
+import java.util.Date;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * Builder to construct a {@link Gson} instance.
+ *
+ * @see EmptyDateTypeAdapter
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class SnookerGsonBuilder {
+
+    private static final GsonBuilder GSON_BUILDER =
+            new GsonBuilder().registerTypeAdapter(
+                    Date.class, new EmptyDateTypeAdapter()
+            );
+
+    public static Gson build() {
+        return GSON_BUILDER.create();
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonCollectionEntity.java b/src/main/java/org/hedgecode/snooker/json/JsonCollectionEntity.java
new file mode 100644 (file)
index 0000000..3223323
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.hedgecode.snooker.api.CollectionEntity;
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Abstract Collection Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class JsonCollectionEntity<E extends IdEntity>
+        implements CollectionEntity<E>, JsonSerializable
+{
+    private final Map<Integer, E> entities = new LinkedHashMap<>();
+
+    protected JsonCollectionEntity(E[] entities) {
+        for (E entity : entities) {
+            if (entity != null)
+                this.entities.put(entity.getId(), entity);
+        }
+    }
+
+    protected JsonCollectionEntity(List<E> entities) {
+        for (E entity : entities) {
+            this.entities.put(entity.getId(), entity);
+        }
+    }
+
+    @Override
+    public int size() {
+        return entities.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return entities.isEmpty();
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return entities.values().iterator();
+    }
+
+    @Override
+    public E byId(int id) {
+        return entities.get(id);
+    }
+
+    protected void sort(Comparator<E> comparator) {
+        List<E> entityList = new LinkedList<>(entities.values());
+        Collections.sort(
+                entityList, comparator
+        );
+        entities.clear();
+        for (E entity : entityList) {
+            entities.put(entity.getId(), entity);
+        }
+    }
+
+    @Override
+    public void sortById() {
+        sort(
+                (entity1, entity2) -> entity1.getId() - entity2.getId()
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonEvent.java b/src/main/java/org/hedgecode/snooker/json/JsonEvent.java
new file mode 100644 (file)
index 0000000..2f47ee4
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.Date;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Event Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonEvent extends JsonIdEntity implements Event {
+
+    @SerializedName("ID")
+    private int eventId;
+    @SerializedName("Name")
+    private String name;
+    @SerializedName("StartDate")
+    private Date startDate;
+    @SerializedName("EndDate")
+    private Date endDate;
+    @SerializedName("Sponsor")
+    private String sponsor;
+    @SerializedName("Season")
+    private int seasonYear;
+    @Expose
+    private Season season;
+    @SerializedName("Type")
+    private String type;
+    @SerializedName("Num")
+    private int num;
+    @SerializedName("Venue")
+    private String venue;
+    @SerializedName("City")
+    private String city;
+    @SerializedName("Country")
+    private String country;
+    @SerializedName("Discipline")
+    private String discipline;
+    @SerializedName("Main")
+    private int mainEventId;
+    @Expose
+    private Event mainEvent;
+    @SerializedName("Sex")
+    private String sex;
+    @SerializedName("AgeGroup")
+    private String ageGroup;
+    @SerializedName("Url")
+    private String url;
+    @SerializedName("Related")
+    private String related;
+    @SerializedName("Stage")
+    private String stage;
+    @SerializedName("ValueType")
+    private String valueType;
+    @SerializedName("ShortName")
+    private String shortName;
+    @SerializedName("WorldSnookerId")
+    private int worldSnookerId;
+    @SerializedName("RankingType")
+    private String rankingType;
+    @SerializedName("EventPredictionID")
+    private int eventPredictionId;
+    @SerializedName("Team")
+    private boolean team;
+    @SerializedName("Format")
+    private int format;
+    @SerializedName("Twitter")
+    private String twitter;
+    @SerializedName("HashTag")
+    private String hashTag;
+    @SerializedName("ConversionRate")
+    private float conversionRate;
+    @SerializedName("AllRoundsAdded")
+    private boolean allRoundsAdded;
+    @SerializedName("PhotoURLs")
+    private String photoUrls;
+    @SerializedName("NumCompetitors")
+    private int numCompetitors;
+    @SerializedName("NumUpcoming")
+    private int numUpcoming;
+    @SerializedName("NumActive")
+    private int numActive;
+    @SerializedName("NumResults")
+    private int numResults;
+    @SerializedName("Note")
+    private String note;
+    @SerializedName("CommonNote")
+    private String commonNote;
+    @SerializedName("DefendingChampion")
+    private int defendingChampion;
+    @SerializedName("PreviousEdition")
+    private int previousEdition;
+
+    @Override
+    public int eventId() {
+        return eventId;
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public Date startDate() {
+        return startDate;
+    }
+
+    @Override
+    public Date endDate() {
+        return endDate;
+    }
+
+    @Override
+    public String sponsor() {
+        return sponsor;
+    }
+
+    @Override
+    public Season season() {
+        if (season == null)
+            season = Season.getSeason(seasonYear);
+        return season;
+    }
+
+    @Override
+    public String type() {
+        return type;
+    }
+
+    @Override
+    public int num() {
+        return num;
+    }
+
+    @Override
+    public String venue() {
+        return venue;
+    }
+
+    @Override
+    public String city() {
+        return city;
+    }
+
+    @Override
+    public String country() {
+        return country;
+    }
+
+    @Override
+    public String discipline() {
+        return discipline;
+    }
+
+    @Override
+    public int mainEventId() {
+        return mainEventId;
+    }
+
+    @Override
+    public Event mainEvent() {
+        if (mainEvent == null && mainEventId == eventId)
+            mainEvent = this;
+        return mainEvent;
+    }
+
+    public void setMainEvent(Event event) {
+        if (event != null && eventId == event.eventId())
+            mainEvent = event;
+    }
+
+    @Override
+    public String sex() {
+        return sex;
+    }
+
+    @Override
+    public String ageGroup() {
+        return ageGroup;
+    }
+
+    @Override
+    public String url() {
+        return url;
+    }
+
+    @Override
+    public String related() {
+        return related;
+    }
+
+    @Override
+    public String stage() {
+        return stage;
+    }
+
+    @Override
+    public String valueType() {
+        return valueType;
+    }
+
+    @Override
+    public String shortName() {
+        return shortName;
+    }
+
+    @Override
+    public int worldSnookerId() {
+        return worldSnookerId;
+    }
+
+    @Override
+    public String rankingType() {
+        return rankingType;
+    }
+
+    @Override
+    public int eventPredictionId() {
+        return eventPredictionId;
+    }
+
+    @Override
+    public boolean team() {
+        return team;
+    }
+
+    @Override
+    public int format() {
+        return format;
+    }
+
+    @Override
+    public String twitter() {
+        return twitter;
+    }
+
+    @Override
+    public String hashTag() {
+        return hashTag;
+    }
+
+    @Override
+    public float conversionRate() {
+        return conversionRate;
+    }
+
+    @Override
+    public boolean allRoundsAdded() {
+        return allRoundsAdded;
+    }
+
+    @Override
+    public String photoUrls() {
+        return photoUrls;
+    }
+
+    @Override
+    public int numCompetitors() {
+        return numCompetitors;
+    }
+
+    @Override
+    public int numUpcoming() {
+        return numUpcoming;
+    }
+
+    @Override
+    public int numActive() {
+        return numActive;
+    }
+
+    @Override
+    public int numResults() {
+        return numResults;
+    }
+
+    @Override
+    public String note() {
+        return note;
+    }
+
+    @Override
+    public String commonNote() {
+        return commonNote;
+    }
+
+    @Override
+    public int defendingChampion() {
+        return defendingChampion;
+    }
+
+    @Override
+    public int previousEdition() {
+        return previousEdition;
+    }
+
+    @Override
+    public int getId() {
+        return eventId;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonEvents.java b/src/main/java/org/hedgecode/snooker/json/JsonEvents.java
new file mode 100644 (file)
index 0000000..78474de
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+import org.hedgecode.snooker.api.Season;
+import org.hedgecode.snooker.compare.EventComparators;
+
+/**
+ * Events Entity (set of {@link Event}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonEvents extends JsonCollectionEntity<Event> implements Events {
+
+    protected JsonEvents(Event[] entities) {
+        super(entities);
+    }
+
+    protected JsonEvents(List<Event> entities) {
+        super(entities);
+    }
+
+    @Override
+    public Events bySeason(Season season) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.season().equals(season))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events byType(String type) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.type().equals(type))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events byCity(String city) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.city().equals(city))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events byCountry(String country) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.country().equals(country))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events bySex(String sex) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.sex().equals(sex))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events byStage(String stage) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.stage().equals(stage))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events byValueType(String valueType) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.valueType().equals(valueType))
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events bySnookerId(int worldSnookerId) {
+        List<Event> events = new ArrayList<>();
+        for (Event event : this)
+            if (event.worldSnookerId() == worldSnookerId)
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events ended() {
+        List<Event> events = new ArrayList<>();
+        long currentTime = System.currentTimeMillis();
+        for (Event event : this)
+            if (event.endDate().getTime() < currentTime)
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events current() {
+        List<Event> events = new ArrayList<>();
+        long currentTime = System.currentTimeMillis();
+        for (Event event : this)
+            if (event.startDate().getTime() < currentTime
+                    && event.endDate().getTime() > currentTime)
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public Events upcoming() {
+        List<Event> events = new ArrayList<>();
+        long currentTime = System.currentTimeMillis();
+        for (Event event : this)
+            if (event.startDate().getTime() > currentTime)
+                events.add(event);
+        return events.isEmpty() ? null : new JsonEvents(events);
+    }
+
+    @Override
+    public void sortByDate() {
+        sort(
+                EventComparators.DATE.comparator()
+        );
+    }
+
+    @Override
+    public void sortBySnookerId() {
+        sort(
+                EventComparators.SNOOKER_ID.comparator()
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonIdEntity.java b/src/main/java/org/hedgecode/snooker/json/JsonIdEntity.java
new file mode 100644 (file)
index 0000000..6b6c213
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Abstract Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class JsonIdEntity implements IdEntity, JsonSerializable {
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        IdEntity idEntity = (IdEntity) obj;
+        return getId() == idEntity.getId();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + getId();
+        return result;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonMatch.java b/src/main/java/org/hedgecode/snooker/json/JsonMatch.java
new file mode 100644 (file)
index 0000000..2731565
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.Date;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Player;
+
+/**
+ * Match Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonMatch extends JsonIdEntity implements Match {
+
+    @SerializedName("ID")
+    private int matchId;
+    @SerializedName("EventID")
+    private int eventId;
+    @Expose
+    private Event event;
+    @SerializedName("Round")
+    private int round;
+    @SerializedName("Number")
+    private int number;
+    @SerializedName("Player1ID")
+    private int player1Id;
+    @Expose
+    private Player player1;
+    @SerializedName("Score1")
+    private int score1;
+    @SerializedName("Walkover1")
+    private boolean walkover1;
+    @SerializedName("Player2ID")
+    private int player2Id;
+    @Expose
+    private Player player2;
+    @SerializedName("Score2")
+    private int score2;
+    @SerializedName("Walkover2")
+    private boolean walkover2;
+    @SerializedName("WinnerID")
+    private int winnerId;
+    @Expose
+    private Player winner;
+    @SerializedName("Unfinished")
+    private boolean unfinished;
+    @SerializedName("OnBreak")
+    private boolean onBreak;
+    @SerializedName("WorldSnookerID")
+    private int worldSnookerId;
+    @SerializedName("LiveUrl")
+    private String liveUrl;
+    @SerializedName("DetailsUrl")
+    private String detailsUrl;
+    @SerializedName("PointsDropped")
+    private boolean pointsDropped;
+    @SerializedName("ShowCommonNote")
+    private boolean showCommonNote;
+    @SerializedName("Estimated")
+    private boolean estimated;
+    @SerializedName("Type")
+    private int type;
+    @SerializedName("TableNo")
+    private int tableNo;
+    @SerializedName("VideoURL")
+    private String videoURL;
+    @SerializedName("InitDate")
+    private Date initDate;
+    @SerializedName("ModDate")
+    private Date modDate;
+    @SerializedName("StartDate")
+    private Date startDate;
+    @SerializedName("EndDate")
+    private Date endDate;
+    @SerializedName("ScheduledDate")
+    private Date scheduledDate;
+    @SerializedName("FrameScores")
+    private String frameScores;
+    @SerializedName("Sessions")
+    private String sessions;
+    @SerializedName("Note")
+    private String  note;
+    @SerializedName("ExtendedNote")
+    private String  extendedNote;
+
+    @Override
+    public int matchId() {
+        return matchId;
+    }
+
+    @Override
+    public int eventId() {
+        return eventId;
+    }
+
+    @Override
+    public Event event() {
+        return event;
+    }
+
+    public void setEvent(Event event) {
+        if (event != null && eventId == event.eventId())
+            this.event = event;
+    }
+
+    @Override
+    public int round() {
+        return round;
+    }
+
+    @Override
+    public int number() {
+        return number;
+    }
+
+    @Override
+    public int player1Id() {
+        return player1Id;
+    }
+
+    @Override
+    public Player player1() {
+        return player1;
+    }
+
+    public void setPlayer1(Player player) {
+        if (player != null && player1Id == player.playerId())
+            this.player1 = player;
+    }
+
+    @Override
+    public int score1() {
+        return score1;
+    }
+
+    @Override
+    public boolean walkover1() {
+        return walkover1;
+    }
+
+    @Override
+    public int player2Id() {
+        return player2Id;
+    }
+
+    @Override
+    public Player player2() {
+        return player2;
+    }
+
+    public void setPlayer2(Player player) {
+        if (player != null && player2Id == player.playerId())
+            this.player2 = player;
+    }
+
+    @Override
+    public int score2() {
+        return score2;
+    }
+
+    @Override
+    public boolean walkover2() {
+        return walkover2;
+    }
+
+    @Override
+    public int winnerId() {
+        return winnerId;
+    }
+
+    @Override
+    public Player winner() {
+        return winner;
+    }
+
+    public void setWinner(Player winner) {
+        if (winner != null && winnerId == winner.playerId())
+            this.winner = winner;
+    }
+
+    @Override
+    public boolean unfinished() {
+        return unfinished;
+    }
+
+    @Override
+    public boolean onBreak() {
+        return onBreak;
+    }
+
+    @Override
+    public int worldSnookerId() {
+        return worldSnookerId;
+    }
+
+    @Override
+    public String liveUrl() {
+        return liveUrl;
+    }
+
+    @Override
+    public String detailsUrl() {
+        return detailsUrl;
+    }
+
+    @Override
+    public boolean pointsDropped() {
+        return pointsDropped;
+    }
+
+    @Override
+    public boolean showCommonNote() {
+        return showCommonNote;
+    }
+
+    @Override
+    public boolean estimated() {
+        return estimated;
+    }
+
+    @Override
+    public int type() {
+        return type;
+    }
+
+    @Override
+    public int tableNo() {
+        return tableNo;
+    }
+
+    @Override
+    public String videoURL() {
+        return videoURL;
+    }
+
+    @Override
+    public Date initDate() {
+        return initDate;
+    }
+
+    @Override
+    public Date modDate() {
+        return modDate;
+    }
+
+    @Override
+    public Date startDate() {
+        return startDate;
+    }
+
+    @Override
+    public Date endDate() {
+        return endDate;
+    }
+
+    @Override
+    public Date scheduledDate() {
+        return scheduledDate;
+    }
+
+    @Override
+    public String frameScores() {
+        return frameScores;
+    }
+
+    @Override
+    public String sessions() {
+        return sessions;
+    }
+
+    @Override
+    public String note() {
+        return note;
+    }
+
+    @Override
+    public String extendedNote() {
+        return extendedNote;
+    }
+
+    @Override
+    public int getId() {
+        return matchId;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonMatches.java b/src/main/java/org/hedgecode/snooker/json/JsonMatches.java
new file mode 100644 (file)
index 0000000..0d4dd02
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Matches;
+import org.hedgecode.snooker.compare.MatchComparators;
+
+/**
+ * Matches Entity (set of {@link Match}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonMatches extends JsonCollectionEntity<Match> implements Matches {
+
+    protected JsonMatches(Match[] entities) {
+        super(entities);
+    }
+
+    protected JsonMatches(List<Match> entities) {
+        super(entities);
+    }
+
+    @Override
+    public Matches byEvent(int eventId) {
+        List<Match> matches = new ArrayList<>();
+        for (Match match : this)
+            if (match.eventId() == eventId)
+                matches.add(match);
+        return matches.isEmpty() ? null : new JsonMatches(matches);
+    }
+
+    @Override
+    public Matches byRound(int eventId, int round) {
+        List<Match> matches = new ArrayList<>();
+        for (Match match : this)
+            if (match.eventId() == eventId && match.round() == round)
+                matches.add(match);
+        return matches.isEmpty() ? null : new JsonMatches(matches);
+    }
+
+    @Override
+    public Matches byPlayer(int playerId) {
+        List<Match> matches = new ArrayList<>();
+        for (Match match : this)
+            if (match.player1Id() == playerId || match.player2Id() == playerId)
+                matches.add(match);
+        return matches.isEmpty() ? null : new JsonMatches(matches);
+    }
+
+    @Override
+    public Matches ended() {
+        List<Match> matches = new ArrayList<>();
+        for (Match match : this)
+            if (match.endDate() != null)
+                matches.add(match);
+        return matches.isEmpty() ? null : new JsonMatches(matches);
+    }
+
+    @Override
+    public Matches current() {
+        List<Match> matches = new ArrayList<>();
+        for (Match match : this)
+            if (match.startDate() != null && match.endDate() == null)
+                matches.add(match);
+        return matches.isEmpty() ? null : new JsonMatches(matches);
+    }
+
+    @Override
+    public Matches upcoming() {
+        List<Match> matches = new ArrayList<>();
+        for (Match match : this)
+            if (match.startDate() == null)
+                matches.add(match);
+        return matches.isEmpty() ? null : new JsonMatches(matches);
+    }
+
+    @Override
+    public void sortByNumber() {
+        sort(
+                MatchComparators.ROUND_NUMBER.comparator()
+        );
+    }
+
+    @Override
+    public void sortByEvent() {
+        sort(
+                MatchComparators.EVENT.comparator()
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonOngoingMatch.java b/src/main/java/org/hedgecode/snooker/json/JsonOngoingMatch.java
new file mode 100644 (file)
index 0000000..6e5cb1d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.OngoingMatch;
+
+/**
+ * Ongoing Match Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonOngoingMatch extends JsonMatch implements OngoingMatch {
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonOngoingMatches.java b/src/main/java/org/hedgecode/snooker/json/JsonOngoingMatches.java
new file mode 100644 (file)
index 0000000..7c18095
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.OngoingMatch;
+import org.hedgecode.snooker.api.OngoingMatches;
+
+/**
+ * Ongoing Matches Entity (set of {@link OngoingMatches}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonOngoingMatches
+        extends JsonCollectionEntity<OngoingMatch> implements OngoingMatches
+{
+    protected JsonOngoingMatches(OngoingMatch[] entities) {
+        super(entities);
+    }
+
+    @Override
+    public OngoingMatch byNumber(int number) {
+        for (OngoingMatch ongoingMatch : this)
+            if (ongoingMatch.number() == number)
+                return ongoingMatch;
+        return null;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonPlayer.java b/src/main/java/org/hedgecode/snooker/json/JsonPlayer.java
new file mode 100644 (file)
index 0000000..6db13d1
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.Date;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.snooker.api.Player;
+
+/**
+ * Player Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonPlayer extends JsonIdEntity implements Player {
+
+    @SerializedName("ID")
+    private int playerId;
+    @SerializedName("Type")
+    private int type;
+    @SerializedName("FirstName")
+    private String firstName;
+    @SerializedName("MiddleName")
+    private String middleName;
+    @SerializedName("LastName")
+    private String lastName;
+    @SerializedName("TeamName")
+    private String teamName;
+    @SerializedName("TeamNumber")
+    private int teamNumber;
+    @SerializedName("TeamSeason")
+    private int teamSeason;
+    @SerializedName("ShortName")
+    private String shortName;
+    @SerializedName("Nationality")
+    private String nationality;
+    @SerializedName("Sex")
+    private String sex;
+    @SerializedName("BioPage")
+    private String bioPage;
+    @SerializedName("Born")
+    private Date born;
+    @SerializedName("Twitter")
+    private String twitter;
+    @SerializedName("SurnameFirst")
+    private boolean surnameFirst;
+    @SerializedName("License")
+    private String license;
+    @SerializedName("Club")
+    private String club;
+    @SerializedName("URL")
+    private String url;
+    @SerializedName("Photo")
+    private String photo;
+    @SerializedName("Info")
+    private String info;
+
+    @Override
+    public int playerId() {
+        return playerId;
+    }
+
+    @Override
+    public int type() {
+        return type;
+    }
+
+    @Override
+    public String firstName() {
+        return firstName;
+    }
+
+    @Override
+    public String middleName() {
+        return middleName;
+    }
+
+    @Override
+    public String lastName() {
+        return lastName;
+    }
+
+    @Override
+    public String teamName() {
+        return teamName;
+    }
+
+    @Override
+    public int teamNumber() {
+        return teamNumber;
+    }
+
+    @Override
+    public int teamSeason() {
+        return teamSeason;
+    }
+
+    @Override
+    public String shortName() {
+        return shortName;
+    }
+
+    @Override
+    public String nationality() {
+        return nationality;
+    }
+
+    @Override
+    public String sex() {
+        return sex;
+    }
+
+    @Override
+    public String bioPage() {
+        return bioPage;
+    }
+
+    @Override
+    public Date born() {
+        return born;
+    }
+
+    @Override
+    public String twitter() {
+        return twitter;
+    }
+
+    @Override
+    public boolean surnameFirst() {
+        return surnameFirst;
+    }
+
+    @Override
+    public String license() {
+        return license;
+    }
+
+    @Override
+    public String club() {
+        return club;
+    }
+
+    @Override
+    public String url() {
+        return url;
+    }
+
+    @Override
+    public String photo() {
+        return photo;
+    }
+
+    @Override
+    public String info() {
+        return info;
+    }
+
+    @Override
+    public int getId() {
+        return playerId;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonPlayers.java b/src/main/java/org/hedgecode/snooker/json/JsonPlayers.java
new file mode 100644 (file)
index 0000000..26c68e2
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.api.Players;
+import org.hedgecode.snooker.compare.PlayerComparators;
+
+/**
+ * Players Entity (set of {@link Player}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonPlayers extends JsonCollectionEntity<Player> implements Players {
+
+    protected JsonPlayers(Player[] entities) {
+        super(entities);
+    }
+
+    protected JsonPlayers(List<Player> entities) {
+        super(entities);
+    }
+
+    @Override
+    public Players byType(int type) {
+        List<Player> players = new ArrayList<>();
+        for (Player player : this)
+            if (player.type() == type)
+                players.add(player);
+        return players.isEmpty() ? null : new JsonPlayers(players);
+    }
+
+    @Override
+    public Players byName(String name) {
+        List<Player> players = new ArrayList<>();
+        for (Player player : this)
+            if (player.shortName().contains(name))
+                players.add(player);
+        return players.isEmpty() ? null : new JsonPlayers(players);
+    }
+
+    @Override
+    public Players byNationality(String nationality) {
+        List<Player> players = new ArrayList<>();
+        for (Player player : this)
+            if (player.nationality().equals(nationality))
+                players.add(player);
+        return players.isEmpty() ? null : new JsonPlayers(players);
+    }
+
+    @Override
+    public Players bySex(String sex) {
+        List<Player> players = new ArrayList<>();
+        for (Player player : this)
+            if (player.nationality().equals(sex))
+                players.add(player);
+        return players.isEmpty() ? null : new JsonPlayers(players);
+    }
+
+    @Override
+    public void sortByName() {
+        sort(
+                PlayerComparators.NAME.comparator()
+        );
+    }
+
+    @Override
+    public void sortByAge() {
+        sort(
+                PlayerComparators.AGE.comparator()
+        );
+    }
+
+    @Override
+    public void sortByAgeDesc() {
+        sort(
+                PlayerComparators.AGE.comparator().reversed()
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonRanking.java b/src/main/java/org/hedgecode/snooker/json/JsonRanking.java
new file mode 100644 (file)
index 0000000..02e08f5
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.api.RankingType;
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Ranking Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonRanking extends JsonIdEntity implements Ranking {
+
+    @SerializedName("ID")
+    private int rankingId;
+    @SerializedName("Position")
+    private int position;
+    @SerializedName("PlayerID")
+    private int playerId;
+    @Expose
+    private Player player;
+    @SerializedName("Season")
+    private int seasonYear;
+    @Expose
+    private Season season;
+    @SerializedName("Sum")
+    private long sum;
+    @SerializedName("Type")
+    private String type;
+    @Expose
+    private RankingType rankingType;
+
+    @Override
+    public int rankingId() {
+        return rankingId;
+    }
+
+    @Override
+    public int position() {
+        return position;
+    }
+
+    @Override
+    public int playerId() {
+        return playerId;
+    }
+
+    @Override
+    public Player player() {
+        return player;
+    }
+
+    public void setPlayer(Player player) {
+        if (player != null && playerId == player.playerId())
+            this.player = player;
+    }
+
+    @Override
+    public Season season() {
+        if (season == null)
+            season = Season.getSeason(seasonYear);
+        return season;
+    }
+
+    @Override
+    public long sum() {
+        return sum;
+    }
+
+    @Override
+    public RankingType rankingType() {
+        if (rankingType == null)
+            rankingType = RankingType.byName(type);
+        return rankingType;
+    }
+
+    @Override
+    public int getId() {
+        return rankingId;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonRankings.java b/src/main/java/org/hedgecode/snooker/json/JsonRankings.java
new file mode 100644 (file)
index 0000000..75a3358
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.api.Rankings;
+import org.hedgecode.snooker.compare.RankingComparators;
+
+/**
+ * Rankings Entity (set of {@link Ranking}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonRankings extends JsonCollectionEntity<Ranking> implements Rankings {
+
+    protected JsonRankings(Ranking[] entities) {
+        super(entities);
+    }
+
+    protected JsonRankings(List<Ranking> entities) {
+        super(entities);
+    }
+
+    @Override
+    public Ranking byPlayer(int playerId) {
+        for (Ranking ranking : this)
+            if (ranking.playerId() == playerId)
+                return ranking;
+        return null;
+    }
+
+    @Override
+    public Rankings bySum(long minSum, long maxSum) {
+        List<Ranking> rankings = new ArrayList<>();
+        for (Ranking ranking : this)
+            if (ranking.sum() >= minSum && ranking.sum() <= maxSum)
+                rankings.add(ranking);
+        return rankings.isEmpty() ? null : new JsonRankings(rankings);
+    }
+
+    @Override
+    public void sortByPosition() {
+        sort(
+                RankingComparators.POSITION.comparator()
+        );
+    }
+
+    @Override
+    public void sortBySum() {
+        sort(
+                RankingComparators.SUM.comparator()
+        );
+    }
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonSerializable.java b/src/main/java/org/hedgecode/snooker/json/JsonSerializable.java
new file mode 100644 (file)
index 0000000..8d7db08
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.io.Serializable;
+
+/**
+ * Dummy Interface to Serializable Objects.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface JsonSerializable extends Serializable {
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonSnookerScore.java b/src/main/java/org/hedgecode/snooker/json/JsonSnookerScore.java
new file mode 100644 (file)
index 0000000..aa27161
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import com.google.gson.Gson;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Matches;
+import org.hedgecode.snooker.api.OngoingMatches;
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.api.PlayerCategory;
+import org.hedgecode.snooker.api.Players;
+import org.hedgecode.snooker.api.RankingType;
+import org.hedgecode.snooker.api.Rankings;
+import org.hedgecode.snooker.api.Season;
+import org.hedgecode.snooker.api.SnookerScoreAPI;
+import org.hedgecode.snooker.gson.SnookerGsonBuilder;
+import org.hedgecode.snooker.request.RequestException;
+import org.hedgecode.snooker.request.RequestParams;
+import org.hedgecode.snooker.request.RequestType;
+
+/**
+ * Implementation of Interface {@link SnookerScoreAPI}
+ * with deserialize from input JSON strings.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonSnookerScore implements SnookerScoreAPI {
+
+    public static final int UNKNOWN_PLAYER_ID = 376;
+
+    private final Gson GSON = SnookerGsonBuilder.build();
+
+    private static JsonSnookerScore _instance;
+
+    public static JsonSnookerScore getInstance() {
+        if (_instance == null)
+            _instance = new JsonSnookerScore();
+        return _instance;
+    }
+
+    protected JsonSnookerScore() {
+    }
+
+    @Override
+    public Event getEvent(int eventId) throws APIException {
+        Event[] events;
+        try {
+            events = GSON.fromJson(
+                    JsonStringToken.token(
+                            RequestType.request(RequestType.EVENT, eventId)
+                    ),
+                    JsonEvent[].class
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return events.length > 0 ? events[0] : null;
+    }
+
+    @Override
+    public Match getMatch(int eventId, int roundId, int matchNumber) throws APIException {
+        Match[] matches;
+        try {
+            matches = GSON.fromJson(
+                    JsonStringToken.token(
+                            RequestType.request(
+                                    RequestType.MATCH,
+                                    new RequestParams(
+                                            eventId, roundId, matchNumber
+                                    )
+                            )
+                    ),
+                    JsonMatch[].class
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return matches.length > 0 ? matches[0] : null;
+    }
+
+    @Override
+    public Player getPlayer(int playerId) throws APIException {
+        Player[] players;
+        try {
+            players = GSON.fromJson(
+                    JsonStringToken.token(
+                            RequestType.request(RequestType.PLAYER, playerId)
+                    ),
+                    JsonPlayer[].class
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return players.length > 0 ? players[0] : null;
+    }
+
+    @Override
+    public Events getSeasonEvents(Season season) throws APIException {
+        Events events;
+        try {
+            events = new JsonEvents(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.SEASON_EVENTS,
+                                            new RequestParams(
+                                                    RequestType.SEASON_EVENTS, 0, season
+                                            )
+                                    )
+                            ),
+                            JsonEvent[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return events;
+    }
+
+    @Override
+    public Matches getEventMatches(int eventId) throws APIException {
+        Matches matches;
+        try {
+            matches = new JsonMatches(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.EVENT_MATCHES,
+                                            eventId
+                                    )
+                            ),
+                            JsonMatch[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return matches;
+    }
+
+    @Override
+    public OngoingMatches getOngoingMatches() throws APIException {
+        OngoingMatches ongoingMatches;
+        try {
+            ongoingMatches = new JsonOngoingMatches(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.ONGOING_MATCHES,
+                                            null
+                                    )
+                            ),
+                            JsonOngoingMatch[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return ongoingMatches;
+    }
+
+    @Override
+    public Matches getPlayerMatches(int playerId, Season season) throws APIException {
+        Matches matches;
+        try {
+            matches = new JsonMatches(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.PLAYER_MATCHES,
+                                            new RequestParams(
+                                                    RequestType.PLAYER_MATCHES, playerId, season
+                                            )
+                                    )
+                            ),
+                            JsonMatch[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return matches;
+    }
+
+    @Override
+    public Players getEventPlayers(int eventId) throws APIException {
+        Players players;
+        try {
+            players = new JsonPlayers(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.EVENT_PLAYERS,
+                                            eventId
+                                    )
+                            ),
+                            JsonPlayer[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return players;
+    }
+
+    @Override
+    public Players getPlayers(Season season, PlayerCategory category) throws APIException {
+        Players players;
+        try {
+            players = new JsonPlayers(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.SEASON_PLAYERS,
+                                            new RequestParams(
+                                                    season, category
+                                            )
+                                    )
+                            ),
+                            JsonPlayer[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return players;
+    }
+
+    @Override
+    public Rankings getRankings(Season season, RankingType type) throws APIException {
+        Rankings rankings;
+        try {
+            rankings = new JsonRankings(
+                    GSON.fromJson(
+                            JsonStringToken.token(
+                                    RequestType.request(
+                                            RequestType.RANKING,
+                                            new RequestParams(
+                                                    season, type
+                                            )
+                                    )
+                            ),
+                            JsonRanking[].class
+                    )
+            );
+        } catch (RequestException e) {
+            throw new APIException(
+                    APIException.Type.REQUEST, e.getMessage()
+            );
+        }
+        return rankings;
+    }
+
+    @Override
+    public void setCurrentSeason(Season season) throws APIException {
+        throw new APIException(
+                APIException.Type.INFO, "This feature is only available in Cached API"
+        );
+    }
+
+    @Override
+    public Season currentSeason() throws APIException {
+        throw new APIException(
+                APIException.Type.INFO, "This feature is only available in Cached API"
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/json/JsonStringToken.java b/src/main/java/org/hedgecode/snooker/json/JsonStringToken.java
new file mode 100644 (file)
index 0000000..b7dd25a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+/**
+ * Null checking Token for parsing input JSON strings.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class JsonStringToken {
+
+    private static final String NULL_QUOTES_TOKEN = "\"\"";
+    private static final String NULL_JSON = "[null]";
+
+    private JsonStringToken() {
+    }
+
+    public static String token(String json) {
+        if (json == null || json.isEmpty() || NULL_QUOTES_TOKEN.equals(json))
+            return NULL_JSON;
+        return json;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/AbstractRequester.java b/src/main/java/org/hedgecode/snooker/request/AbstractRequester.java
new file mode 100644 (file)
index 0000000..a127bb5
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * Abstract Data Requester from the portal api.snooker.org.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class AbstractRequester implements Requester {
+
+    protected static final String API_SNOOKER_URL = "http://api.snooker.org/";
+
+    protected abstract String getRequestUrl(int id) throws RequestException;
+
+    protected abstract String getRequestUrl(RequestParams params) throws RequestException;
+
+    @Override
+    public String request(int id) throws RequestException {
+        return _request(
+                getRequestUrl(id)
+        );
+    }
+
+    @Override
+    public String request(RequestParams params) throws RequestException {
+        return _request(
+                getRequestUrl(params)
+        );
+    }
+
+    private String _request(String requestUrl) throws RequestException {
+        StringBuilder result = new StringBuilder();
+        try {
+            URL url = new URL(requestUrl);
+            URLConnection urlConnection = url.openConnection();
+            BufferedReader br = new BufferedReader(
+                    new InputStreamReader(
+                            urlConnection.getInputStream()
+                    )
+            );
+            String inputLine;
+            while ((inputLine = br.readLine()) != null) {
+                result.append(inputLine);
+            }
+            br.close();
+        } catch (IOException e) {
+            throw new RequestException(requestUrl, e.getMessage());
+        }
+        return result.toString();
+    }
+
+    protected boolean isCorrectId(int id) {
+        return id > 0;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/EventMatchesRequester.java b/src/main/java/org/hedgecode/snooker/request/EventMatchesRequester.java
new file mode 100644 (file)
index 0000000..c3315be
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of Matches of an Event.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventMatchesRequester extends AbstractRequester {
+
+    private static final String EVENT_MATCHES_URL = API_SNOOKER_URL + "?t=6&e=[EventID]";
+
+    private static final Requester _instance = new EventMatchesRequester();
+
+    private EventMatchesRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        if (!isCorrectId(id))
+            throw new RequestException(EVENT_MATCHES_URL, "Incorrect Event ID");
+
+        return EVENT_MATCHES_URL.replace(
+                "[EventID]", String.valueOf(id)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null || !isCorrectId(params.getEventId()))
+            throw new RequestException(EVENT_MATCHES_URL, "Incorrect Event ID");
+
+        return EVENT_MATCHES_URL.replace(
+                "[EventID]", String.valueOf(params.getEventId())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/EventPlayersRequester.java b/src/main/java/org/hedgecode/snooker/request/EventPlayersRequester.java
new file mode 100644 (file)
index 0000000..fe4722a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of Players in an Event.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventPlayersRequester extends AbstractRequester {
+
+    private static final String EVENT_PLAYERS_URL = API_SNOOKER_URL + "?t=9&e=[EventID]";
+
+    private static final Requester _instance = new EventPlayersRequester();
+
+    private EventPlayersRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        if (!isCorrectId(id))
+            throw new RequestException(EVENT_PLAYERS_URL, "Incorrect Event ID");
+
+        return EVENT_PLAYERS_URL.replace(
+                "[EventID]", String.valueOf(id)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null || !isCorrectId(params.getEventId()))
+            throw new RequestException(EVENT_PLAYERS_URL, "Incorrect Event ID");
+
+        return EVENT_PLAYERS_URL.replace(
+                "[EventID]", String.valueOf(params.getEventId())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/EventRequester.java b/src/main/java/org/hedgecode/snooker/request/EventRequester.java
new file mode 100644 (file)
index 0000000..09df212
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of an Event by ID.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventRequester extends AbstractRequester {
+
+    private static final String EVENT_URL = API_SNOOKER_URL + "?e=[EventID]";
+
+    private static final Requester _instance = new EventRequester();
+
+    private EventRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        if (!isCorrectId(id))
+            throw new RequestException(EVENT_URL, "Incorrect Event ID");
+
+        return EVENT_URL.replace(
+                "[EventID]", String.valueOf(id)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null || !isCorrectId(params.getEventId()))
+            throw new RequestException(EVENT_URL, "Incorrect Event ID");
+
+        return EVENT_URL.replace(
+                "[EventID]", String.valueOf(params.getEventId())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/MatchRequester.java b/src/main/java/org/hedgecode/snooker/request/MatchRequester.java
new file mode 100644 (file)
index 0000000..e2005f4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of a Match by Event, Round and Number.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class MatchRequester extends AbstractRequester {
+
+    private static final String MATCH_URL =
+            API_SNOOKER_URL + "?e=[EventID]&r=[RoundID]&n=[MatchNumber]";
+
+    private static final Requester _instance = new MatchRequester();
+
+    private MatchRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        throw new RequestException(MATCH_URL, "Incorrect Match Params");
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null
+                || !isCorrectId(params.getEventId())
+                || !isCorrectId(params.getRoundId())
+                || !isCorrectId(params.getMatchNumber()))
+            throw new RequestException(MATCH_URL, "Incorrect Match Params");
+
+        return MATCH_URL.replace(
+                "[EventID]", String.valueOf(params.getEventId())
+        ).replace(
+                "[RoundID]", String.valueOf(params.getRoundId())
+        ).replace(
+                "[MatchNumber]", String.valueOf(params.getMatchNumber())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/OngoingMatchesRequester.java b/src/main/java/org/hedgecode/snooker/request/OngoingMatchesRequester.java
new file mode 100644 (file)
index 0000000..b78b88f
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of Ongoing Matches.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class OngoingMatchesRequester extends AbstractRequester {
+
+    private static final String ONGOING_MATCHES_URL = API_SNOOKER_URL + "?t=7";
+
+    private static final Requester _instance = new OngoingMatchesRequester();
+
+    private OngoingMatchesRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        return ONGOING_MATCHES_URL;
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        return ONGOING_MATCHES_URL;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/PlayerMatchesRequester.java b/src/main/java/org/hedgecode/snooker/request/PlayerMatchesRequester.java
new file mode 100644 (file)
index 0000000..3de47c5
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Requester of Matches for a Player in a Season.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class PlayerMatchesRequester extends AbstractRequester {
+
+    private static final String PLAYER_MATCHES_URL =
+            API_SNOOKER_URL + "?t=8&p=[PlayerID]&s=[Season]";
+
+    private static final Requester _instance = new PlayerMatchesRequester();
+
+    private PlayerMatchesRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        if (!isCorrectId(id))
+            throw new RequestException(PLAYER_MATCHES_URL, "Incorrect Player ID");
+
+        return PLAYER_MATCHES_URL.replace(
+                "[PlayerID]", String.valueOf(id)
+        ).replace(
+                "[Season]", String.valueOf(Season.CURRENT_YEAR)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null
+                || !isCorrectId(params.getPlayerId())
+                || params.getSeason() == null)
+            throw new RequestException(PLAYER_MATCHES_URL, "Incorrect Player Params");
+
+        return PLAYER_MATCHES_URL.replace(
+                "[PlayerID]", String.valueOf(params.getPlayerId())
+        ).replace(
+                "[Season]", String.valueOf(params.getSeason().getYear())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/PlayerRequester.java b/src/main/java/org/hedgecode/snooker/request/PlayerRequester.java
new file mode 100644 (file)
index 0000000..46b7656
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of a Player by ID.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class PlayerRequester extends AbstractRequester {
+
+    private static final String PLAYER_URL = API_SNOOKER_URL + "?p=[PlayerID]";
+
+    private static final Requester _instance = new PlayerRequester();
+
+    private PlayerRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        if (!isCorrectId(id))
+            throw new RequestException(PLAYER_URL, "Incorrect Player ID");
+
+        return PLAYER_URL.replace(
+                "[PlayerID]", String.valueOf(id)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null || !isCorrectId(params.getPlayerId()))
+            throw new RequestException(PLAYER_URL, "Incorrect Player ID");
+
+        return PLAYER_URL.replace(
+                "[PlayerID]", String.valueOf(params.getPlayerId())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/RankingRequester.java b/src/main/java/org/hedgecode/snooker/request/RankingRequester.java
new file mode 100644 (file)
index 0000000..b9255dc
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester of Player Money Rankings.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RankingRequester extends AbstractRequester {
+
+    private static final String RANKING_URL =
+            API_SNOOKER_URL + "?rt=[RankingType]&s=[Season]";
+
+    private static final Requester _instance = new RankingRequester();
+
+    private RankingRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        throw new RequestException(RANKING_URL, "Incorrect Ranking Params");
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null
+                || params.getRankingType() == null
+                || params.getSeason() == null)
+            throw new RequestException(RANKING_URL, "Incorrect Ranking Params");
+
+        return RANKING_URL.replace(
+                "[RankingType]", params.getRankingType().name()
+        ).replace(
+                "[Season]", String.valueOf(params.getSeason().getYear())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/RequestException.java b/src/main/java/org/hedgecode/snooker/request/RequestException.java
new file mode 100644 (file)
index 0000000..a227a9f
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Exception for information about request errors.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RequestException extends Exception {
+
+    private String requestUrl;
+
+    public RequestException(String requestUrl, String message) {
+        super(message);
+        this.requestUrl = requestUrl;
+    }
+
+    public String getRequestUrl() {
+        return requestUrl;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/RequestParams.java b/src/main/java/org/hedgecode/snooker/request/RequestParams.java
new file mode 100644 (file)
index 0000000..a11da9b
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+import org.hedgecode.snooker.api.PlayerCategory;
+import org.hedgecode.snooker.api.RankingType;
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Input Params for Request.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RequestParams {
+
+    private int playerId;
+    private int eventId;
+    private int roundId;
+    private int matchNumber;
+    private Season season;
+    private PlayerCategory category;
+    private RankingType rankingType;
+
+    public RequestParams(RequestType type, int id, Season season) {
+        switch (type) {
+            case PLAYER:
+                this.playerId = id;
+                break;
+            case PLAYER_MATCHES:
+                this.playerId = id;
+                this.season = season;
+                break;
+            case EVENT:
+            case EVENT_MATCHES:
+            case EVENT_PLAYERS:
+                this.eventId = id;
+                break;
+            case SEASON_EVENTS:
+                this.season = season;
+                break;
+        }
+    }
+
+    public RequestParams(int eventId, int roundId, int matchNumber) {
+        this.eventId = eventId;
+        this.roundId = roundId;
+        this.matchNumber = matchNumber;
+    }
+
+    public RequestParams(Season season, PlayerCategory category) {
+        this.season = season;
+        this.category = category;
+    }
+
+    public RequestParams(Season season, RankingType rankingType) {
+        this.season = season;
+        this.rankingType = rankingType;
+    }
+
+    public int getPlayerId() {
+        return playerId;
+    }
+
+    public void setPlayerId(int playerId) {
+        this.playerId = playerId;
+    }
+
+    public int getEventId() {
+        return eventId;
+    }
+
+    public void setEventId(int eventId) {
+        this.eventId = eventId;
+    }
+
+    public int getRoundId() {
+        return roundId;
+    }
+
+    public void setRoundId(int roundId) {
+        this.roundId = roundId;
+    }
+
+    public int getMatchNumber() {
+        return matchNumber;
+    }
+
+    public void setMatchNumber(int matchNumber) {
+        this.matchNumber = matchNumber;
+    }
+
+    public Season getSeason() {
+        return season;
+    }
+
+    public void setSeason(Season season) {
+        this.season = season;
+    }
+
+    public PlayerCategory getCategory() {
+        return category;
+    }
+
+    public void setCategory(PlayerCategory category) {
+        this.category = category;
+    }
+
+    public RankingType getRankingType() {
+        return rankingType;
+    }
+
+    public void setRankingType(RankingType rankingType) {
+        this.rankingType = rankingType;
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/RequestType.java b/src/main/java/org/hedgecode/snooker/request/RequestType.java
new file mode 100644 (file)
index 0000000..d62bbb1
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Set of Types to Request.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum RequestType {
+
+    EVENT           ( EventRequester.getInstance()          ),
+    MATCH           ( MatchRequester.getInstance()          ),
+    PLAYER          ( PlayerRequester.getInstance()         ),
+    SEASON_EVENTS   ( SeasonEventsRequester.getInstance()   ),
+    EVENT_MATCHES   ( EventMatchesRequester.getInstance()   ),
+    ONGOING_MATCHES ( OngoingMatchesRequester.getInstance() ),
+    PLAYER_MATCHES  ( PlayerMatchesRequester.getInstance()  ),
+    EVENT_PLAYERS   ( EventPlayersRequester.getInstance()   ),
+    SEASON_PLAYERS  ( SeasonPlayersRequester.getInstance()  ),
+    RANKING         ( RankingRequester.getInstance()        );
+
+    private Requester requester;
+
+    RequestType(Requester requester) {
+        this.requester = requester;
+    }
+
+    public Requester requester() {
+        return requester;
+    }
+
+    public static String request(RequestType type, int id)
+            throws RequestException
+    {
+        if (type == null)
+            throw new RequestException(null, "Incorrect Request Type");
+        return type.requester().request(id);
+    }
+
+    public static String request(RequestType type, RequestParams params)
+            throws RequestException
+    {
+        if (type == null)
+            throw new RequestException(null, "Incorrect Request Type");
+        return type.requester().request(params);
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/Requester.java b/src/main/java/org/hedgecode/snooker/request/Requester.java
new file mode 100644 (file)
index 0000000..6cb8003
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+/**
+ * Requester Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Requester {
+
+    String request(int id) throws RequestException;
+
+    String request(RequestParams params) throws RequestException;
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/SeasonEventsRequester.java b/src/main/java/org/hedgecode/snooker/request/SeasonEventsRequester.java
new file mode 100644 (file)
index 0000000..ff548f1
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Requester of Events in a Season.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class SeasonEventsRequester extends AbstractRequester {
+
+    private static final String SEASON_EVENTS_URL = API_SNOOKER_URL + "?t=5&s=[Season]";
+
+    private static final Requester _instance = new SeasonEventsRequester();
+
+    private SeasonEventsRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        return SEASON_EVENTS_URL.replace(
+                "[Season]", String.valueOf(Season.CURRENT_YEAR)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null || params.getSeason() == null)
+            throw new RequestException(SEASON_EVENTS_URL, "Incorrect Season");
+
+        return SEASON_EVENTS_URL.replace(
+                "[Season]", String.valueOf(params.getSeason().getYear())
+        );
+    }
+
+}
diff --git a/src/main/java/org/hedgecode/snooker/request/SeasonPlayersRequester.java b/src/main/java/org/hedgecode/snooker/request/SeasonPlayersRequester.java
new file mode 100644 (file)
index 0000000..e5b204d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.request;
+
+import org.hedgecode.snooker.api.PlayerCategory;
+import org.hedgecode.snooker.api.Season;
+
+/**
+ * Requester of Players in a Season.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class SeasonPlayersRequester extends AbstractRequester {
+
+    private static final String SEASON_PLAYERS_URL =
+            API_SNOOKER_URL + "?t=10&st=[Category]&s=[Season]";
+
+    private static final Requester _instance = new SeasonPlayersRequester();
+
+    private SeasonPlayersRequester() {
+    }
+
+    public static Requester getInstance() {
+        return _instance;
+    }
+
+    @Override
+    protected String getRequestUrl(int id) throws RequestException {
+        return SEASON_PLAYERS_URL.replace(
+                "[Category]", PlayerCategory.PRO.letter()
+        ).replace(
+                "[Season]", String.valueOf(Season.CURRENT_YEAR)
+        );
+    }
+
+    @Override
+    protected String getRequestUrl(RequestParams params) throws RequestException {
+        if (params == null
+                || params.getCategory() == null
+                || params.getSeason() == null)
+            throw new RequestException(SEASON_PLAYERS_URL, "Incorrect Players Params");
+
+        return SEASON_PLAYERS_URL.replace(
+                "[Category]", params.getCategory().letter()
+        ).replace(
+                "[Season]", String.valueOf(params.getSeason().getYear())
+        );
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/api/SeasonTest.java b/src/test/java/org/hedgecode/snooker/api/SeasonTest.java
new file mode 100644 (file)
index 0000000..0c618af
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.api;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link Season}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class SeasonTest extends Assert {
+
+    @Test
+    public void testSeason() throws Exception {
+        assertNull(
+                Season.getSeason(
+                        Season.BEGIN_YEAR - 1
+                )
+        );
+        assertNull(
+                Season.getSeason(
+                        Season.CURRENT_YEAR + 1
+                )
+        );
+        for (int year = Season.BEGIN_YEAR; year <= Season.CURRENT_YEAR; ++year) {
+            Season season = Season.getSeason(year);
+            assertNotNull(season);
+            assertEquals(year, season.getYear());
+        }
+        assertEquals(
+                Season.ALL,
+                Season.getSeason(-1)
+        );
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/AbstractJsonTest.java b/src/test/java/org/hedgecode/snooker/json/AbstractJsonTest.java
new file mode 100644 (file)
index 0000000..0ef6fa6
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import com.google.gson.Gson;
+
+import org.hedgecode.snooker.gson.SnookerGsonBuilder;
+
+import org.junit.Assert;
+
+/**
+ * Abstract Test class with input JSON from file.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class AbstractJsonTest extends Assert {
+
+    private static final String JSON_EXT = ".json";
+    private static final String SERIALIZE_EXT = ".ser";
+
+    protected static final Gson GSON = SnookerGsonBuilder.build();
+
+    private final File jsonFile =
+            new File(
+                    getClass().getResource(
+                            getClass().getSimpleName() + JSON_EXT
+                    ).getFile()
+            );
+    private final File serFile =
+            new File(
+                    jsonFile.getParent() + File.separator
+                            + getClass().getSimpleName() + SERIALIZE_EXT
+            );
+
+    public static void assertNull(JsonIdEntity expected, JsonIdEntity[] actuals) {
+        if (actuals.length == 1 && actuals[0] == null) {
+                assertNull(expected);
+        }
+    }
+
+    protected String jsonFromFile() throws IOException {
+        StringBuilder sb = new StringBuilder();
+        try (BufferedReader br =
+                     new BufferedReader(
+                             new FileReader(
+                                     jsonFile.getAbsolutePath()
+                             )
+                     )
+        ) {
+            String line = br.readLine();
+            while (line != null) {
+                sb.append(line);
+                line = br.readLine();
+            }
+        }
+        return sb.toString();
+    }
+
+    protected void serialize(JsonSerializable jsonObject) throws IOException {
+        try (ObjectOutputStream oos =
+                     new ObjectOutputStream(
+                             new FileOutputStream(
+                                     serFile.getAbsolutePath()
+                             )
+                     )
+        ) {
+            oos.writeObject(jsonObject);
+        }
+    }
+
+    protected JsonSerializable deserialize() throws IOException, ClassNotFoundException {
+        JsonSerializable jsonObject;
+        try (ObjectInputStream ois =
+                     new ObjectInputStream(
+                             new FileInputStream(
+                                     serFile.getAbsolutePath()
+                             )
+                     )
+        ) {
+            jsonObject = (JsonSerializable) ois.readObject();
+        }
+        return jsonObject;
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonEventTest.java b/src/test/java/org/hedgecode/snooker/json/JsonEventTest.java
new file mode 100644 (file)
index 0000000..0262013
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonEvent}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonEventTest extends AbstractJsonTest {
+
+    @Test
+    public void testEvent() throws Exception {
+        JsonEvent[] jsonEvents = GSON.fromJson(
+                JsonStringToken.token(
+                        jsonFromFile()
+                ),
+                JsonEvent[].class
+        );
+        //serialize(jsonEvents[0]);
+        JsonEvent expectedEvent = (JsonEvent) deserialize();
+        assertNull(
+                expectedEvent,
+                jsonEvents
+        );
+        JsonEvent actualEvent = jsonEvents[0];
+        assertEquals(
+                expectedEvent,
+                actualEvent
+        );
+    }
+
+    public static void assertEquals(JsonEvent expected, JsonEvent actual) {
+        assertEquals(expected.eventId(), actual.eventId());
+        assertEquals(expected.name(), actual.name());
+        assertEquals(expected.startDate(), actual.startDate());
+        assertEquals(expected.endDate(), actual.endDate());
+        assertEquals(expected.sponsor(), actual.sponsor());
+        assertEquals(expected.season(), actual.season());
+        assertEquals(expected.type(), actual.type());
+        assertEquals(expected.num(), actual.num());
+        assertEquals(expected.venue(), actual.venue());
+        assertEquals(expected.city(), actual.city());
+        assertEquals(expected.country(), actual.country());
+        assertEquals(expected.discipline(), actual.discipline());
+        assertEquals(expected.mainEventId(), actual.mainEventId());
+        assertEquals(expected.mainEvent(), actual.mainEvent());
+        assertEquals(expected.sex(), actual.sex());
+        assertEquals(expected.ageGroup(), actual.ageGroup());
+        assertEquals(expected.url(), actual.url());
+        assertEquals(expected.related(), actual.related());
+        assertEquals(expected.stage(), actual.stage());
+        assertEquals(expected.valueType(), actual.valueType());
+        assertEquals(expected.shortName(), actual.shortName());
+        assertEquals(expected.worldSnookerId(), actual.worldSnookerId());
+        assertEquals(expected.rankingType(), actual.rankingType());
+        assertEquals(expected.eventPredictionId(), actual.eventPredictionId());
+        assertEquals(expected.team(), actual.team());
+        assertEquals(expected.format(), actual.format());
+        assertEquals(expected.twitter(), actual.twitter());
+        assertEquals(expected.hashTag(), actual.hashTag());
+        assertEquals(expected.conversionRate(), actual.conversionRate(), 0.001);
+        assertEquals(expected.allRoundsAdded(), actual.allRoundsAdded());
+        assertEquals(expected.photoUrls(), actual.photoUrls());
+        assertEquals(expected.numCompetitors(), actual.numCompetitors());
+        assertEquals(expected.numUpcoming(), actual.numUpcoming());
+        assertEquals(expected.numActive(), actual.numActive());
+        assertEquals(expected.numResults(), actual.numResults());
+        assertEquals(expected.note(), actual.note());
+        assertEquals(expected.commonNote(), actual.commonNote());
+        assertEquals(expected.defendingChampion(), actual.defendingChampion());
+        assertEquals(expected.previousEdition(), actual.previousEdition());
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonEventsTest.java b/src/test/java/org/hedgecode/snooker/json/JsonEventsTest.java
new file mode 100644 (file)
index 0000000..8a238f6
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.Event;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonEvents}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonEventsTest extends AbstractJsonTest {
+
+    @Test
+    public void testEvents() throws Exception {
+        JsonEvents actualEvents = new JsonEvents(
+                GSON.fromJson(
+                        JsonStringToken.token(
+                                jsonFromFile()
+                        ),
+                        JsonEvent[].class
+                )
+        );
+        //serialize(actualEvents);
+        JsonEvents expectedEvents = (JsonEvents) deserialize();
+        assertEquals(
+                expectedEvents,
+                actualEvents
+        );
+    }
+
+    public static void assertEquals(JsonEvents expecteds, JsonEvents actuals) {
+        assertEquals(
+                expecteds.size(),
+                actuals.size()
+        );
+        for (Event expected : expecteds) {
+            JsonEventTest.assertEquals(
+                    (JsonEvent) expected,
+                    (JsonEvent) actuals.byId(expected.getId())
+            );
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonMatchTest.java b/src/test/java/org/hedgecode/snooker/json/JsonMatchTest.java
new file mode 100644 (file)
index 0000000..0895582
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonMatch}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonMatchTest extends AbstractJsonTest {
+
+    @Test
+    public void testMatch() throws Exception {
+        JsonMatch[] jsonMatches = GSON.fromJson(
+                JsonStringToken.token(
+                        jsonFromFile()
+                ),
+                JsonMatch[].class
+        );
+        //serialize(jsonMatches[0]);
+        JsonMatch expectedMatch = (JsonMatch) deserialize();
+        assertNull(
+                expectedMatch,
+                jsonMatches
+        );
+        JsonMatch actualMatch = jsonMatches[0];
+        assertEquals(
+                expectedMatch,
+                actualMatch
+        );
+    }
+
+    public static void assertEquals(JsonMatch expected, JsonMatch actual) {
+        assertEquals(expected.matchId(), actual.matchId());
+        assertEquals(expected.eventId(), actual.eventId());
+        assertEquals(expected.round(), actual.round());
+        assertEquals(expected.number(), actual.number());
+        assertEquals(expected.player1Id(), actual.player1Id());
+        assertEquals(expected.score1(), actual.score1());
+        assertEquals(expected.walkover1(), actual.walkover1());
+        assertEquals(expected.player2Id(), actual.player2Id());
+        assertEquals(expected.score2(), actual.score2());
+        assertEquals(expected.walkover2(), actual.walkover2());
+        assertEquals(expected.winnerId(), actual.winnerId());
+        assertEquals(expected.unfinished(), actual.unfinished());
+        assertEquals(expected.onBreak(), actual.onBreak());
+        assertEquals(expected.worldSnookerId(), actual.worldSnookerId());
+        assertEquals(expected.liveUrl(), actual.liveUrl());
+        assertEquals(expected.detailsUrl(), actual.detailsUrl());
+        assertEquals(expected.pointsDropped(), actual.pointsDropped());
+        assertEquals(expected.showCommonNote(), actual.showCommonNote());
+        assertEquals(expected.estimated(), actual.estimated());
+        assertEquals(expected.type(), actual.type());
+        assertEquals(expected.tableNo(), actual.tableNo());
+        assertEquals(expected.videoURL(), actual.videoURL());
+        assertEquals(expected.initDate(), actual.initDate());
+        assertEquals(expected.modDate(), actual.modDate());
+        assertEquals(expected.startDate(), actual.startDate());
+        assertEquals(expected.endDate(), actual.endDate());
+        assertEquals(expected.scheduledDate(), actual.scheduledDate());
+        assertEquals(expected.frameScores(), actual.frameScores());
+        assertEquals(expected.sessions(), actual.sessions());
+        assertEquals(expected.note(), actual.note());
+        assertEquals(expected.extendedNote(), actual.extendedNote());
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonMatchesTest.java b/src/test/java/org/hedgecode/snooker/json/JsonMatchesTest.java
new file mode 100644 (file)
index 0000000..acc2656
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.Match;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonMatches}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonMatchesTest extends AbstractJsonTest {
+
+    @Test
+    public void testMatches() throws Exception {
+        JsonMatches actualMatches = new JsonMatches(
+                GSON.fromJson(
+                        JsonStringToken.token(
+                                jsonFromFile()
+                        ),
+                        JsonMatch[].class
+                )
+        );
+        //serialize(actualMatches);
+        JsonMatches expectedMatches = (JsonMatches) deserialize();
+        assertEquals(
+                expectedMatches,
+                actualMatches
+        );
+    }
+
+    public static void assertEquals(JsonMatches expecteds, JsonMatches actuals) {
+        assertEquals(
+                expecteds.size(),
+                actuals.size()
+        );
+        for (Match expected : expecteds) {
+            JsonMatchTest.assertEquals(
+                    (JsonMatch) expected,
+                    (JsonMatch) actuals.byId(expected.getId())
+            );
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchTest.java b/src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchTest.java
new file mode 100644 (file)
index 0000000..faca10e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonOngoingMatch}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonOngoingMatchTest extends JsonMatchTest {
+
+    @Test
+    public void testOngoingMatch() throws Exception {
+        JsonOngoingMatch[] jsonOngoingMatches = GSON.fromJson(
+                JsonStringToken.token(
+                        jsonFromFile()
+                ),
+                JsonOngoingMatch[].class
+        );
+        //serialize(jsonOngoingMatches[0]);
+        JsonOngoingMatch expectedOngoingMatch = (JsonOngoingMatch) deserialize();
+        assertNull(
+                expectedOngoingMatch,
+                jsonOngoingMatches
+        );
+        JsonOngoingMatch actualOngoingMatch = jsonOngoingMatches[0];
+        assertEquals(
+                expectedOngoingMatch,
+                actualOngoingMatch
+        );
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchesTest.java b/src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchesTest.java
new file mode 100644 (file)
index 0000000..590d6f7
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.Match;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonOngoingMatches}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonOngoingMatchesTest extends AbstractJsonTest {
+
+    @Test
+    public void testOngoingMatches() throws Exception {
+        JsonOngoingMatches actualOngoingMatches = new JsonOngoingMatches(
+                GSON.fromJson(
+                        JsonStringToken.token(
+                                jsonFromFile()
+                        ),
+                        JsonOngoingMatch[].class
+                )
+        );
+        //serialize(actualOngoingMatches);
+        JsonOngoingMatches expectedOngoingMatches = (JsonOngoingMatches) deserialize();
+        assertEquals(
+                expectedOngoingMatches,
+                actualOngoingMatches
+        );
+    }
+
+    public static void assertEquals(JsonOngoingMatches expecteds, JsonOngoingMatches actuals) {
+        assertEquals(
+                expecteds.size(),
+                actuals.size()
+        );
+        for (Match expected : expecteds) {
+            JsonMatchTest.assertEquals(
+                    (JsonMatch) expected,
+                    (JsonMatch) actuals.byId(expected.getId())
+            );
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonPlayerTest.java b/src/test/java/org/hedgecode/snooker/json/JsonPlayerTest.java
new file mode 100644 (file)
index 0000000..9b3ae63
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonPlayer}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonPlayerTest extends AbstractJsonTest {
+
+    @Test
+    public void testPlayer() throws Exception {
+        JsonPlayer[] jsonPlayers = GSON.fromJson(
+                JsonStringToken.token(
+                        jsonFromFile()
+                ),
+                JsonPlayer[].class
+        );
+        //serialize(jsonPlayers[0]);
+        JsonPlayer expectedPlayer = (JsonPlayer) deserialize();
+        assertNull(
+                expectedPlayer,
+                jsonPlayers
+        );
+        JsonPlayer actualPlayer = jsonPlayers[0];
+        assertEquals(
+                expectedPlayer,
+                actualPlayer
+        );
+    }
+
+    public static void assertEquals(JsonPlayer expected, JsonPlayer actual) {
+        assertEquals(expected.playerId(), actual.playerId());
+        assertEquals(expected.type(), actual.type());
+        assertEquals(expected.firstName(), actual.firstName());
+        assertEquals(expected.middleName(), actual.middleName());
+        assertEquals(expected.lastName(), actual.lastName());
+        assertEquals(expected.teamName(), actual.teamName());
+        assertEquals(expected.teamNumber(), actual.teamNumber());
+        assertEquals(expected.teamSeason(), actual.teamSeason());
+        assertEquals(expected.shortName(), actual.shortName());
+        assertEquals(expected.nationality(), actual.nationality());
+        assertEquals(expected.sex(), actual.sex());
+        assertEquals(expected.bioPage(), actual.bioPage());
+        assertEquals(expected.born(), actual.born());
+        assertEquals(expected.twitter(), actual.twitter());
+        assertEquals(expected.surnameFirst(), actual.surnameFirst());
+        assertEquals(expected.license(), actual.license());
+        assertEquals(expected.club(), actual.club());
+        assertEquals(expected.url(), actual.url());
+        assertEquals(expected.photo(), actual.photo());
+        assertEquals(expected.info(), actual.info());
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonPlayersTest.java b/src/test/java/org/hedgecode/snooker/json/JsonPlayersTest.java
new file mode 100644 (file)
index 0000000..cae5606
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.Player;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonPlayers}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonPlayersTest extends AbstractJsonTest {
+
+    @Test
+    public void testPlayers() throws Exception {
+        JsonPlayers actualPlayers = new JsonPlayers(
+                GSON.fromJson(
+                        JsonStringToken.token(
+                                jsonFromFile()
+                        ),
+                        JsonPlayer[].class
+                )
+        );
+        //serialize(actualPlayers);
+        JsonPlayers expectedPlayers = (JsonPlayers) deserialize();
+        assertEquals(
+                expectedPlayers,
+                actualPlayers
+        );
+    }
+
+    public static void assertEquals(JsonPlayers expecteds, JsonPlayers actuals) {
+        assertEquals(
+                expecteds.size(),
+                actuals.size()
+        );
+        for (Player expected : expecteds) {
+            JsonPlayerTest.assertEquals(
+                    (JsonPlayer) expected,
+                    (JsonPlayer) actuals.byId(expected.getId())
+            );
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonRankingTest.java b/src/test/java/org/hedgecode/snooker/json/JsonRankingTest.java
new file mode 100644 (file)
index 0000000..6dcf4c7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonRanking}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonRankingTest extends AbstractJsonTest {
+
+    @Test
+    public void testRanking() throws Exception {
+        JsonRanking[] jsonRankings = GSON.fromJson(
+                JsonStringToken.token(
+                        jsonFromFile()
+                ),
+                JsonRanking[].class
+        );
+        //serialize(jsonRankings[0]);
+        JsonRanking expectedRanking = (JsonRanking) deserialize();
+        assertNull(
+                expectedRanking,
+                jsonRankings
+        );
+        JsonRanking actualRanking = jsonRankings[0];
+        assertEquals(
+                expectedRanking,
+                actualRanking
+        );
+    }
+
+    public static void assertEquals(JsonRanking expected, JsonRanking actual) {
+        assertEquals(expected.rankingId(), actual.rankingId());
+        assertEquals(expected.position(), actual.position());
+        assertEquals(expected.playerId(), actual.playerId());
+        assertEquals(expected.season(), actual.season());
+        assertEquals(expected.sum(), actual.sum());
+        assertEquals(expected.rankingType(), actual.rankingType());
+    }
+
+}
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonRankingsTest.java b/src/test/java/org/hedgecode/snooker/json/JsonRankingsTest.java
new file mode 100644 (file)
index 0000000..7f1e953
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.Ranking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonRankings}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonRankingsTest extends AbstractJsonTest {
+
+    @Test
+    public void testRankings() throws Exception {
+        JsonRankings actualRankings = new JsonRankings(
+                GSON.fromJson(
+                        JsonStringToken.token(
+                                jsonFromFile()
+                        ),
+                        JsonRanking[].class
+                )
+        );
+        //serialize(actualRankings);
+        JsonRankings expectedRankings = (JsonRankings) deserialize();
+        assertEquals(
+                expectedRankings,
+                actualRankings
+        );
+    }
+
+    public static void assertEquals(JsonRankings expecteds, JsonRankings actuals) {
+        assertEquals(
+                expecteds.size(),
+                actuals.size()
+        );
+        for (Ranking expected : expecteds) {
+            JsonRankingTest.assertEquals(
+                    (JsonRanking) expected,
+                    (JsonRanking) actuals.byId(expected.getId())
+            );
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/hedgecode/snooker/json/JsonStringTokenTest.java b/src/test/java/org/hedgecode/snooker/json/JsonStringTokenTest.java
new file mode 100644 (file)
index 0000000..202a672
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * 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 org.hedgecode.snooker.json;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for {@link JsonStringToken}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+@RunWith(JUnit4.class)
+public class JsonStringTokenTest extends Assert {
+
+    private static final String[] NULL_JSONS = {null, "", "\"\""};
+    private static final String[] NOT_NULL_JSONS = {"[{{\"ID\": 1}]", "blabla", "[null]"};
+
+    private static final String NULL_JSON = "[null]";
+
+    @Test
+    public void testToken() throws Exception {
+        for (String json : NULL_JSONS) {
+            assertEquals(
+                    NULL_JSON,
+                    JsonStringToken.token(json)
+            );
+        }
+        for (String json : NOT_NULL_JSONS) {
+            assertEquals(
+                    json,
+                    JsonStringToken.token(json)
+            );
+        }
+    }
+
+}
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonEventTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonEventTest.json
new file mode 100644 (file)
index 0000000..2c1ec93
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 531,"Name": "Masters","StartDate": "2017-01-15","EndDate": "2017-01-22","Sponsor": "Dafabet","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Alexandra Palace","City": "London","Country": "England","Discipline": "snooker","Main": 531,"Sex": "Both","AgeGroup": "O","Url": "","Related": "masters","Stage": "F","ValueType": "Masters","ShortName": "","WorldSnookerId": 13913,"RankingType": "","EventPredictionID": 2630,"Team": false,"Format": 1,"Twitter": "","HashTag": "DafabetMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 8,"NumActive": 1,"NumResults": 6,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.bbc.co.uk\u002Fiplayer\u0022>BBC<\u002Fa>, <a href=\u0022http:\u002F\u002Feurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 5,"PreviousEdition": 417}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonEventTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonEventTest.ser
new file mode 100644 (file)
index 0000000..3723494
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonEventTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.json
new file mode 100644 (file)
index 0000000..42711b5
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 528,"Name": "Indian Open Qualifiers","StartDate": "2016-05-28","EndDate": "2016-05-30","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 514,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "IO","ShortName": "","WorldSnookerId": 13898,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 510,"Name": "World Open Qualifiers","StartDate": "2016-05-31","EndDate": "2016-06-02","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 537,"Sex": "Both","AgeGroup": "O","Url": "","Related": "cc","Stage": "Q","ValueType": "CC","ShortName": "","WorldSnookerId": 13900,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 513,"Name": "Riga Masters Qualifiers","StartDate": "2016-06-03","EndDate": "2016-06-04","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 515,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "Q","ValueType": "","ShortName": "","WorldSnookerId": 13901,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 515,"Name": "Riga Masters","StartDate": "2016-06-22","EndDate": "2016-06-24","Sponsor": "Kaspersky","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Arena Riga","City": "Riga","Country": "Latvia","Discipline": "snooker","Main": 515,"Sex": "Both","AgeGroup": "O","Url": "https:\u002F\u002Fwww.facebook.com\u002FTheRigaOpen","Related": "ptc","Stage": "F","ValueType": "RM","ShortName": "","WorldSnookerId": 13902,"RankingType": "WR","EventPredictionID": 2601,"Team": false,"Format": 1,"Twitter": "","HashTag": "RigaOpen","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 63,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and\u002For selected betting sites","DefendingChampion": 16,"PreviousEdition": 397},{"ID": 514,"Name": "Indian Open","StartDate": "2016-07-05","EndDate": "2016-07-09","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "HICC Novotel Hotel","City": "Hyderabad","Country": "India","Discipline": "snooker","Main": 514,"Sex": "Both","AgeGroup": "","Url": "","Related": "","Stage": "F","ValueType": "IO","ShortName": "","WorldSnookerId": 13898,"RankingType": "WR","EventPredictionID": 2602,"Team": false,"Format": 1,"Twitter": "","HashTag": "IndianOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 134,"NumUpcoming": 0,"NumActive": 0,"NumResults": 69,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 171,"PreviousEdition": 349},{"ID": 537,"Name": "World Open","StartDate": "2016-07-25","EndDate": "2016-07-31","Sponsor": "Hanteng Autos","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Yushan Number One Middle School ","City": "Yushan","Country": "China","Discipline": "snooker","Main": 537,"Sex": "Both","AgeGroup": "O","Url": "","Related": "hwo","Stage": "F","ValueType": "HWO","ShortName": "","WorldSnookerId": 13900,"RankingType": "WR","EventPredictionID": 2603,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 132,"NumUpcoming": 0,"NumActive": 0,"NumResults": 67,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 97,"PreviousEdition": 285},{"ID": 518,"Name": "Paul Hunter Classic ","StartDate": "2016-08-24","EndDate": "2016-08-28","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Stadthalle","City": "FГјrth","Country": "Germany","Discipline": "snooker","Main": 518,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "F","ValueType": "PHC","ShortName": "","WorldSnookerId": 13904,"RankingType": "WR","EventPredictionID": 2604,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 242,"NumUpcoming": 0,"NumActive": 0,"NumResults": 241,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 158,"PreviousEdition": 399},{"ID": 572,"Name": "Paul Hunter Ladies Classic, Group A","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, A","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 573,"Name": "Paul Hunter Ladies Classic, Group B","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, B","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 577,"Name": "Paul Hunter Ladies Classic, Group F","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, F","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 578,"Name": "Paul Hunter Ladies Classic, Group G","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, G","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 579,"Name": "Paul Hunter Ladies Classic, Group H","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, H","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 575,"Name": "Paul Hunter Ladies Classic, Group D","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, D","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 576,"Name": "Paul Hunter Ladies Classic, Group E","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, E","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 574,"Name": "Paul Hunter Ladies Classic, Group C","StartDate": "2016-08-25","EndDate": "2016-08-26","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, C","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 570,"Name": "Paul Hunter Ladies Classic","StartDate": "2016-08-25","EndDate": "2016-08-28","Sponsor": "","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "http:\u002F\u002Fwww.mysnookerstats.com\u002Ftournament\u002Ftrn468\u002F","Related": "phl","Stage": "F","ValueType": "PHLC","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 31,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 519,"Name": "Shanghai Masters Qualifiers","StartDate": "2016-08-30","EndDate": "2016-09-02","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Barnsley Metrodome","City": "Barnsley","Country": "England","Discipline": "snooker","Main": 516,"Sex": "Both","AgeGroup": "O","Url": "","Related": "shanghai","Stage": "Q","ValueType": "SM","ShortName": "","WorldSnookerId": 13905,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerShanghaiMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 96,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 561,"Name": "6 Red World Championship, Group C","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, C","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 559,"Name": "6 Red World Championship, Group A","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, A","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 560,"Name": "6 Red World Championship Group B","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "6RED","ShortName": "6 Red, B","WorldSnookerId": 0,"RankingType": "Unknown","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 562,"Name": "6 Red World Championship, Group D","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, D","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 564,"Name": "6 Red World Championship, Group E","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, E","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 565,"Name": "6 Red World Championship, Group F","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, F","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 566,"Name": "6 Red World Championship, Group G","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, G","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 567,"Name": "6 Red World Championship, Group H","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Unknown","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, H","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 520,"Name": "6 Red World Championship","StartDate": "2016-09-05","EndDate": "2016-09-10","Sponsor": "SangSom","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.thailandsnooker.org\u002Fdata\u002Fschedules\u002Ffiles\u002F1473417993_51.pdf","Related": "6red","Stage": "F","ValueType": "6RED","ShortName": "","WorldSnookerId": 0,"RankingType": "Unknown","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 48,"NumUpcoming": 0,"NumActive": 0,"NumResults": 31,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 217,"PreviousEdition": 402},{"ID": 516,"Name": "Shanghai Masters","StartDate": "2016-09-19","EndDate": "2016-09-25","Sponsor": "Bank of Communications OTO","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Shanghai Grand Stage","City": "Shanghai","Country": "China","Discipline": "snooker","Main": 516,"Sex": "Both","AgeGroup": "O","Url": "","Related": "shanghai","Stage": "F","ValueType": "SM","ShortName": "","WorldSnookerId": 13906,"RankingType": "WR","EventPredictionID": 2605,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerShanghaiMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 136,"NumUpcoming": 0,"NumActive": 0,"NumResults": 39,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 39,"PreviousEdition": 403},{"ID": 558,"Name": "European Masters Qualifiers","StartDate": "2016-09-26","EndDate": "2016-09-28","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 511,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "EM","ShortName": "","WorldSnookerId": 13925,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 96,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 512,"Name": "International Championship Qualifiers","StartDate": "2016-09-29","EndDate": "2016-10-01","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 517,"Sex": "Both","AgeGroup": "O","Url": "","Related": "international","Stage": "Q","ValueType": "IC","ShortName": "","WorldSnookerId": 13920,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "InternationalChampionship","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 511,"Name": "European Masters","StartDate": "2016-10-03","EndDate": "2016-10-09","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Circul Globus","City": "Bucharest","Country": "Romania","Discipline": "snooker","Main": 511,"Sex": "Both","AgeGroup": "O","Url": "","Related": "European","Stage": "F","ValueType": "EM","ShortName": "","WorldSnookerId": 13925,"RankingType": "WR","EventPredictionID": 2606,"Team": false,"Format": 1,"Twitter": "","HashTag": "EuropeanMasters","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 31,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 585,"Name": "UK Ladies Championship, Group E","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, E","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 586,"Name": "UK Ladies Championship, Group F","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, F","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 587,"Name": "UK Ladies Championship, Group G","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, G","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 588,"Name": "UK Ladies Championship, Group H","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, H","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 581,"Name": "UK Ladies Championship, Group A","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, A","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 582,"Name": "UK Ladies Championship, Group B","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, B","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 583,"Name": "UK Ladies Championship, Group C","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, C","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 584,"Name": "UK Ladies Championship, Group D","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, D","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 580,"Name": "UK Ladies Championship","StartDate": "2016-10-08","EndDate": "2016-10-09","Sponsor": "LITEtask","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "http:\u002F\u002Fwww.mysnookerstats.com\u002Ftournament\u002Ftrn481\u002F","Related": "","Stage": "F","ValueType": "UKL","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 26,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "Watch on <a href=\u0022https:\u002F\u002Fwww.youtube.com\u002Fc\u002FMysnookerstats\u002Flive\u0022>YouTube<\u002Fa>","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 522,"Name": "English Open","StartDate": "2016-10-10","EndDate": "2016-10-16","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Event City","City": "Manchester","Country": "England","Discipline": "snooker","Main": 522,"Sex": "Both","AgeGroup": "O","Url": "","Related": "Home Nations Series","Stage": "F","ValueType": "EO","ShortName": "","WorldSnookerId": 13910,"RankingType": "WR","EventPredictionID": 2607,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>, <a href=\u0022http:\u002F\u002Fquesttv.co.uk\u002F\u0022>Quest<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 517,"Name": "International Championship","StartDate": "2016-10-23","EndDate": "2016-10-30","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Baihu Media Broadcasting Centre","City": "Daqing","Country": "China","Discipline": "snooker","Main": 517,"Sex": "Both","AgeGroup": "O","Url": "","Related": "international","Stage": "F","ValueType": "IC","ShortName": "","WorldSnookerId": 13920,"RankingType": "WR","EventPredictionID": 2608,"Team": false,"Format": 1,"Twitter": "","HashTag": "InternationalChampionship","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 132,"NumUpcoming": 0,"NumActive": 0,"NumResults": 67,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 237,"PreviousEdition": 407},{"ID": 568,"Name": "China Championship","StartDate": "2016-11-01","EndDate": "2016-11-05","Sponsor": "Evergrande","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Guangzhou Sports Venue (No.2)","City": "Guangzhou","Country": "China","Discipline": "snooker","Main": 568,"Sex": "Both","AgeGroup": "O","Url": "","Related": "cc","Stage": "F","ValueType": "CC","ShortName": "","WorldSnookerId": 13930,"RankingType": "","EventPredictionID": 2640,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 525,"Name": "Champion of Champions","StartDate": "2016-11-07","EndDate": "2016-11-12","Sponsor": "Dafabet","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 525,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championofchampionssnooker.co.uk\u002F","Related": "cc","Stage": "F","ValueType": "COC","ShortName": "","WorldSnookerId": 13931,"RankingType": "","EventPredictionID": 2620,"Team": false,"Format": 1,"Twitter": "","HashTag": "ChampionOfChampions","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.itv.com\u002Fhub\u002Fitv4\u0022>ITV 4<\u002Fa> and selected betting sites  ","DefendingChampion": 154,"PreviousEdition": 408},{"ID": 523,"Name": "Northern Ireland Open","StartDate": "2016-11-14","EndDate": "2016-11-20","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Titanic Belfast ","City": "Belfast","Country": "Ireland","Discipline": "snooker","Main": 523,"Sex": "Both","AgeGroup": "O","Url": "","Related": "Home Nations Series","Stage": "F","ValueType": "NIO","ShortName": "","WorldSnookerId": 13911,"RankingType": "WR","EventPredictionID": 2609,"Team": false,"Format": 1,"Twitter": "","HashTag": "NorthernIrelandOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>, <a href=\u0022http:\u002F\u002Fquesttv.co.uk\u002F\u0022>Quest<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 526,"Name": "UK Championship","StartDate": "2016-11-22","EndDate": "2016-12-04","Sponsor": "Betway ","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Barbican Centre","City": "York","Country": "England","Discipline": "snooker","Main": 526,"Sex": "Both","AgeGroup": "O","Url": "","Related": "uk","Stage": "F","ValueType": "UK","ShortName": "","WorldSnookerId": 13914,"RankingType": "WR","EventPredictionID": 2610,"Team": false,"Format": 1,"Twitter": "","HashTag": "UKChampionship","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.bbc.co.uk\u002Fiplayer\u0022>BBC<\u002Fa>, <a href=\u0022http:\u002F\u002Feurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 154,"PreviousEdition": 410},{"ID": 527,"Name": "German Masters Qualifiers","StartDate": "2016-12-06","EndDate": "2016-12-09","Sponsor": "F66.com","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Barnsley Metrodome","City": "Barnsley","Country": "England","Discipline": "snooker","Main": 532,"Sex": "Both","AgeGroup": "O","Url": "","Related": "german","Stage": "Q","ValueType": "GM","ShortName": "","WorldSnookerId": 13915,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 96,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 524,"Name": "Scottish Open","StartDate": "2016-12-12","EndDate": "2016-12-18","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Emirates Arena","City": "Glasgow","Country": "Scotland","Discipline": "snooker","Main": 524,"Sex": "Both","AgeGroup": "O","Url": "","Related": "scottish","Stage": "F","ValueType": "SO","ShortName": "","WorldSnookerId": 13912,"RankingType": "WR","EventPredictionID": 2611,"Team": false,"Format": 1,"Twitter": "","HashTag": "ScottishOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport<\u002Fa>, <a href=\u0022http:\u002F\u002Fquesttv.co.uk\u002F\u0022>Quest<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 539,"Name": "Championship League - Group 1","StartDate": "2017-01-02","EndDate": "2017-01-03","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 1,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championshipleaguesnooker.co.uk\u002F","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13933,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 430},{"ID": 540,"Name": "Championship League - Group 2","StartDate": "2017-01-04","EndDate": "2017-01-05","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 2,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championshipleaguesnooker.co.uk\u002F","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13934,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "Players placed 2-5 gets a new chance in Group Three","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 431},{"ID": 542,"Name": "Championship League - Group 3","StartDate": "2017-01-09","EndDate": "2017-01-10","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 3,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13935,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 434},{"ID": 543,"Name": "Championship League - Group 4","StartDate": "2017-01-11","EndDate": "2017-01-12","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 4,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13936,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 435},{"ID": 592,"Name": "Women's Masters, Group A","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 593,"Name": "Women's Masters, Group B","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 594,"Name": "Women's Masters, Group C","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 595,"Name": "Women's Masters, Group D","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 596,"Name": "Women's Masters, Group E","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 597,"Name": "Women's Masters, Group F","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 598,"Name": "Women's Masters, Group G","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 599,"Name": "Women's Masters, Group H","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 589,"Name": "Women's Masters","StartDate": "2017-01-14","EndDate": "2017-01-15","Sponsor": "Eden","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "WomensMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 26,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 531,"Name": "Masters","StartDate": "2017-01-15","EndDate": "2017-01-22","Sponsor": "Dafabet","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Alexandra Palace","City": "London","Country": "England","Discipline": "snooker","Main": 531,"Sex": "Both","AgeGroup": "O","Url": "","Related": "masters","Stage": "F","ValueType": "Masters","ShortName": "","WorldSnookerId": 13913,"RankingType": "","EventPredictionID": 2630,"Team": false,"Format": 1,"Twitter": "","HashTag": "DafabetMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 8,"NumActive": 1,"NumResults": 6,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.bbc.co.uk\u002Fiplayer\u0022>BBC<\u002Fa>, <a href=\u0022http:\u002F\u002Feurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 5,"PreviousEdition": 417},{"ID": 548,"Name": "China Open Qualifiers","StartDate": "2017-01-24","EndDate": "2017-01-27","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 533,"Sex": "Both","AgeGroup": "O","Url": "","Related": "china","Stage": "Q","ValueType": "CO","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerChinaOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 60,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 532,"Name": "German Masters","StartDate": "2017-02-01","EndDate": "2017-02-05","Sponsor": "F66.com","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Tempodrom","City": "Berlin","Country": "Germany","Discipline": "snooker","Main": 532,"Sex": "Both","AgeGroup": "O","Url": "","Related": "german","Stage": "F","ValueType": "GM","ShortName": "","WorldSnookerId": 13916,"RankingType": "WR","EventPredictionID": 2612,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 31,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>","DefendingChampion": 27,"PreviousEdition": 420},{"ID": 556,"Name": "World Grand Prix","StartDate": "2017-02-06","EndDate": "2017-02-12","Sponsor": "Ladbrokes","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 556,"Sex": "Both","AgeGroup": "O","Url": "","Related": "Unknown","Stage": "F","ValueType": "WGP","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "WorldGrandPrix","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 97,"PreviousEdition": 429},{"ID": 534,"Name": "Welsh Open","StartDate": "2017-02-13","EndDate": "2017-02-19","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Motorpoint Arena","City": "Cardiff","Country": "Wales","Discipline": "snooker","Main": 534,"Sex": "Both","AgeGroup": "O","Url": "","Related": "welsh","Stage": "F","ValueType": "WO","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 5,"PreviousEdition": 427},{"ID": 590,"Name": "Connie Gough Memorial Trophy","StartDate": "2017-02-18","EndDate": "2017-02-18","Sponsor": "","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Dunstable Snooker Club","City": "Dunstable","Country": "England","Discipline": "snooker","Main": 590,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "CGMT","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "CGMT","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 544,"Name": "Championship League - Group 5","StartDate": "2017-02-20","EndDate": "2017-02-21","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 5,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13937,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 24,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 436},{"ID": 545,"Name": "Championship League - Group 6","StartDate": "2017-02-22","EndDate": "2017-02-23","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 6,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13938,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "Will be joined by players placed 2-5 in Group Five","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 437},{"ID": 557,"Name": "Snooker Shoot-Out","StartDate": "2017-02-23","EndDate": "2017-02-26","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Watford Colosseum","City": "Watford","Country": "England","Discipline": "snooker","Main": 557,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "ShootOut","ShortName": "Shoot-Out","WorldSnookerId": 0,"RankingType": "Unknown","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerShootOut","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 549,"PreviousEdition": 447},{"ID": 546,"Name": "Championship League - Group 7","StartDate": "2017-02-27","EndDate": "2017-02-28","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 7,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13939,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 438},{"ID": 541,"Name": "Championship League - Winners' Group","StartDate": "2017-03-01","EndDate": "2017-03-02","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championshipleaguesnooker.co.uk\u002F","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 25,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 12,"PreviousEdition": 431},{"ID": 547,"Name": "Gibraltar Open","StartDate": "2017-03-03","EndDate": "2017-03-05","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Tercentenary Sports Hall","City": "Gibraltar","Country": "Gibraltar","Discipline": "snooker","Main": 547,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "F","ValueType": "EPTC","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 4,"PreviousEdition": 411},{"ID": 555,"Name": "Players Championship","StartDate": "2017-03-06","EndDate": "2017-03-12","Sponsor": "Ladbrokes","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Venue Cymru","City": "Llandudno","Country": "Wales","Discipline": "snooker","Main": 555,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "F","ValueType": "PTCF","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "PTCFinals","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 202,"PreviousEdition": 423},{"ID": 591,"Name": "Women's World Snooker Championship","StartDate": "2017-03-13","EndDate": "2017-03-19","Sponsor": "Eden","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Lagoon Billard Room, Safra Toa Payoh","City": "Singapore","Country": "Singapore","Discipline": "snooker","Main": 591,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "WWC","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "LadiesWSC","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 533,"Name": "China Open","StartDate": "2017-03-27","EndDate": "2017-04-02","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Beijing University Students Gymnasium","City": "Beijing","Country": "China","Discipline": "snooker","Main": 533,"Sex": "Both","AgeGroup": "O","Url": "","Related": "china","Stage": "F","ValueType": "CO","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 12,"PreviousEdition": 422},{"ID": 535,"Name": "World Championship Qualifiers","StartDate": "2017-04-05","EndDate": "2017-04-12","Sponsor": "Betfred","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Ponds Forge International Sports Centre","City": "Sheffield","Country": "England","Discipline": "snooker","Main": 536,"Sex": "Both","AgeGroup": "O","Url": "","Related": "world","Stage": "Q","ValueType": "WC","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 421},{"ID": 536,"Name": "World Championship","StartDate": "2017-04-15","EndDate": "2017-05-01","Sponsor": "Betfred","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Crucible Theatre","City": "Sheffield","Country": "England","Discipline": "snooker","Main": 536,"Sex": "Both","AgeGroup": "O","Url": "","Related": "world","Stage": "F","ValueType": "WC","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 416}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.ser
new file mode 100644 (file)
index 0000000..4877309
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.json
new file mode 100644 (file)
index 0000000..14875bf
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 3352358,"EventID": 531,"Round": 7,"Number": 3,"Player1ID": 12,"Score1": 5,"Walkover1": false,"Player2ID": 4,"Score2": 6,"Walkover2": false,"WinnerID": 4,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434075,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=U4Sut-Jtv1M","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T13:04:10Z","StartDate": "2017-01-17T13:04:10Z","EndDate": "2017-01-17T16:13:44Z","ScheduledDate": "2017-01-17T13:00:00Z","FrameScores": "","Sessions": "","Note": "Five centuries and nine half centuries!","ExtendedNote": ""}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.ser
new file mode 100644 (file)
index 0000000..23c7493
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.json
new file mode 100644 (file)
index 0000000..ad275fc
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 3351411,"EventID": 531,"Round": 15,"Number": 1,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:47:58Z","ModDate": "2016-12-04T20:55:14Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-22T13:00:00Z","FrameScores": "","Sessions": "<br \u002F>Second session 8 pm ","Note": "","ExtendedNote": ""},{"ID": 3351409,"EventID": 531,"Round": 14,"Number": 1,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:47:42Z","ModDate": "2016-12-05T01:27:13Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-21T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351410,"EventID": 531,"Round": 14,"Number": 2,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T20:54:39Z","ModDate": "2016-12-05T01:27:13Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-21T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351405,"EventID": 531,"Round": 13,"Number": 1,"Player1ID": 5,"Score1": 0,"Walkover1": false,"Player2ID": 154,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:46:53Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-19T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351406,"EventID": 531,"Round": 13,"Number": 2,"Player1ID": 4,"Score1": 0,"Walkover1": false,"Player2ID": 202,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:46:53Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-19T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351407,"EventID": 531,"Round": 13,"Number": 3,"Player1ID": 168,"Score1": 0,"Walkover1": false,"Player2ID": 224,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T20:52:11Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-20T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351408,"EventID": 531,"Round": 13,"Number": 4,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T20:52:11Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-20T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352356,"EventID": 531,"Round": 7,"Number": 1,"Player1ID": 5,"Score1": 6,"Walkover1": false,"Player2ID": 200,"Score2": 5,"Walkover2": false,"WinnerID": 5,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434073,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002Fh-V4tlXRcFI","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-15T12:58:50Z","StartDate": "2017-01-15T12:58:50Z","EndDate": "2017-01-15T16:39:44Z","ScheduledDate": "2017-01-15T13:00:00Z","FrameScores": "","Sessions": "","Note": "Liang missed match ball black in frame 10. O'Sullivan made a 121 break in the decider.","ExtendedNote": ""},{"ID": 3352357,"EventID": 531,"Round": 7,"Number": 2,"Player1ID": 154,"Score1": 6,"Walkover1": false,"Player2ID": 158,"Score2": 3,"Walkover2": false,"WinnerID": 154,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434074,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FNEBEOlOYlOE","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T19:03:04Z","StartDate": "2017-01-17T19:03:04Z","EndDate": "2017-01-17T21:50:36Z","ScheduledDate": "2017-01-17T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352358,"EventID": 531,"Round": 7,"Number": 3,"Player1ID": 12,"Score1": 5,"Walkover1": false,"Player2ID": 4,"Score2": 6,"Walkover2": false,"WinnerID": 4,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434075,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=U4Sut-Jtv1M","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T13:04:10Z","StartDate": "2017-01-17T13:04:10Z","EndDate": "2017-01-17T16:13:44Z","ScheduledDate": "2017-01-17T13:00:00Z","FrameScores": "","Sessions": "","Note": "Five centuries and nine half centuries!","ExtendedNote": ""},{"ID": 3352359,"EventID": 531,"Round": 7,"Number": 4,"Player1ID": 237,"Score1": 5,"Walkover1": false,"Player2ID": 202,"Score2": 6,"Walkover2": false,"WinnerID": 202,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434076,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FxCVGf9dhDbs","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-16T13:00:46Z","StartDate": "2017-01-16T13:00:46Z","EndDate": "2017-01-16T16:22:33Z","ScheduledDate": "2017-01-16T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": "Re-rack in frame 2. Re-spotted black in frame 9 (67-67)."},{"ID": 3352360,"EventID": 531,"Round": 7,"Number": 5,"Player1ID": 30,"Score1": 1,"Walkover1": false,"Player2ID": 168,"Score2": 6,"Walkover2": false,"WinnerID": 168,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434077,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FVMakJBk540s","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-16T18:54:22Z","StartDate": "2017-01-16T18:54:22Z","EndDate": "2017-01-16T21:40:51Z","ScheduledDate": "2017-01-16T19:00:00Z","FrameScores": "","Sessions": "","Note": "132 by Bingham is the new highest break in the tournament  ","ExtendedNote": "Re-spotted black in frame two."},{"ID": 3352361,"EventID": 531,"Round": 7,"Number": 6,"Player1ID": 224,"Score1": 6,"Walkover1": false,"Player2ID": 39,"Score2": 3,"Walkover2": false,"WinnerID": 224,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434078,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FuwBHxoYEgEc","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-15T19:14:20Z","StartDate": "2017-01-15T19:14:20Z","EndDate": "2017-01-15T22:17:16Z","ScheduledDate": "2017-01-15T19:00:00Z","FrameScores": "","Sessions": "","Note": "Ding missed the yellow on the way to a maximum in the second frame","ExtendedNote": ""},{"ID": 3352362,"EventID": 531,"Round": 7,"Number": 7,"Player1ID": 97,"Score1": 0,"Walkover1": false,"Player2ID": 16,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434079,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T22:48:55Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-18T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352363,"EventID": 531,"Round": 7,"Number": 8,"Player1ID": 17,"Score1": 3,"Walkover1": false,"Player2ID": 1,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 434080,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-18T14:19:13Z","StartDate": "2017-01-18T13:10:00Z","EndDate": "","ScheduledDate": "2017-01-18T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.ser
new file mode 100644 (file)
index 0000000..aa94b37
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.json
new file mode 100644 (file)
index 0000000..1944905
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 3352363,"EventID": 531,"Round": 7,"Number": 8,"Player1ID": 17,"Score1": 3,"Walkover1": false,"Player2ID": 1,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 434080,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-18T14:19:13Z","StartDate": "2017-01-18T13:10:00Z","EndDate": "","ScheduledDate": "2017-01-18T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.ser
new file mode 100644 (file)
index 0000000..65acd8d
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.json
new file mode 100644 (file)
index 0000000..b3a6bc4
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 3352363,"EventID": 531,"Round": 7,"Number": 8,"Player1ID": 17,"Score1": 3,"Walkover1": false,"Player2ID": 1,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 434080,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-18T14:19:13Z","StartDate": "2017-01-18T13:10:00Z","EndDate": "","ScheduledDate": "2017-01-18T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352564,"EventID": 531,"Round": 13,"Number": 1,"Player1ID": 5,"Score1": 1,"Walkover1": false,"Player2ID": 154,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 481773,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:46:53Z","ModDate": "2017-01-19T13:48:02Z","StartDate": "2017-01-19T13:10:06Z","EndDate": "","ScheduledDate": "2017-01-19T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.ser
new file mode 100644 (file)
index 0000000..a94696a
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.json
new file mode 100644 (file)
index 0000000..fe2481a
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 1,"Type": 1,"FirstName": "Mark","MiddleName": "J","LastName": "Williams","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "M J Williams","Nationality": "Wales","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fmwilliams.shtml","Born": "1975-03-21","Twitter": "markwil147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMarkWilliams.png","Info": ""}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.ser
new file mode 100644 (file)
index 0000000..e95ccd5
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.json
new file mode 100644 (file)
index 0000000..fc6fb5c
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 1,"Type": 1,"FirstName": "Mark","MiddleName": "J","LastName": "Williams","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "M J Williams","Nationality": "Wales","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fmwilliams.shtml","Born": "1975-03-21","Twitter": "markwil147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMarkWilliams.png","Info": ""},{"ID": 2,"Type": 1,"FirstName": "Stephen","MiddleName": "","LastName": "Maguire","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1981-03-13","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "stephenmaguire147.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMaguire.png","Info": ""},{"ID": 3,"Type": 1,"FirstName": "Jamie","MiddleName": "","LastName": "Cope","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1985-09-12","Twitter": "JamieCope147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FJamieCope.png","Info": ""},{"ID": 4,"Type": 1,"FirstName": "Marco","MiddleName": "","LastName": "Fu","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Hong Kong","Sex": "M","BioPage": "","Born": "1978-01-08","Twitter": "Marcofu18","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fmfu.jpg","Info": ""},{"ID": 5,"Type": 1,"FirstName": "Ronnie","MiddleName": "","LastName": "O'Sullivan","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "R O'Sullivan","Nationality": "England","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Frosullivan.shtml","Born": "1975-12-05","Twitter": "ronnieo147","SurnameFirst": false,"License": "","Club": "","URL": "ronnieosullivan.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Frosullivan.jpg","Info": ""},{"ID": 8,"Type": 1,"FirstName": "Tom","MiddleName": "","LastName": "Ford","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1983-08-17","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FTomFord.png","Info": ""},{"ID": 9,"Type": 1,"FirstName": "Matthew","MiddleName": "","LastName": "Stevens","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "M Stevens","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1977-09-11","Twitter": "MattStevens147","SurnameFirst": false,"License": "","Club": "","URL": "matthew-stevens.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FStevens.png","Info": ""},{"ID": 10,"Type": 1,"FirstName": "Jamie","MiddleName": "","LastName": "Jones","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Jamie Jones","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1988-02-14","Twitter": "TheJonesKid147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FJamie Jones.png","Info": ""},{"ID": 12,"Type": 1,"FirstName": "Judd","MiddleName": "","LastName": "Trump","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1989-08-20","Twitter": "judd147t","SurnameFirst": false,"License": "","Club": "","URL": "facebook.com\u002Fjuddtrump147","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fjtrump.jpg","Info": ""},{"ID": 14,"Type": 1,"FirstName": "Nigel","MiddleName": "","LastName": "Bond","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "N Bond","Nationality": "England","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fnbond.shtml","Born": "1965-11-15","Twitter": "NigelBond00","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBond.png","Info": ""},{"ID": 15,"Type": 1,"FirstName": "Mark","MiddleName": "","LastName": "Davis","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Mark Davis","Nationality": "England","Sex": "M","BioPage": "","Born": "1972-08-12","Twitter": "markdavis2108","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMarkDavis.png","Info": ""},{"ID": 16,"Type": 1,"FirstName": "Barry","MiddleName": "","LastName": "Hawkins","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1979-04-23","Twitter": "TheHawk147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fbhawkins.jpg","Info": ""},{"ID": 17,"Type": 1,"FirstName": "Mark","MiddleName": "","LastName": "Selby","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1983-06-19","Twitter": "markjesterselby","SurnameFirst": false,"License": "","Club": "","URL": "markselby.info","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fmselby.jpg","Info": ""},{"ID": 18,"Type": 1,"FirstName": "Igor","MiddleName": "","LastName": "Figueiredo","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Brazil","Sex": "M","BioPage": "","Born": "1977-10-11","Twitter": "igorsnooker","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FIgor.png","Info": ""},{"ID": 19,"Type": 1,"FirstName": "Ben","MiddleName": "","LastName": "Woollaston","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1987-05-14","Twitter": "ben_Woollaston","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FWoollaston.png","Info": ""},{"ID": 20,"Type": 1,"FirstName": "Jimmy","MiddleName": "","LastName": "White","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "J White","Nationality": "England","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fjwhite.shtml","Born": "1962-05-02","Twitter": "jimmywhite147","SurnameFirst": false,"License": "","Club": "","URL": "jimmywhirlwindwhite.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FJimmy White.png","Info": ""},{"ID": 21,"Type": 1,"FirstName": "Alfie","MiddleName": "","LastName": "Burden","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1976-12-14","Twitter": "ABOFLONDON","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBurden.png","Info": ""},{"ID": 22,"Type": 1,"FirstName": "Anthony","MiddleName": "","LastName": "McGill","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1991-02-05","Twitter": "antsmcgill","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMcGill.png","Info": ""},{"ID": 23,"Type": 1,"FirstName": "Paul","MiddleName": "S","LastName": "Davison","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "P S Davison","Nationality": "England","Sex": "M","BioPage": "","Born": "1971-10-01","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 24,"Type": 1,"FirstName": "Guodong","MiddleName": "","LastName": "Xiao","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Xiao Guodong","Nationality": "China","Sex": "M","BioPage": "","Born": "1989-02-10","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FXiao.png","Info": ""},{"ID": 25,"Type": 1,"FirstName": "Andrew","MiddleName": "","LastName": "Higginson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1977-12-13","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FHigginson.png","Info": ""},{"ID": 26,"Type": 1,"FirstName": "Allan","MiddleName": "","LastName": "Taylor","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "A Taylor","Nationality": "England","Sex": "M","BioPage": "","Born": "1984-11-28","Twitter": "AllanTaylor147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FAllan Taylor.png","Info": ""},{"ID": 27,"Type": 1,"FirstName": "Martin","MiddleName": "","LastName": "Gould","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1981-09-14","Twitter": "GouldyBalls147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FGould.png","Info": ""},{"ID": 28,"Type": 1,"FirstName": "Mark","MiddleName": "","LastName": "King","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "M King","Nationality": "England","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fmking.shtml","Born": "1974-03-28","Twitter": "markking147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FKing.png","Info": ""},{"ID": 30,"Type": 1,"FirstName": "Stuart","MiddleName": "","LastName": "Bingham","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1976-05-21","Twitter": "Stuart__Bingham  ","SurnameFirst": false,"License": "","Club": "","URL": "stuartbingham.uk.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBingham.png","Info": ""},{"ID": 32,"Type": 1,"FirstName": "Daniel","MiddleName": "","LastName": "Wells","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1988-07-31","Twitter": "danielwells147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FWells.png","Info": ""},{"ID": 33,"Type": 1,"FirstName": "Dominic","MiddleName": "","LastName": "Dale","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1971-12-29","Twitter": "spaceman147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fdale.png","Info": ""},{"ID": 35,"Type": 1,"FirstName": "Joe","MiddleName": "","LastName": "Swail","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Northern Ireland","Sex": "M","BioPage": "","Born": "1969-08-29","Twitter": "joeswail","SurnameFirst": false,"License": "","Club": "","URL": "joeswail.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FSwail.png","Info": ""},{"ID": 39,"Type": 1,"FirstName": "Kyren","MiddleName": "","LastName": "Wilson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "K Wilson","Nationality": "England","Sex": "M","BioPage": "","Born": "1991-12-23","Twitter": "KyrenWilson","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FKyren Wilson.png","Info": ""},{"ID": 42,"Type": 1,"FirstName": "Peter","MiddleName": "","LastName": "Ebdon","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fpebdon.shtml","Born": "1970-08-27","Twitter": "pdebdon","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FEbdon.png","Info": ""},{"ID": 44,"Type": 1,"FirstName": "Alan","MiddleName": "","LastName": "McManus","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Famcmanus.shtml","Born": "1971-01-21","Twitter": "alan_mcmanus","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMcManus.png","Info": ""},{"ID": 45,"Type": 1,"FirstName": "Liam","MiddleName": "","LastName": "Highfield","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1990-01-01","Twitter": "liamhighfield","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 47,"Type": 1,"FirstName": "Matthew","MiddleName": "","LastName": "Selt","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1985-03-07","Twitter": "MattSelt","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FSelt.png","Info": ""},{"ID": 48,"Type": 1,"FirstName": "Mark","MiddleName": "","LastName": "Joyce","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1983-08-11","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FJoyce.png","Info": ""},{"ID": 49,"Type": 1,"FirstName": "Mitchell","MiddleName": "","LastName": "Mann","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1991-12-26","Twitter": "MitchellSnooker","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMann.png","Info": ""},{"ID": 50,"Type": 1,"FirstName": "Rory","MiddleName": "","LastName": "McLeod","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1971-03-26","Twitter": "Rory_McLeod147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMcLeod.png","Info": ""},{"ID": 52,"Type": 1,"FirstName": "Graeme","MiddleName": "","LastName": "Dott","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1977-05-12","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "graemedottcoaching.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDott.png","Info": ""},{"ID": 53,"Type": 1,"FirstName": "Jamie","MiddleName": "","LastName": "Burnett","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1975-09-16","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 54,"Type": 1,"FirstName": "Mike","MiddleName": "","LastName": "Dunn","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1971-11-20","Twitter": "mikedunn147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDunn.png","Info": ""},{"ID": 61,"Type": 1,"FirstName": "Kurt","MiddleName": "","LastName": "Maflin","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "K Maflin","Nationality": "Norway","Sex": "M","BioPage": "","Born": "1983-08-08","Twitter": "KurtMaflin147","SurnameFirst": false,"License": "","Club": "","URL": "kurtmaflin.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMaflin.png","Info": ""},{"ID": 62,"Type": 1,"FirstName": "Ricky","MiddleName": "","LastName": "Walden","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1982-11-11","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "rickywalden.co.uk","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FWalden.png","Info": ""},{"ID": 63,"Type": 1,"FirstName": "Fergal","MiddleName": "","LastName": "O'Brien","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "F O'Brien","Nationality": "Ireland","Sex": "M","BioPage": "","Born": "1972-03-08","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "fergalobrien.ie","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FOBrien.png","Info": ""},{"ID": 67,"Type": 1,"FirstName": "David","MiddleName": "","LastName": "Grace","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1985-05-05","Twitter": "daveg147","SurnameFirst": false,"License": "","Club": "","URL": "davidgracesnooker.co.uk","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FGrace.png","Info": ""},{"ID": 68,"Type": 1,"FirstName": "Ryan","MiddleName": "","LastName": "Day","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "R Day","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1980-03-23","Twitter": "ryan23day","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FRyan Day.png","Info": ""},{"ID": 74,"Type": 1,"FirstName": "Adam","MiddleName": "","LastName": "Duffy","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "A Duffy","Nationality": "England","Sex": "M","BioPage": "","Born": "1989-03-30","Twitter": "A147D","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 76,"Type": 1,"FirstName": "Sam","MiddleName": "","LastName": "Baird","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1988-06-17","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "www.sambaird147.co.uk","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBaird.png","Info": ""},{"ID": 81,"Type": 1,"FirstName": "Anda","MiddleName": "","LastName": "Zhang","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Zhang Anda","Nationality": "China","Sex": "M","BioPage": "","Born": "1991-12-25","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FAnda.png","Info": ""},{"ID": 85,"Type": 1,"FirstName": "Jack","MiddleName": "","LastName": "Lisowski","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1991-06-25","Twitter": "JackLisowski","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FLisowski.png","Info": ""},{"ID": 87,"Type": 1,"FirstName": "Ian","MiddleName": "","LastName": "Burns","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1985-03-11","Twitter": "BurnsyIB","SurnameFirst": false,"License": "","Club": "","URL": "http:\u002F\u002Fwww.ianburnssnooker.com\u002F","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBurns.png","Info": ""},{"ID": 90,"Type": 1,"FirstName": "Jak","MiddleName": "","LastName": "Jones","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Jak Jones","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1993-06-29","Twitter": "JakJones_","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 92,"Type": 1,"FirstName": "Robert","MiddleName": "","LastName": "Milkins","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1976-03-06","Twitter": "RobertMilkins","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMilkins.png","Info": ""},{"ID": 93,"Type": 1,"FirstName": "Jimmy","MiddleName": "","LastName": "Robertson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "J Robertson","Nationality": "England","Sex": "M","BioPage": "","Born": "1986-05-03","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FJimmy Robertson.png","Info": ""},{"ID": 96,"Type": 1,"FirstName": "Robbie","MiddleName": "","LastName": "Williams","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "R Williams","Nationality": "England","Sex": "M","BioPage": "","Born": "1986-12-28","Twitter": "RLW147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FRobbie Williams.png","Info": ""},{"ID": 97,"Type": 1,"FirstName": "Shaun","MiddleName": "","LastName": "Murphy","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "S Murphy","Nationality": "England","Sex": "M","BioPage": "","Born": "1982-08-10","Twitter": "Magician147","SurnameFirst": false,"License": "","Club": "","URL": "shaunmurphy.net","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMurphy.png","Info": ""},{"ID": 101,"Type": 1,"FirstName": "Luca","MiddleName": "","LastName": "Brecel","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Belgium","Sex": "M","BioPage": "","Born": "1995-03-08","Twitter": "LucaLoy_Brecel","SurnameFirst": false,"License": "","Club": "","URL": "brecelluca.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBrecel.png","Info": ""},{"ID": 108,"Type": 1,"FirstName": "Aditya","MiddleName": "","LastName": "Mehta","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "India","Sex": "M","BioPage": "","Born": "1985-10-31","Twitter": "snookered_adi","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMehta.png","Info": ""},{"ID": 109,"Type": 1,"FirstName": "Sam","MiddleName": "","LastName": "Craigie","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Sam Craigie","Nationality": "England","Sex": "M","BioPage": "","Born": "1993-12-29","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 115,"Type": 1,"FirstName": "Anthony","MiddleName": "","LastName": "Hamilton","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fahamilton.shtml","Born": "1971-06-29","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FHamilton.PNG","Info": ""},{"ID": 118,"Type": 1,"FirstName": "David","MiddleName": "B","LastName": "Gilbert","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "D B Gilbert","Nationality": "England","Sex": "M","BioPage": "","Born": "1981-06-12","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FGilbert.png","Info": ""},{"ID": 120,"Type": 1,"FirstName": "Martin","MiddleName": "","LastName": "O'Donnell","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1986-06-04","Twitter": "TheMOD147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMartin O.PNG","Info": ""},{"ID": 124,"Type": 1,"FirstName": "Michael","MiddleName": "","LastName": "Wild","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1981-03-27","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 125,"Type": 1,"FirstName": "Michael","MiddleName": "","LastName": "Holt","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1978-08-07","Twitter": "HitmanHolt","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FHolt.png","Info": ""},{"ID": 128,"Type": 1,"FirstName": "Stuart","MiddleName": "","LastName": "Carrington","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1990-05-14","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FCarrington.png","Info": ""},{"ID": 131,"Type": 1,"FirstName": "Craig","MiddleName": "","LastName": "Steadman","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1984-07-14","Twitter": "stedz1","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FSteadman.png","Info": ""},{"ID": 133,"Type": 1,"FirstName": "Zhe","MiddleName": "","LastName": "Chen","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Chen Zhe","Nationality": "China","Sex": "M","BioPage": "","Born": "1993-02-28","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 151,"Type": 1,"FirstName": "James","MiddleName": "","LastName": "Cahill","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1995-12-27","Twitter": "JamesCahill147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 154,"Type": 1,"FirstName": "Neil","MiddleName": "","LastName": "Robertson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "N Robertson","Nationality": "Australia","Sex": "M","BioPage": "","Born": "1982-02-11","Twitter": "nr147","SurnameFirst": false,"License": "","Club": "","URL": "neilrobertson.net","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FNRobertson.png","Info": ""},{"ID": 158,"Type": 1,"FirstName": "Allister","MiddleName": "","LastName": "Carter","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1979-07-25","Twitter": "TheCaptain147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fcarter.png","Info": ""},{"ID": 165,"Type": 1,"FirstName": "Jamie","MiddleName": "","LastName": "Barrett","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1984-04-19","Twitter": "Jazz6039","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 168,"Type": 1,"FirstName": "Joe","MiddleName": "","LastName": "Perry","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1974-08-13","Twitter": "joegentlemanjoe","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FPerry.png","Info": ""},{"ID": 170,"Type": 1,"FirstName": "Ken","MiddleName": "","LastName": "Doherty","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "K Doherty","Nationality": "Ireland","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fkdoherty.shtml","Born": "1969-09-17","Twitter": "kendoherty1997","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDoherty.png","Info": ""},{"ID": 171,"Type": 1,"FirstName": "Michael","MiddleName": "","LastName": "White","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Michael White","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1991-07-05","Twitter": "michaelwhite147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMWhite.png","Info": ""},{"ID": 177,"Type": 1,"FirstName": "Rod","MiddleName": "","LastName": "Lawler","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1971-07-12","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FLawler.png","Info": ""},{"ID": 184,"Type": 1,"FirstName": "Delu","MiddleName": "","LastName": "Yu","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Yu Delu","Nationality": "China","Sex": "M","BioPage": "","Born": "1987-10-11","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDelu.png","Info": ""},{"ID": 193,"Type": 1,"FirstName": "James","MiddleName": "","LastName": "Wattana","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Thailand","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fjwattana.shtml","Born": "1970-01-17","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": "Also known as Ratchapol Pu-ob-orm."},{"ID": 200,"Type": 1,"FirstName": "Wenbo","MiddleName": "","LastName": "Liang","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Liang Wenbo","Nationality": "China","Sex": "M","BioPage": "","Born": "1987-03-05","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FWenbo.png","Info": ""},{"ID": 202,"Type": 1,"FirstName": "Mark","MiddleName": "","LastName": "Allen","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "M Allen","Nationality": "Northern Ireland","Sex": "M","BioPage": "","Born": "1986-02-22","Twitter": "pistol147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMarkAllen.png","Info": ""},{"ID": 208,"Type": 1,"FirstName": "Noppon","MiddleName": "","LastName": "Saengkham","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Thailand","Sex": "M","BioPage": "","Born": "1992-07-15","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 217,"Type": 1,"FirstName": "Thepchaiya","MiddleName": "","LastName": "Un-Nooh","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Thailand","Sex": "M","BioPage": "","Born": "1985-07-18","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FUn-Nooh.png","Info": ""},{"ID": 218,"Type": 1,"FirstName": "Pengfei","MiddleName": "","LastName": "Tian","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Tian Pengfei","Nationality": "China","Sex": "M","BioPage": "","Born": "1987-08-16","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FPengfei.png","Info": ""},{"ID": 224,"Type": 1,"FirstName": "Junhui","MiddleName": "","LastName": "Ding","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Ding Junhui","Nationality": "China","Sex": "M","BioPage": "","Born": "1987-04-01","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDingjunhui.jpg","Info": ""},{"ID": 237,"Type": 1,"FirstName": "John","MiddleName": "","LastName": "Higgins","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "J Higgins","Nationality": "Scotland","Sex": "M","BioPage": "http:\u002F\u002Fsnooker.org\u002Fplr\u002Fbio\u002Fjhiggins.shtml","Born": "1975-05-18","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fjhiggins.jpg","Info": ""},{"ID": 269,"Type": 1,"FirstName": "Gareth","MiddleName": "","LastName": "Allen","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "G Allen","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1988-09-09","Twitter": "gaz_147","SurnameFirst": false,"License": "","Club": "","URL": "http:\u002F\u002Fwww.garethallen.weebly.com","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FGAllen.png","Info": ""},{"ID": 295,"Type": 1,"FirstName": "Hang","MiddleName": "","LastName": "Li","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Li Hang","Nationality": "China","Sex": "M","BioPage": "","Born": "1990-10-04","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FHang.png","Info": ""},{"ID": 306,"Type": 1,"FirstName": "Xiwen","MiddleName": "","LastName": "Mei","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Mei Xiwen","Nationality": "China","Sex": "M","BioPage": "","Born": "1982-10-08","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 339,"Type": 1,"FirstName": "Rouzi","MiddleName": "","LastName": "Maimaiti","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "China","Sex": "M","BioPage": "","Born": "1983-07-04","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 416,"Type": 1,"FirstName": "Christopher","MiddleName": "","LastName": "Keogan","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1992-08-01","Twitter": "ChrisKeogan123","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 422,"Type": 1,"FirstName": "Leo","MiddleName": "","LastName": "Fernandez","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Ireland","Sex": "M","BioPage": "","Born": "1976-07-05","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 448,"Type": 1,"FirstName": "Duane","MiddleName": "","LastName": "Jones","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "D Jones","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1993-04-30","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 475,"Type": 1,"FirstName": "Ian","MiddleName": "","LastName": "Preece","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1982-06-23","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 497,"Type": 1,"FirstName": "Michael","MiddleName": "","LastName": "Georgiou","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Cyprus","Sex": "M","BioPage": "","Born": "1988-01-18","Twitter": "mikegeorgiou147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMichaelG.png","Info": "Represented England prior to the 2016 Q School"},{"ID": 507,"Type": 1,"FirstName": "Yupeng","MiddleName": "","LastName": "Cao","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Cao Yupeng","Nationality": "China","Sex": "M","BioPage": "","Born": "1990-10-27","Twitter": "ECaoyupeng","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FYupeng.png","Info": ""},{"ID": 515,"Type": 1,"FirstName": "Alex","MiddleName": "","LastName": "Borg","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Malta","Sex": "M","BioPage": "","Born": "1969-06-05","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FBorg.png","Info": ""},{"ID": 520,"Type": 1,"FirstName": "Lee","MiddleName": "","LastName": "Walker","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "L Walker","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1976-02-11","Twitter": "leewalker147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FLee Walker.png","Info": ""},{"ID": 523,"Type": 1,"FirstName": "Sydney","MiddleName": "","LastName": "Wilson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "S Wilson","Nationality": "England","Sex": "M","BioPage": "","Born": "1990-04-06","Twitter": "squidski","SurnameFirst": false,"License": "","Club": "","URL": "sydneywilsonjr.com","Photo": "","Info": ""},{"ID": 526,"Type": 1,"FirstName": "John","MiddleName": "","LastName": "Astley","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "John Astley","Nationality": "England","Sex": "M","BioPage": "","Born": "1989-01-13","Twitter": "JohnAstley147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 534,"Type": 1,"FirstName": "Fraser","MiddleName": "","LastName": "Patrick","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1985-11-08","Twitter": "fraserp147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FPatrick.png","Info": ""},{"ID": 546,"Type": 1,"FirstName": "Gary","MiddleName": "","LastName": "Wilson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "G Wilson","Nationality": "England","Sex": "M","BioPage": "","Born": "1985-08-11","Twitter": "Gary_Wilson11","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FGary Wilson.png","Info": ""},{"ID": 549,"Type": 1,"FirstName": "Robin","MiddleName": "","LastName": "Hull","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Finland","Sex": "M","BioPage": "","Born": "1974-08-16","Twitter": "robhull_","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fhull.png","Info": ""},{"ID": 552,"Type": 1,"FirstName": "Sean","MiddleName": "","LastName": "O'Sullivan","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Sean O'Sullivan","Nationality": "England","Sex": "M","BioPage": "","Born": "1994-04-29","Twitter": "SeanTheStorm147","SurnameFirst": false,"License": "","Club": "","URL": "sean-osullivan.net","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FSean OSullivan.png","Info": ""},{"ID": 582,"Type": 1,"FirstName": "Dechawat","MiddleName": "","LastName": "Poomjaeng","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "D Poomjaeng","Nationality": "Thailand","Sex": "M","BioPage": "","Born": "1978-07-11","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDechawat.png","Info": ""},{"ID": 583,"Type": 1,"FirstName": "Itaro","MiddleName": "","LastName": "Santos","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Brazil","Sex": "M","BioPage": "","Born": "1985-07-28","Twitter": "ItaroSantos","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 592,"Type": 1,"FirstName": "Oliver","MiddleName": "","LastName": "Lines","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "O Lines","Nationality": "England","Sex": "M","BioPage": "","Born": "1995-06-16","Twitter": "oliverlines147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FOLines.png","Info": ""},{"ID": 593,"Type": 1,"FirstName": "Hammad","MiddleName": "","LastName": "Miah","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Hammad Miah","Nationality": "England","Sex": "M","BioPage": "","Born": "1993-07-06","Twitter": "HammadMiah147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 608,"Type": 1,"FirstName": "Elliot","MiddleName": "","LastName": "Slessor","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1994-08-04","Twitter": "sless147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 620,"Type": 1,"FirstName": "Eden","MiddleName": "","LastName": "Sharav","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1990-04-30","Twitter": "147Eden","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 621,"Type": 1,"FirstName": "Sanderson","MiddleName": "","LastName": "Lam","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "S Lam","Nationality": "England","Sex": "M","BioPage": "","Born": "1994-01-28","Twitter": "sandi147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 666,"Type": 1,"FirstName": "Hossein","MiddleName": "","LastName": "Vafaei Ayouri","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Iran","Sex": "M","BioPage": "","Born": "1994-09-14","Twitter": "hosseinvafae","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FHossein.png","Info": ""},{"ID": 762,"Type": 1,"FirstName": "Josh","MiddleName": "","LastName": "Boileau","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Ireland","Sex": "M","BioPage": "","Born": "1995-07-02","Twitter": "Boileau147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002Fjosh Boileau.png","Info": ""},{"ID": 892,"Type": 1,"FirstName": "Darryl","MiddleName": "","LastName": "Hill","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Isle of Man","Sex": "M","BioPage": "","Born": "1996-04-30","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 894,"Type": 1,"FirstName": "Scott","MiddleName": "","LastName": "Donaldson","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1994-03-19","Twitter": "ThePPM","SurnameFirst": false,"License": "","Club": "","URL": "scottdonaldson.pro","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FDonaldson.png","Info": ""},{"ID": 898,"Type": 1,"FirstName": "Ross","MiddleName": "","LastName": "Muir","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1995-10-06","Twitter": "rossmuir147","SurnameFirst": false,"License": "","Club": "","URL": "https:\u002F\u002Fwww.facebook.com\u002FRossMuirSnooker\u002F","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FMuir.png","Info": ""},{"ID": 906,"Type": 1,"FirstName": "Yuelong","MiddleName": "","LastName": "Zhou","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Zhou Yuelong","Nationality": "China","Sex": "M","BioPage": "","Born": "1998-01-24","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FYuelong.png","Info": ""},{"ID": 917,"Type": 1,"FirstName": "Rhys","MiddleName": "","LastName": "Clark","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Rhys Clark","Nationality": "Scotland","Sex": "M","BioPage": "","Born": "1994-08-17","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FClark.png","Info": ""},{"ID": 946,"Type": 1,"FirstName": "Xintong","MiddleName": "","LastName": "Zhao","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Zhao Xintong","Nationality": "China","Sex": "M","BioPage": "","Born": "1997-04-03","Twitter": "wwwXintongzhao","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 947,"Type": 1,"FirstName": "Yong","MiddleName": "","LastName": "Zhang","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Zhang Yong","Nationality": "China","Sex": "M","BioPage": "","Born": "1995-07-21","Twitter": "XGKysHncGoEu1WG","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 954,"Type": 1,"FirstName": "Yuchen","MiddleName": "","LastName": "Wang","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Wang Yuchen","Nationality": "China","Sex": "M","BioPage": "","Born": "1997-08-05","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1044,"Type": 1,"FirstName": "Chris","MiddleName": "","LastName": "Wakelin","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1992-03-16","Twitter": "chris147ace","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FWakelin.png","Info": ""},{"ID": 1114,"Type": 1,"FirstName": "Xiongman","MiddleName": "","LastName": "Fang","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Fang Xiongman","Nationality": "China","Sex": "M","BioPage": "","Born": "1993-04-09","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1260,"Type": 1,"FirstName": "Bingtao","MiddleName": "","LastName": "Yan","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "Yan Bingtao","Nationality": "China","Sex": "M","BioPage": "","Born": "2000-02-16","Twitter": "","SurnameFirst": true,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1505,"Type": 1,"FirstName": "Jason","MiddleName": "","LastName": "Weston","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "England","Sex": "M","BioPage": "","Born": "1971-01-12","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1509,"Type": 1,"FirstName": "Thor","MiddleName": "","LastName": "Chuan Leong","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Malaysia","Sex": "M","BioPage": "","Born": "1988-03-24","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "http:\u002F\u002Fsnooker.org\u002Fimg\u002Fplayers\u002FLeong.png","Info": ""},{"ID": 1577,"Type": 1,"FirstName": "Kritsanut","MiddleName": "","LastName": "Lertsattayatthorn","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Thailand","Sex": "M","BioPage": "","Born": "1988-12-16","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1578,"Type": 1,"FirstName": "Boonyarit","MiddleName": "","LastName": "Kaettikun","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Thailand","Sex": "M","BioPage": "","Born": "1995-10-05","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1737,"Type": 1,"FirstName": "David","MiddleName": "","LastName": "John","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "D John","Nationality": "Wales","Sex": "M","BioPage": "","Born": "1984-11-24","Twitter": "daijohn147147","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1762,"Type": 1,"FirstName": "Hamza","MiddleName": "","LastName": "Akbar","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Pakistan","Sex": "M","BioPage": "","Born": "1993-11-12","Twitter": "Hamza_Akbar1","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1763,"Type": 1,"FirstName": "Akani","MiddleName": "","LastName": "Songsermsawad","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Thailand","Sex": "M","BioPage": "","Born": "1995-09-10","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 1764,"Type": 1,"FirstName": "Hatem","MiddleName": "","LastName": "Yassin","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Egypt","Sex": "M","BioPage": "","Born": "1986-08-21","Twitter": "","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""},{"ID": 2064,"Type": 1,"FirstName": "Kurt","MiddleName": "","LastName": "Dunham","TeamName": "","TeamNumber": 0,"TeamSeason": 0,"ShortName": "","Nationality": "Australia","Sex": "M","BioPage": "","Born": "1991-12-06","Twitter": "KurtDunham","SurnameFirst": false,"License": "","Club": "","URL": "","Photo": "","Info": ""}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.ser
new file mode 100644 (file)
index 0000000..9a9046e
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.json
new file mode 100644 (file)
index 0000000..14d4739
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 12202013,"Position": 1,"PlayerID": 17,"Season": 2016,"Sum": 994942,"Type": "MoneyRankings"}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.ser
new file mode 100644 (file)
index 0000000..9a4c4ca
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.ser differ
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.json b/src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.json
new file mode 100644 (file)
index 0000000..5ea068f
--- /dev/null
@@ -0,0 +1 @@
+[{"ID": 12202013,"Position": 1,"PlayerID": 17,"Season": 2016,"Sum": 994942,"Type": "MoneyRankings"},{"ID": 12202014,"Position": 2,"PlayerID": 30,"Season": 2016,"Sum": 517012,"Type": "MoneyRankings"},{"ID": 12202015,"Position": 3,"PlayerID": 237,"Season": 2016,"Sum": 484892,"Type": "MoneyRankings"},{"ID": 12202016,"Position": 4,"PlayerID": 12,"Season": 2016,"Sum": 463166,"Type": "MoneyRankings"},{"ID": 12202017,"Position": 5,"PlayerID": 97,"Season": 2016,"Sum": 446767,"Type": "MoneyRankings"},{"ID": 12202018,"Position": 6,"PlayerID": 224,"Season": 2016,"Sum": 444925,"Type": "MoneyRankings"},{"ID": 12202019,"Position": 7,"PlayerID": 154,"Season": 2016,"Sum": 371291,"Type": "MoneyRankings"},{"ID": 12202020,"Position": 8,"PlayerID": 4,"Season": 2016,"Sum": 323375,"Type": "MoneyRankings"},{"ID": 12202021,"Position": 9,"PlayerID": 168,"Season": 2016,"Sum": 306800,"Type": "MoneyRankings"},{"ID": 12202022,"Position": 10,"PlayerID": 202,"Season": 2016,"Sum": 300592,"Type": "MoneyRankings"},{"ID": 12202023,"Position": 11,"PlayerID": 200,"Season": 2016,"Sum": 277667,"Type": "MoneyRankings"},{"ID": 12202024,"Position": 12,"PlayerID": 16,"Season": 2016,"Sum": 271025,"Type": "MoneyRankings"},{"ID": 12202025,"Position": 13,"PlayerID": 5,"Season": 2016,"Sum": 267583,"Type": "MoneyRankings"},{"ID": 12202026,"Position": 14,"PlayerID": 158,"Season": 2016,"Sum": 256825,"Type": "MoneyRankings"},{"ID": 12202027,"Position": 15,"PlayerID": 1,"Season": 2016,"Sum": 247975,"Type": "MoneyRankings"},{"ID": 12202028,"Position": 16,"PlayerID": 39,"Season": 2016,"Sum": 246925,"Type": "MoneyRankings"},{"ID": 12202029,"Position": 17,"PlayerID": 62,"Season": 2016,"Sum": 216008,"Type": "MoneyRankings"},{"ID": 12202030,"Position": 18,"PlayerID": 22,"Season": 2016,"Sum": 195125,"Type": "MoneyRankings"},{"ID": 12202031,"Position": 19,"PlayerID": 27,"Season": 2016,"Sum": 187059,"Type": "MoneyRankings"},{"ID": 12202032,"Position": 20,"PlayerID": 118,"Season": 2016,"Sum": 185417,"Type": "MoneyRankings"},{"ID": 12202033,"Position": 21,"PlayerID": 28,"Season": 2016,"Sum": 176550,"Type": "MoneyRankings"},{"ID": 12202034,"Position": 22,"PlayerID": 125,"Season": 2016,"Sum": 174225,"Type": "MoneyRankings"},{"ID": 12202035,"Position": 23,"PlayerID": 171,"Season": 2016,"Sum": 173175,"Type": "MoneyRankings"},{"ID": 12202036,"Position": 24,"PlayerID": 68,"Season": 2016,"Sum": 167503,"Type": "MoneyRankings"},{"ID": 12202037,"Position": 25,"PlayerID": 2,"Season": 2016,"Sum": 158917,"Type": "MoneyRankings"},{"ID": 12202038,"Position": 26,"PlayerID": 101,"Season": 2016,"Sum": 150508,"Type": "MoneyRankings"},{"ID": 12202039,"Position": 27,"PlayerID": 19,"Season": 2016,"Sum": 148808,"Type": "MoneyRankings"},{"ID": 12202040,"Position": 28,"PlayerID": 44,"Season": 2016,"Sum": 146017,"Type": "MoneyRankings"},{"ID": 12202041,"Position": 29,"PlayerID": 47,"Season": 2016,"Sum": 132300,"Type": "MoneyRankings"},{"ID": 12202042,"Position": 30,"PlayerID": 52,"Season": 2016,"Sum": 131475,"Type": "MoneyRankings"},{"ID": 12202043,"Position": 31,"PlayerID": 15,"Season": 2016,"Sum": 128108,"Type": "MoneyRankings"},{"ID": 12202044,"Position": 32,"PlayerID": 92,"Season": 2016,"Sum": 123783,"Type": "MoneyRankings"},{"ID": 12202045,"Position": 33,"PlayerID": 217,"Season": 2016,"Sum": 119258,"Type": "MoneyRankings"},{"ID": 12202046,"Position": 34,"PlayerID": 10,"Season": 2016,"Sum": 115095,"Type": "MoneyRankings"},{"ID": 12202047,"Position": 35,"PlayerID": 33,"Season": 2016,"Sum": 110767,"Type": "MoneyRankings"},{"ID": 12202048,"Position": 36,"PlayerID": 93,"Season": 2016,"Sum": 109462,"Type": "MoneyRankings"},{"ID": 12202049,"Position": 37,"PlayerID": 8,"Season": 2016,"Sum": 107558,"Type": "MoneyRankings"},{"ID": 12202050,"Position": 38,"PlayerID": 42,"Season": 2016,"Sum": 104154,"Type": "MoneyRankings"},{"ID": 12202051,"Position": 39,"PlayerID": 546,"Season": 2016,"Sum": 98787,"Type": "MoneyRankings"},{"ID": 12202052,"Position": 40,"PlayerID": 906,"Season": 2016,"Sum": 95925,"Type": "MoneyRankings"},{"ID": 12202053,"Position": 41,"PlayerID": 9,"Season": 2016,"Sum": 94412,"Type": "MoneyRankings"},{"ID": 12202054,"Position": 42,"PlayerID": 61,"Season": 2016,"Sum": 94162,"Type": "MoneyRankings"},{"ID": 12202055,"Position": 43,"PlayerID": 54,"Season": 2016,"Sum": 92375,"Type": "MoneyRankings"},{"ID": 12202056,"Position": 44,"PlayerID": 63,"Season": 2016,"Sum": 84062,"Type": "MoneyRankings"},{"ID": 12202057,"Position": 45,"PlayerID": 48,"Season": 2016,"Sum": 81412,"Type": "MoneyRankings"},{"ID": 12202058,"Position": 46,"PlayerID": 184,"Season": 2016,"Sum": 79025,"Type": "MoneyRankings"},{"ID": 12202059,"Position": 47,"PlayerID": 76,"Season": 2016,"Sum": 77858,"Type": "MoneyRankings"},{"ID": 12202060,"Position": 48,"PlayerID": 67,"Season": 2016,"Sum": 73475,"Type": "MoneyRankings"},{"ID": 12202061,"Position": 49,"PlayerID": 25,"Season": 2016,"Sum": 73200,"Type": "MoneyRankings"},{"ID": 12202062,"Position": 50,"PlayerID": 96,"Season": 2016,"Sum": 72983,"Type": "MoneyRankings"},{"ID": 12202063,"Position": 51,"PlayerID": 218,"Season": 2016,"Sum": 72300,"Type": "MoneyRankings"},{"ID": 12202064,"Position": 52,"PlayerID": 85,"Season": 2016,"Sum": 72162,"Type": "MoneyRankings"},{"ID": 12202065,"Position": 53,"PlayerID": 24,"Season": 2016,"Sum": 72042,"Type": "MoneyRankings"},{"ID": 12202066,"Position": 54,"PlayerID": 592,"Season": 2016,"Sum": 69954,"Type": "MoneyRankings"},{"ID": 12202067,"Position": 55,"PlayerID": 128,"Season": 2016,"Sum": 69117,"Type": "MoneyRankings"},{"ID": 12202068,"Position": 56,"PlayerID": 549,"Season": 2016,"Sum": 68708,"Type": "MoneyRankings"},{"ID": 12202069,"Position": 57,"PlayerID": 295,"Season": 2016,"Sum": 66775,"Type": "MoneyRankings"},{"ID": 12202070,"Position": 58,"PlayerID": 50,"Season": 2016,"Sum": 65687,"Type": "MoneyRankings"},{"ID": 12202071,"Position": 59,"PlayerID": 582,"Season": 2016,"Sum": 62558,"Type": "MoneyRankings"},{"ID": 12202072,"Position": 60,"PlayerID": 177,"Season": 2016,"Sum": 56770,"Type": "MoneyRankings"},{"ID": 12202073,"Position": 61,"PlayerID": 35,"Season": 2016,"Sum": 55970,"Type": "MoneyRankings"},{"ID": 12202074,"Position": 62,"PlayerID": 170,"Season": 2016,"Sum": 54150,"Type": "MoneyRankings"},{"ID": 12202075,"Position": 63,"PlayerID": 87,"Season": 2016,"Sum": 51562,"Type": "MoneyRankings"},{"ID": 12202076,"Position": 64,"PlayerID": 1044,"Season": 2016,"Sum": 49750,"Type": "MoneyRankings"},{"ID": 12202077,"Position": 65,"PlayerID": 21,"Season": 2016,"Sum": 48350,"Type": "MoneyRankings"},{"ID": 12202078,"Position": 66,"PlayerID": 115,"Season": 2016,"Sum": 46525,"Type": "MoneyRankings"},{"ID": 12202079,"Position": 67,"PlayerID": 32,"Season": 2016,"Sum": 45612,"Type": "MoneyRankings"},{"ID": 12202080,"Position": 68,"PlayerID": 53,"Season": 2016,"Sum": 40608,"Type": "MoneyRankings"},{"ID": 12202081,"Position": 69,"PlayerID": 898,"Season": 2016,"Sum": 36150,"Type": "MoneyRankings"},{"ID": 12202082,"Position": 70,"PlayerID": 1260,"Season": 2016,"Sum": 36100,"Type": "MoneyRankings"},{"ID": 12202083,"Position": 71,"PlayerID": 14,"Season": 2016,"Sum": 35275,"Type": "MoneyRankings"},{"ID": 12202084,"Position": 72,"PlayerID": 208,"Season": 2016,"Sum": 35025,"Type": "MoneyRankings"},{"ID": 12202085,"Position": 73,"PlayerID": 81,"Season": 2016,"Sum": 34500,"Type": "MoneyRankings"},{"ID": 12202086,"Position": 74,"PlayerID": 3,"Season": 2016,"Sum": 32625,"Type": "MoneyRankings"},{"ID": 12202087,"Position": 75,"PlayerID": 120,"Season": 2016,"Sum": 31925,"Type": "MoneyRankings"},{"ID": 12202088,"Position": 76,"PlayerID": 917,"Season": 2016,"Sum": 28850,"Type": "MoneyRankings"},{"ID": 12202089,"Position": 77,"PlayerID": 894,"Season": 2016,"Sum": 27025,"Type": "MoneyRankings"},{"ID": 12202090,"Position": 78,"PlayerID": 306,"Season": 2016,"Sum": 26212,"Type": "MoneyRankings"},{"ID": 12202091,"Position": 79,"PlayerID": 666,"Season": 2016,"Sum": 26125,"Type": "MoneyRankings"},{"ID": 12202092,"Position": 80,"PlayerID": 45,"Season": 2016,"Sum": 24725,"Type": "MoneyRankings"},{"ID": 12202093,"Position": 81,"PlayerID": 526,"Season": 2016,"Sum": 23400,"Type": "MoneyRankings"},{"ID": 12202094,"Position": 82,"PlayerID": 1763,"Season": 2016,"Sum": 22000,"Type": "MoneyRankings"},{"ID": 12202095,"Position": 83,"PlayerID": 497,"Season": 2016,"Sum": 21237,"Type": "MoneyRankings"},{"ID": 12202096,"Position": 84,"PlayerID": 193,"Season": 2016,"Sum": 21000,"Type": "MoneyRankings"},{"ID": 12202097,"Position": 85,"PlayerID": 552,"Season": 2016,"Sum": 20800,"Type": "MoneyRankings"},{"ID": 12202098,"Position": 86,"PlayerID": 946,"Season": 2016,"Sum": 18387,"Type": "MoneyRankings"},{"ID": 12202099,"Position": 87,"PlayerID": 49,"Season": 2016,"Sum": 18000,"Type": "MoneyRankings"},{"ID": 12202100,"Position": 88,"PlayerID": 448,"Season": 2016,"Sum": 17087,"Type": "MoneyRankings"},{"ID": 12202101,"Position": 89,"PlayerID": 109,"Season": 2016,"Sum": 15837,"Type": "MoneyRankings"},{"ID": 12202102,"Position": 90,"PlayerID": 23,"Season": 2016,"Sum": 15750,"Type": "MoneyRankings"},{"ID": 12202103,"Position": 91,"PlayerID": 90,"Season": 2016,"Sum": 15362,"Type": "MoneyRankings"},{"ID": 12202104,"Position": 92,"PlayerID": 947,"Season": 2016,"Sum": 15025,"Type": "MoneyRankings"},{"ID": 12202105,"Position": 93,"PlayerID": 520,"Season": 2016,"Sum": 14925,"Type": "MoneyRankings"},{"ID": 12202106,"Position": 94,"PlayerID": 26,"Season": 2016,"Sum": 14337,"Type": "MoneyRankings"},{"ID": 12202107,"Position": 95,"PlayerID": 593,"Season": 2016,"Sum": 13312,"Type": "MoneyRankings"},{"ID": 12202108,"Position": 96,"PlayerID": 954,"Season": 2016,"Sum": 13000,"Type": "MoneyRankings"},{"ID": 12202109,"Position": 97,"PlayerID": 621,"Season": 2016,"Sum": 12725,"Type": "MoneyRankings"},{"ID": 12202110,"Position": 98,"PlayerID": 108,"Season": 2016,"Sum": 12000,"Type": "MoneyRankings"},{"ID": 12202111,"Position": 99,"PlayerID": 620,"Season": 2016,"Sum": 11700,"Type": "MoneyRankings"},{"ID": 12202112,"Position": 100,"PlayerID": 151,"Season": 2016,"Sum": 11625,"Type": "MoneyRankings"},{"ID": 12202113,"Position": 101,"PlayerID": 892,"Season": 2016,"Sum": 11550,"Type": "MoneyRankings"},{"ID": 12202114,"Position": 102,"PlayerID": 20,"Season": 2016,"Sum": 11500,"Type": "MoneyRankings"},{"ID": 12202115,"Position": 103,"PlayerID": 1762,"Season": 2016,"Sum": 9600,"Type": "MoneyRankings"},{"ID": 12202116,"Position": 104,"PlayerID": 534,"Season": 2016,"Sum": 9575,"Type": "MoneyRankings"},{"ID": 12202117,"Position": 105,"PlayerID": 523,"Season": 2016,"Sum": 9250,"Type": "MoneyRankings"},{"ID": 12202118,"Position": 106,"PlayerID": 475,"Season": 2016,"Sum": 9000,"Type": "MoneyRankings"},{"ID": 12202119,"Position": 107,"PlayerID": 1509,"Season": 2016,"Sum": 8500,"Type": "MoneyRankings"},{"ID": 12202120,"Position": 108,"PlayerID": 1577,"Season": 2016,"Sum": 8000,"Type": "MoneyRankings"},{"ID": 12202121,"Position": 109,"PlayerID": 74,"Season": 2016,"Sum": 7862,"Type": "MoneyRankings"},{"ID": 12202122,"Position": 110,"PlayerID": 269,"Season": 2016,"Sum": 7800,"Type": "MoneyRankings"},{"ID": 12202123,"Position": 111,"PlayerID": 124,"Season": 2016,"Sum": 6625,"Type": "MoneyRankings"},{"ID": 12202124,"Position": 112,"PlayerID": 608,"Season": 2016,"Sum": 6337,"Type": "MoneyRankings"},{"ID": 12202125,"Position": 113,"PlayerID": 131,"Season": 2016,"Sum": 6025,"Type": "MoneyRankings"},{"ID": 12202126,"Position": 114,"PlayerID": 1114,"Season": 2016,"Sum": 5025,"Type": "MoneyRankings"},{"ID": 12202127,"Position": 115,"PlayerID": 515,"Season": 2016,"Sum": 5000,"Type": "MoneyRankings"},{"ID": 12202128,"Position": 116,"PlayerID": 762,"Season": 2016,"Sum": 4812,"Type": "MoneyRankings"},{"ID": 12202129,"Position": 117,"PlayerID": 507,"Season": 2016,"Sum": 4525,"Type": "MoneyRankings"},{"ID": 12202130,"Position": 118,"PlayerID": 2064,"Season": 2016,"Sum": 3025,"Type": "MoneyRankings"},{"ID": 12202131,"Position": 119,"PlayerID": 133,"Season": 2016,"Sum": 3000,"Type": "MoneyRankings"},{"ID": 12202132,"Position": 119,"PlayerID": 165,"Season": 2016,"Sum": 3000,"Type": "MoneyRankings"},{"ID": 12202133,"Position": 121,"PlayerID": 18,"Season": 2016,"Sum": 2500,"Type": "MoneyRankings"},{"ID": 12202134,"Position": 122,"PlayerID": 1505,"Season": 2016,"Sum": 2100,"Type": "MoneyRankings"},{"ID": 12202135,"Position": 123,"PlayerID": 1737,"Season": 2016,"Sum": 1312,"Type": "MoneyRankings"},{"ID": 12202136,"Position": 124,"PlayerID": 416,"Season": 2016,"Sum": 1050,"Type": "MoneyRankings"},{"ID": 12202140,"Position": 125,"PlayerID": 339,"Season": 2016,"Sum": 0,"Type": "MoneyRankings"},{"ID": 12202141,"Position": 125,"PlayerID": 422,"Season": 2016,"Sum": 0,"Type": "MoneyRankings"},{"ID": 12202137,"Position": 125,"PlayerID": 583,"Season": 2016,"Sum": 0,"Type": "MoneyRankings"},{"ID": 12202138,"Position": 125,"PlayerID": 1578,"Season": 2016,"Sum": 0,"Type": "MoneyRankings"},{"ID": 12202139,"Position": 125,"PlayerID": 1764,"Season": 2016,"Sum": 0,"Type": "MoneyRankings"}]
\ No newline at end of file
diff --git a/src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.ser b/src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.ser
new file mode 100644 (file)
index 0000000..026534c
Binary files /dev/null and b/src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.ser differ