From 8a35619be41b2db6d339f8f0a7f3ba0fc1ca1ed4 Mon Sep 17 00:00:00 2001 From: gotty Date: Sat, 21 Jan 2017 01:57:01 +0000 Subject: [PATCH] [LIB-2] Add snooker-score-api source files git-svn-id: https://svn.hedgecode.org/lib/snooker-score-api/trunk@98 fb0bcced-7025-49ed-a12f-f98bce993226 --- src/main/java/org/hedgecode/snooker/Snooker.java | 49 ++++ .../org/hedgecode/snooker/SnookerScoreApp.java | 97 ++++++ .../org/hedgecode/snooker/api/APIException.java | 42 +++ .../hedgecode/snooker/api/CollectionEntity.java | 34 +++ src/main/java/org/hedgecode/snooker/api/Event.java | 106 +++++++ .../java/org/hedgecode/snooker/api/Events.java | 44 +++ .../java/org/hedgecode/snooker/api/IdEntity.java | 28 ++ src/main/java/org/hedgecode/snooker/api/Match.java | 98 +++++++ .../java/org/hedgecode/snooker/api/Matches.java | 37 +++ .../org/hedgecode/snooker/api/OngoingMatch.java | 26 ++ .../org/hedgecode/snooker/api/OngoingMatches.java | 28 ++ .../java/org/hedgecode/snooker/api/Player.java | 68 +++++ .../org/hedgecode/snooker/api/PlayerCategory.java | 39 +++ .../java/org/hedgecode/snooker/api/Players.java | 35 +++ .../java/org/hedgecode/snooker/api/Ranking.java | 40 +++ .../org/hedgecode/snooker/api/RankingType.java | 146 ++++++++++ .../java/org/hedgecode/snooker/api/Rankings.java | 32 ++ .../java/org/hedgecode/snooker/api/Season.java | 72 +++++ .../org/hedgecode/snooker/api/SnookerScoreAPI.java | 50 ++++ .../hedgecode/snooker/cache/CacheSnookerScore.java | 184 ++++++++++++ .../cache/assign/CacheCollectionAssigner.java | 51 ++++ .../snooker/cache/assign/CacheIdAssigner.java | 31 ++ .../snooker/cache/assign/CollectionAssigner.java | 31 ++ .../snooker/cache/assign/EventAssigner.java | 53 ++++ .../snooker/cache/assign/EventsAssigner.java | 44 +++ .../hedgecode/snooker/cache/assign/IdAssigner.java | 31 ++ .../snooker/cache/assign/MatchAssigner.java | 67 +++++ .../snooker/cache/assign/MatchesAssigner.java | 55 ++++ .../snooker/cache/assign/RankingAssigner.java | 51 ++++ .../snooker/cache/assign/RankingsAssigner.java | 44 +++ .../snooker/compare/EventComparators.java | 63 ++++ .../snooker/compare/MatchComparators.java | 65 +++++ .../snooker/compare/PlayerComparators.java | 63 ++++ .../snooker/compare/RankingComparators.java | 64 ++++ .../snooker/gson/EmptyDateTypeAdapter.java | 103 +++++++ .../hedgecode/snooker/gson/SnookerGsonBuilder.java | 42 +++ .../snooker/json/JsonCollectionEntity.java | 91 ++++++ .../java/org/hedgecode/snooker/json/JsonEvent.java | 324 +++++++++++++++++++++ .../org/hedgecode/snooker/json/JsonEvents.java | 159 ++++++++++ .../org/hedgecode/snooker/json/JsonIdEntity.java | 48 +++ .../java/org/hedgecode/snooker/json/JsonMatch.java | 306 +++++++++++++++++++ .../org/hedgecode/snooker/json/JsonMatches.java | 109 +++++++ .../hedgecode/snooker/json/JsonOngoingMatch.java | 28 ++ .../hedgecode/snooker/json/JsonOngoingMatches.java | 42 +++ .../org/hedgecode/snooker/json/JsonPlayer.java | 178 +++++++++++ .../org/hedgecode/snooker/json/JsonPlayers.java | 98 +++++++ .../org/hedgecode/snooker/json/JsonRanking.java | 102 +++++++ .../org/hedgecode/snooker/json/JsonRankings.java | 71 +++++ .../hedgecode/snooker/json/JsonSerializable.java | 28 ++ .../hedgecode/snooker/json/JsonSnookerScore.java | 304 +++++++++++++++++++ .../hedgecode/snooker/json/JsonStringToken.java | 38 +++ .../snooker/request/AbstractRequester.java | 77 +++++ .../snooker/request/EventMatchesRequester.java | 57 ++++ .../snooker/request/EventPlayersRequester.java | 57 ++++ .../hedgecode/snooker/request/EventRequester.java | 57 ++++ .../hedgecode/snooker/request/MatchRequester.java | 60 ++++ .../snooker/request/OngoingMatchesRequester.java | 47 +++ .../snooker/request/PlayerMatchesRequester.java | 66 +++++ .../hedgecode/snooker/request/PlayerRequester.java | 57 ++++ .../snooker/request/RankingRequester.java | 57 ++++ .../snooker/request/RequestException.java | 37 +++ .../hedgecode/snooker/request/RequestParams.java | 130 +++++++++ .../org/hedgecode/snooker/request/RequestType.java | 63 ++++ .../org/hedgecode/snooker/request/Requester.java | 30 ++ .../snooker/request/SeasonEventsRequester.java | 56 ++++ .../snooker/request/SeasonPlayersRequester.java | 64 ++++ .../java/org/hedgecode/snooker/api/SeasonTest.java | 55 ++++ .../hedgecode/snooker/json/AbstractJsonTest.java | 108 +++++++ .../org/hedgecode/snooker/json/JsonEventTest.java | 94 ++++++ .../org/hedgecode/snooker/json/JsonEventsTest.java | 64 ++++ .../org/hedgecode/snooker/json/JsonMatchTest.java | 86 ++++++ .../hedgecode/snooker/json/JsonMatchesTest.java | 64 ++++ .../snooker/json/JsonOngoingMatchTest.java | 52 ++++ .../snooker/json/JsonOngoingMatchesTest.java | 64 ++++ .../org/hedgecode/snooker/json/JsonPlayerTest.java | 75 +++++ .../hedgecode/snooker/json/JsonPlayersTest.java | 64 ++++ .../hedgecode/snooker/json/JsonRankingTest.java | 61 ++++ .../hedgecode/snooker/json/JsonRankingsTest.java | 64 ++++ .../snooker/json/JsonStringTokenTest.java | 53 ++++ .../org/hedgecode/snooker/json/JsonEventTest.json | 1 + .../org/hedgecode/snooker/json/JsonEventTest.ser | Bin 0 -> 1185 bytes .../org/hedgecode/snooker/json/JsonEventsTest.json | 1 + .../org/hedgecode/snooker/json/JsonEventsTest.ser | Bin 0 -> 25544 bytes .../org/hedgecode/snooker/json/JsonMatchTest.json | 1 + .../org/hedgecode/snooker/json/JsonMatchTest.ser | Bin 0 -> 949 bytes .../hedgecode/snooker/json/JsonMatchesTest.json | 1 + .../org/hedgecode/snooker/json/JsonMatchesTest.ser | Bin 0 -> 4028 bytes .../snooker/json/JsonOngoingMatchTest.json | 1 + .../snooker/json/JsonOngoingMatchTest.ser | Bin 0 -> 909 bytes .../snooker/json/JsonOngoingMatchesTest.json | 1 + .../snooker/json/JsonOngoingMatchesTest.ser | Bin 0 -> 1435 bytes .../org/hedgecode/snooker/json/JsonPlayerTest.json | 1 + .../org/hedgecode/snooker/json/JsonPlayerTest.ser | Bin 0 -> 651 bytes .../hedgecode/snooker/json/JsonPlayersTest.json | 1 + .../org/hedgecode/snooker/json/JsonPlayersTest.ser | Bin 0 -> 21312 bytes .../hedgecode/snooker/json/JsonRankingTest.json | 1 + .../org/hedgecode/snooker/json/JsonRankingTest.ser | Bin 0 -> 385 bytes .../hedgecode/snooker/json/JsonRankingsTest.json | 1 + .../hedgecode/snooker/json/JsonRankingsTest.ser | Bin 0 -> 8292 bytes 99 files changed, 5868 insertions(+) create mode 100644 src/main/java/org/hedgecode/snooker/Snooker.java create mode 100644 src/main/java/org/hedgecode/snooker/SnookerScoreApp.java create mode 100644 src/main/java/org/hedgecode/snooker/api/APIException.java create mode 100644 src/main/java/org/hedgecode/snooker/api/CollectionEntity.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Event.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Events.java create mode 100644 src/main/java/org/hedgecode/snooker/api/IdEntity.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Match.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Matches.java create mode 100644 src/main/java/org/hedgecode/snooker/api/OngoingMatch.java create mode 100644 src/main/java/org/hedgecode/snooker/api/OngoingMatches.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Player.java create mode 100644 src/main/java/org/hedgecode/snooker/api/PlayerCategory.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Players.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Ranking.java create mode 100644 src/main/java/org/hedgecode/snooker/api/RankingType.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Rankings.java create mode 100644 src/main/java/org/hedgecode/snooker/api/Season.java create mode 100644 src/main/java/org/hedgecode/snooker/api/SnookerScoreAPI.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/CacheSnookerScore.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/CacheCollectionAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/CacheIdAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/CollectionAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/EventAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/EventsAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/IdAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/MatchAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/MatchesAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/RankingAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/cache/assign/RankingsAssigner.java create mode 100644 src/main/java/org/hedgecode/snooker/compare/EventComparators.java create mode 100644 src/main/java/org/hedgecode/snooker/compare/MatchComparators.java create mode 100644 src/main/java/org/hedgecode/snooker/compare/PlayerComparators.java create mode 100644 src/main/java/org/hedgecode/snooker/compare/RankingComparators.java create mode 100644 src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java create mode 100644 src/main/java/org/hedgecode/snooker/gson/SnookerGsonBuilder.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonCollectionEntity.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonEvent.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonEvents.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonIdEntity.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonMatch.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonMatches.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonOngoingMatch.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonOngoingMatches.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonPlayer.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonPlayers.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonRanking.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonRankings.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonSerializable.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonSnookerScore.java create mode 100644 src/main/java/org/hedgecode/snooker/json/JsonStringToken.java create mode 100644 src/main/java/org/hedgecode/snooker/request/AbstractRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/EventMatchesRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/EventPlayersRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/EventRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/MatchRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/OngoingMatchesRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/PlayerMatchesRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/PlayerRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/RankingRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/RequestException.java create mode 100644 src/main/java/org/hedgecode/snooker/request/RequestParams.java create mode 100644 src/main/java/org/hedgecode/snooker/request/RequestType.java create mode 100644 src/main/java/org/hedgecode/snooker/request/Requester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/SeasonEventsRequester.java create mode 100644 src/main/java/org/hedgecode/snooker/request/SeasonPlayersRequester.java create mode 100644 src/test/java/org/hedgecode/snooker/api/SeasonTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/AbstractJsonTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonEventTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonEventsTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonMatchTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonMatchesTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchesTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonPlayerTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonPlayersTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonRankingTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonRankingsTest.java create mode 100644 src/test/java/org/hedgecode/snooker/json/JsonStringTokenTest.java create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonEventTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonEventTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonEventsTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonMatchTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonMatchesTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonOngoingMatchesTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonRankingTest.ser create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.json create mode 100644 src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.ser diff --git a/src/main/java/org/hedgecode/snooker/Snooker.java b/src/main/java/org/hedgecode/snooker/Snooker.java new file mode 100644 index 0000000..d133db6 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/Snooker.java @@ -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 index 0000000..e81bc6e --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/SnookerScoreApp.java @@ -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 index 0000000..6a87e07 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/APIException.java @@ -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 index 0000000..25a0234 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/CollectionEntity.java @@ -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 extends Iterable { + + 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 index 0000000..45b50b5 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Event.java @@ -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 index 0000000..675c3f9 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Events.java @@ -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 { + + 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 index 0000000..699ea8f --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/IdEntity.java @@ -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 index 0000000..b006c32 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Match.java @@ -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 index 0000000..1777cef --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Matches.java @@ -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 { + + 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 index 0000000..688df16 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/OngoingMatch.java @@ -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 index 0000000..ed26c21 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/OngoingMatches.java @@ -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 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 index 0000000..9c6c7ea --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Player.java @@ -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 index 0000000..b99be6f --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/PlayerCategory.java @@ -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 index 0000000..c4be2ab --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Players.java @@ -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 { + + 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 index 0000000..a0e921e --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Ranking.java @@ -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 index 0000000..699b706 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/RankingType.java @@ -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 index 0000000..07e4e1b --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Rankings.java @@ -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 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 index 0000000..73ee53a --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/Season.java @@ -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 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 index 0000000..787f9fd --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/api/SnookerScoreAPI.java @@ -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 index 0000000..df72b51 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/CacheSnookerScore.java @@ -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 index 0000000..571acdf --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/CacheCollectionAssigner.java @@ -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 + , A extends IdAssigner> + implements CollectionAssigner +{ + 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 index 0000000..8a5d0d8 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/CacheIdAssigner.java @@ -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 implements IdAssigner { + + 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 index 0000000..b3ee8d5 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/CollectionAssigner.java @@ -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 { + + 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 index 0000000..8c2cc8b --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/EventAssigner.java @@ -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 { + + 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 index 0000000..d959a95 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/EventsAssigner.java @@ -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 +{ + 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 index 0000000..4bfd4d6 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/IdAssigner.java @@ -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 { + + 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 index 0000000..5c2ac85 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/MatchAssigner.java @@ -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 { + + 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 index 0000000..e0a1323 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/MatchesAssigner.java @@ -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 +{ + 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 index 0000000..bfe84cd --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/RankingAssigner.java @@ -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 { + + 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 index 0000000..d3751dd --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/cache/assign/RankingsAssigner.java @@ -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 +{ + 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 index 0000000..481435d --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/compare/EventComparators.java @@ -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 comparator; + + EventComparators(Comparator comparator) { + this.comparator = comparator; + } + + public Comparator comparator() { + return comparator; + } + + static class DateComparator implements Comparator { + + @Override + public int compare(Event event1, Event event2) { + return event1.startDate().compareTo(event2.startDate()); + } + + } + + static class SnookerIdComparator implements Comparator { + + @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 index 0000000..939b1bc --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/compare/MatchComparators.java @@ -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 comparator; + + MatchComparators(Comparator comparator) { + this.comparator = comparator; + } + + public Comparator comparator() { + return comparator; + } + + static class RoundNumberComparator implements Comparator { + + @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 { + + @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 index 0000000..834f2e7 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/compare/PlayerComparators.java @@ -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 comparator; + + PlayerComparators(Comparator comparator) { + this.comparator = comparator; + } + + public Comparator comparator() { + return comparator; + } + + static class NameComparator implements Comparator { + + @Override + public int compare(Player player1, Player player2) { + return player1.lastName().compareTo(player2.lastName()); + } + + } + + static class AgeComparator implements Comparator { + + @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 index 0000000..f7551e0 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/compare/RankingComparators.java @@ -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 comparator; + + RankingComparators(Comparator comparator) { + this.comparator = comparator; + } + + public Comparator comparator() { + return comparator; + } + + static class PositionComparator implements Comparator { + + @Override + public int compare(Ranking ranking1, Ranking ranking2) { + return ranking1.position() - ranking2.position(); + } + + } + + static class SumComparator implements Comparator { + + @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 index 0000000..5c625c5 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/gson/EmptyDateTypeAdapter.java @@ -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 { + + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + return typeToken.getRawType() == Date.class + ? (TypeAdapter) 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 index 0000000..07718fb --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/gson/SnookerGsonBuilder.java @@ -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 index 0000000..3223323 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonCollectionEntity.java @@ -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 + implements CollectionEntity, JsonSerializable +{ + private final Map entities = new LinkedHashMap<>(); + + protected JsonCollectionEntity(E[] entities) { + for (E entity : entities) { + if (entity != null) + this.entities.put(entity.getId(), entity); + } + } + + protected JsonCollectionEntity(List 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 iterator() { + return entities.values().iterator(); + } + + @Override + public E byId(int id) { + return entities.get(id); + } + + protected void sort(Comparator comparator) { + List 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 index 0000000..2f47ee4 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonEvent.java @@ -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 index 0000000..78474de --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonEvents.java @@ -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 implements Events { + + protected JsonEvents(Event[] entities) { + super(entities); + } + + protected JsonEvents(List entities) { + super(entities); + } + + @Override + public Events bySeason(Season season) { + List 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 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 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 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 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 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 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 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 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 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 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 index 0000000..6b6c213 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonIdEntity.java @@ -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 index 0000000..2731565 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonMatch.java @@ -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 index 0000000..0d4dd02 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonMatches.java @@ -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 implements Matches { + + protected JsonMatches(Match[] entities) { + super(entities); + } + + protected JsonMatches(List entities) { + super(entities); + } + + @Override + public Matches byEvent(int eventId) { + List 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 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 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 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 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 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 index 0000000..6e5cb1d --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonOngoingMatch.java @@ -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 index 0000000..7c18095 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonOngoingMatches.java @@ -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 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 index 0000000..6db13d1 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonPlayer.java @@ -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 index 0000000..26c68e2 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonPlayers.java @@ -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 implements Players { + + protected JsonPlayers(Player[] entities) { + super(entities); + } + + protected JsonPlayers(List entities) { + super(entities); + } + + @Override + public Players byType(int type) { + List 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 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 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 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 index 0000000..02e08f5 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonRanking.java @@ -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 index 0000000..75a3358 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonRankings.java @@ -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 implements Rankings { + + protected JsonRankings(Ranking[] entities) { + super(entities); + } + + protected JsonRankings(List 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 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 index 0000000..8d7db08 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonSerializable.java @@ -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 index 0000000..aa27161 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonSnookerScore.java @@ -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 index 0000000..b7dd25a --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/json/JsonStringToken.java @@ -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 index 0000000..a127bb5 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/AbstractRequester.java @@ -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 index 0000000..c3315be --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/EventMatchesRequester.java @@ -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 index 0000000..fe4722a --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/EventPlayersRequester.java @@ -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 index 0000000..09df212 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/EventRequester.java @@ -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 index 0000000..e2005f4 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/MatchRequester.java @@ -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 index 0000000..b78b88f --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/OngoingMatchesRequester.java @@ -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 index 0000000..3de47c5 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/PlayerMatchesRequester.java @@ -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 index 0000000..46b7656 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/PlayerRequester.java @@ -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 index 0000000..b9255dc --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/RankingRequester.java @@ -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 index 0000000..a227a9f --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/RequestException.java @@ -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 index 0000000..a11da9b --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/RequestParams.java @@ -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 index 0000000..d62bbb1 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/RequestType.java @@ -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 index 0000000..6cb8003 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/Requester.java @@ -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 index 0000000..ff548f1 --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/SeasonEventsRequester.java @@ -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 index 0000000..e5b204d --- /dev/null +++ b/src/main/java/org/hedgecode/snooker/request/SeasonPlayersRequester.java @@ -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 index 0000000..0c618af --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/api/SeasonTest.java @@ -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 index 0000000..0ef6fa6 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/AbstractJsonTest.java @@ -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 index 0000000..0262013 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonEventTest.java @@ -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 index 0000000..8a238f6 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonEventsTest.java @@ -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 index 0000000..0895582 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonMatchTest.java @@ -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 index 0000000..acc2656 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonMatchesTest.java @@ -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 index 0000000..faca10e --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchTest.java @@ -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 index 0000000..590d6f7 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonOngoingMatchesTest.java @@ -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 index 0000000..9b3ae63 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonPlayerTest.java @@ -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 index 0000000..cae5606 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonPlayersTest.java @@ -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 index 0000000..6dcf4c7 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonRankingTest.java @@ -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 index 0000000..7f1e953 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonRankingsTest.java @@ -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 index 0000000..202a672 --- /dev/null +++ b/src/test/java/org/hedgecode/snooker/json/JsonStringTokenTest.java @@ -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 index 0000000..2c1ec93 --- /dev/null +++ b/src/test/resources/org/hedgecode/snooker/json/JsonEventTest.json @@ -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": "BBC<\u002Fa>, 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 index 0000000000000000000000000000000000000000..3723494f3e68c78fe2218ea1c974b7ec020b77bc GIT binary patch literal 1185 zcmah|&2G~`5T3MY-KJG&;X-dAsssmQ-#~&=)Sna?(o*&3&`KP(-f8UC-Zi`9B$ZHA zUIKAKa7Bm%H?CZGfr>LPz&kLGofL6^D7MDm&U`cT&FrUNFkuZWYSVE;lpPGTMAs^< zPtmw1Rx9@@zgk^X^y=&U&9|FhK90eiL#T^5-qD$oc122*8&D6l>Y}lcRy%^whk1#| zsAQx%YoSO|#(i)wC-Nnq4y$Im1` zQ+)IR!1>Acy#s>EbArjXR#Gd1^Ci&;4IV#ghD7ND&+GMi?$J@;2HMR|JzfTJhNii^ zy1KUHiRHVEzx^>Ynl&?2cye6gHJ4jMG!JSBB^wrF40vLVBP8NsHf%&_37nSd@XAWI z$|d1@Ue7n#&3DbsEurosport 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 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 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 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 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 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 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 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 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 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 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 Eurosport Player<\u002Fa>, 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 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 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 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 Eurosport Player<\u002Fa>, 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": "BBC<\u002Fa>, 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": "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": "Eurosport<\u002Fa>, 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": "BBC<\u002Fa>, 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 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 index 0000000000000000000000000000000000000000..4877309bebe10ab40a95ccaeb5a3c7846509aee2 GIT binary patch literal 25544 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 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 index 0000000000000000000000000000000000000000..aa94b374a7a905dc2cc305f82c929d6602e7f7df GIT binary patch literal 4028 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 COS7H; literal 0 HcmV?d00001 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 index 0000000..fe2481a --- /dev/null +++ b/src/test/resources/org/hedgecode/snooker/json/JsonPlayerTest.json @@ -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 index 0000000000000000000000000000000000000000..e95ccd56ca6b31fcb9699b421c7a5cdb5be62e23 GIT binary patch literal 651 zcmah{%W4!s6uq69VcIc>h?^_|*~CB=T?j%zccMa%Ga+FhLBU1M^i6k7>d~pX?aXY% z{Dj}&LP8e)hLApO`u_Fh8az%RF6&sDy@z#ISX&iI1}U^B!w=m zN*qCdD$D`Tk>Js2&OdS{xz5>ytkC(35p<`8=U~Yh&}F;!yi|lmjpo2 z9dmnHTk&y&Q+v^npm)qAIs*0&cA>%q;g>iTAll}n)Hy*kCRiVD4Y%5GjX6-h&`Y5)KL literal 0 HcmV?d00001 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 index 0000000..fc6fb5c --- /dev/null +++ b/src/test/resources/org/hedgecode/snooker/json/JsonPlayersTest.json @@ -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 index 0000000000000000000000000000000000000000..9a9046e2ced0b7941636b525545e1a34cbdc179b GIT binary patch literal 21312 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 literal 0 HcmV?d00001 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 index 0000000..5ea068f --- /dev/null +++ b/src/test/resources/org/hedgecode/snooker/json/JsonRankingsTest.json @@ -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 index 0000000000000000000000000000000000000000..026534cc68520213dc463ed6e76931b1daebddac GIT binary patch literal 8292 zcma*sdu&tJ9S88Aubns$7zAhn6i5gVUcpWvKu7|CK%OKJ65inv6JHW1#&&Gy#hbRg z3oQi#r4P}KbyeGSg|<@_Z5ni)1lu%?wc0eMPA+tR4YW?`HmTL5eQ)A(e*R}aI8ve` z=X~z(_?&Zp=iHljA5l^yOf!SwR#%(pZ8ckhUegr`1cM!B*wr2h23$4x)!+$q_yVnw zaldQW)pd46nL*SWCii31%AntGwnTlwKzShQi}qbkcildE@ZXONveiRxp5m zhll3E`gnN6^k8DdT-SIhfdqO^U{osX*YbiB;vGsi+ zGfFcB67QhZ5H5KrupFgvuybhbhz?$U%+NGjBjs+4hOwTCF?^3(dez>c#q-|hf85?b zVR7Tos1l`NnrznS5;Hy7Rnzl@$Q#JK~CV@`XH2JPuqS>0pK$AhUncn%Y zM5k$b1=Je2X__Xz-6YZJnmRyJK&NZ!_=nix8JfNYIt+9M)Atbc|IcfVroRRq4w}QX zKTo1FHN6d*3ObW%$qyttOViPyBS2>{&Au+t*_tMSjs%^}^r=#b&e8OB(C>lH(bWF; zB@&&hsg>bIfzD-m`$rPZ)fB@+qd{|-etJft^E6!sng%+L>FV1Ob!nOoItJ9GsqyVX ziMlm?8gwkEo9Vp|B$}sbH|RLfJf@#lOEh28NuW=G<}{^K~)D-!cCV(zv>i?BQ7insOP6S=VboE1tF4lA` z=+mH!nU+^cv`|y5U77@1$h62K(IuK<713nSB}^T^m1vQs7+LH)19?SEZRaIgtm!Dw zOweLYZQuAMTB7MT&@9jrrVoxwbg8C)2AvAJlykuE zHN_4`(?Cm^zW)=6F4uHB=ycHKOyB93=n747?4uc=E0|u(k!YEw$iI{WTE?_r9Hy0u z8rYI)Cg@70M;=H~S1D>g1v(29_pLLAI!3trBZ-zPioKO+HfTB1khq2`G{sV&IiM9x zgMW~sR%(h{oaTa7GHv^lM5{E#QlMPWDyCICBwDR0Qa8;5t!BE+A<-I5KL&My)-Wv) zclFhp)`Gf0S2NAamZH{bilsn#ptyuHhC1do(=O3EO(&pnK4=}&$zMx!ji$|@^Fh}n z&6wMvFijn5LCU zv{6wy47wP!k?BbBD7{`$1BY2E1YOT`gjb5XK~bA^oT4q5`bndujwNZ)mfrg+kzrJ!4w-uu2pw`%$} z=rYi)Og}p&(I!pt9jO$wiRm42HEmPWF%EP&DE3)r40V)GHcC;qD~j_W(F#y(Th18j zC_nqFM0aQ!LEAFW9ZWy^xkPtrngzNNbSKjrxe{&G6bC$71=`H?^{W!~C~AKOv>epK z^voiO?o!n85VQhxR{|ANc#EQVJR+(DZDD%yH&RruroRWR0`)RIaaW?IrpQTD4T{69 zGln|Ku}>wsTT?sQ)`0G2dZ<&Pt(x|Nt_E#ox?emHv?*%82wDr;#x!(8it5w!AZQ(^ zkEu_5SZP<(X62?epzTa|iy5&)QNwyKu@{k?r0it?PKhx%m65XSyVXdZh zpnI4$wMjIfXz~Nl2G9W04PQ$%sHp9qppBqGrVam+Xh>1I1-c$Ilt5D?+Nr34R~fVc zw3F$&p5Gh7`3|QTqp=+dy&4 zJ7cJ$6kV5SpQ48KoUz1$~z3 zjKdOrPEjKrv<>vR1llUmqnf6I`aq8|ot`bxV~X1T0@@CGjOnyl5 zS|HIAiYDXbE>_e)-U+6eVlq9cC=LUJ{4|hvlIfJ6N>NWKY8wd}06mpJdnI~WQLy+qAzOtEoc<_ z!W~0Bpyw0l#}d7u=?~-d!jsaAnvMbOLsT3yoiWr=hKc9lenpeMMBBZf{Y+EDo9>dL z$#+2afg-6oW2mDfWl7)lvZA)DXuBWuGE>JyiN307Bj^FpSDE5|5dL@dnx=2Y>1$6) hUslwpjMJB&lwMIZc}|>Oc~bg{reDSBE03YQ^goDbZC3yQ literal 0 HcmV?d00001 -- 2.10.0