--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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() + ")"
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+/**
+ * Abstract Collection of Entities API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface CollectionEntity<E extends IdEntity> extends Iterable<E> {
+
+ E byId(int id);
+
+ int size();
+
+ boolean isEmpty();
+
+ void sortById();
+
+}
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+/**
+ * Events Entity (set of {@link Event}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Events extends CollectionEntity<Event> {
+
+ Events bySeason(Season season);
+
+ Events byType(String type);
+ Events byCity(String city);
+ Events byCountry(String country);
+ Events bySex(String sex);
+ Events byStage(String stage);
+ Events byValueType(String valueType);
+
+ Events bySnookerId(int worldSnookerId);
+
+ Events ended();
+ Events current();
+ Events upcoming();
+
+ void sortByDate();
+ void sortBySnookerId();
+
+}
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+/**
+ * Matches Entity (set of {@link Match}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Matches extends CollectionEntity<Match> {
+
+ Matches byEvent(int eventId);
+ Matches byRound(int eventId, int round);
+ Matches byPlayer(int playerId);
+
+ Matches ended();
+ Matches current();
+ Matches upcoming();
+
+ void sortByNumber();
+ void sortByEvent();
+
+}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+/**
+ * Ongoing Matches Entity (set of {@link OngoingMatch}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface OngoingMatches extends CollectionEntity<OngoingMatch> {
+
+ OngoingMatch byNumber(int number);
+
+}
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+/**
+ * Players Entity (set of {@link Player}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Players extends CollectionEntity<Player> {
+
+ Players byType(int type);
+ Players byName(String name);
+ Players byNationality(String nationality);
+ Players bySex(String sex);
+
+ void sortByName();
+ void sortByAge();
+ void sortByAgeDesc();
+
+}
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+/**
+ * Rankings Entity (set of {@link Ranking}) API Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface Rankings extends CollectionEntity<Ranking> {
+
+ Ranking byPlayer(int playerId);
+ Rankings bySum(long minSum, long maxSum);
+
+ void sortByPosition();
+ void sortBySum();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.api;
+
+import java.util.Calendar;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Season Entity.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class Season {
+
+ private static final Calendar CURRENT_CALENDAR = Calendar.getInstance();
+
+ public static final int BEGIN_YEAR = 2005;
+ public static final int CURRENT_YEAR =
+ CURRENT_CALENDAR.get(Calendar.MONTH) >= 6
+ ? CURRENT_CALENDAR.get(Calendar.YEAR)
+ : CURRENT_CALENDAR.get(Calendar.YEAR) - 1;
+
+ private static final int ALL_SEASONS = -1;
+
+ public static final Season ALL = new Season(ALL_SEASONS);
+ public static final Season CURRENT_SEASON = new Season(CURRENT_YEAR);
+
+ public static Map<Integer, Season> SEASONS = new LinkedHashMap<>();
+
+ static {
+ for (int year = BEGIN_YEAR; year < CURRENT_YEAR; ++year) {
+ SEASONS.put(year, new Season(year));
+ }
+ SEASONS.put(CURRENT_YEAR, CURRENT_SEASON);
+ SEASONS.put(ALL_SEASONS, ALL);
+ }
+
+ private int year;
+
+ private Season(int year) {
+ this.year = year;
+ }
+
+ public static Season getSeason(int year) {
+ return SEASONS.get(year);
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ @Override
+ public String toString() {
+ return year == ALL_SEASONS ? "All Seasons" : year + "/" + (year + 1);
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.CollectionEntity;
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Abstract Assigner for Collections of Entities.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class CacheCollectionAssigner
+ <T extends IdEntity, E extends CollectionEntity<T>, A extends IdAssigner<T>>
+ implements CollectionAssigner<E>
+{
+ private A entityAsssigner;
+
+ protected CacheCollectionAssigner(A entityAsssigner) {
+ this.entityAsssigner = entityAsssigner;
+ }
+
+ public A assigner() {
+ return entityAsssigner;
+ }
+
+ @Override
+ public void assign(E entities) throws APIException {
+ for (T entity : entities) {
+ entityAsssigner.assign(
+ entity
+ );
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.IdEntity;
+import org.hedgecode.snooker.cache.CacheSnookerScore;
+
+/**
+ * Abstract Assigner for Entities.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class CacheIdAssigner<E extends IdEntity> implements IdAssigner<E> {
+
+ protected static final CacheSnookerScore cacheScore = CacheSnookerScore.getInstance();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.CollectionEntity;
+
+/**
+ * Assigner for Collections Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface CollectionAssigner<E extends CollectionEntity> {
+
+ void assign(E entity) throws APIException;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.json.JsonEvent;
+
+/**
+ * Assigner for Entity fields of {@link Event}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventAssigner extends CacheIdAssigner<Event> {
+
+ private static EventAssigner _instance;
+
+ private EventAssigner() {
+ }
+
+ public static EventAssigner getInstance() {
+ if (_instance == null)
+ _instance = new EventAssigner();
+ return _instance;
+ }
+
+ @Override
+ public void assign(Event event) throws APIException {
+ if (event.mainEventId() != event.eventId() && event.mainEventId() > 0) {
+ JsonEvent jsonEvent = (JsonEvent) event;
+ jsonEvent.setMainEvent(
+ cacheScore.getCachedEvent(
+ event.mainEventId()
+ )
+ );
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+
+/**
+ * Assigner for Collections of Entities {@link Event}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class EventsAssigner
+ extends CacheCollectionAssigner<Event, Events, EventAssigner>
+{
+ private static EventsAssigner _instance;
+
+ private EventsAssigner() {
+ super(
+ EventAssigner.getInstance()
+ );
+ }
+
+ public static EventsAssigner getInstance() {
+ if (_instance == null)
+ _instance = new EventsAssigner();
+ return _instance;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Assigner for Entities Interface.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public interface IdAssigner<E extends IdEntity> {
+
+ void assign(E entity) throws APIException;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.json.JsonMatch;
+
+/**
+ * Assigner for Entity fields of {@link Match}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class MatchAssigner extends CacheIdAssigner<Match> {
+
+ private static MatchAssigner _instance;
+
+ private MatchAssigner() {
+ }
+
+ public static MatchAssigner getInstance() {
+ if (_instance == null)
+ _instance = new MatchAssigner();
+ return _instance;
+ }
+
+ @Override
+ public void assign(Match match) throws APIException {
+ JsonMatch jsonMatch = (JsonMatch) match;
+ jsonMatch.setEvent(
+ cacheScore.getCachedEvent(
+ match.eventId()
+ )
+ );
+ Player player1 = cacheScore.getCachedPlayer(
+ match.player1Id()
+ );
+ Player player2 = cacheScore.getCachedPlayer(
+ match.player2Id()
+ );
+ jsonMatch.setPlayer1(player1);
+ jsonMatch.setPlayer2(player2);
+ jsonMatch.setWinner(
+ match.winnerId() == match.player1Id()
+ ? player1
+ : match.winnerId() == match.player2Id()
+ ? player2
+ : null
+ );
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Matches;
+import org.hedgecode.snooker.api.OngoingMatch;
+import org.hedgecode.snooker.api.OngoingMatches;
+
+/**
+ * Assigner for Collections of Entities {@link Match}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class MatchesAssigner
+ extends CacheCollectionAssigner<Match, Matches, MatchAssigner>
+{
+ private static MatchesAssigner _instance;
+
+ private MatchesAssigner() {
+ super(
+ MatchAssigner.getInstance()
+ );
+ }
+
+ public static MatchesAssigner getInstance() {
+ if (_instance == null)
+ _instance = new MatchesAssigner();
+ return _instance;
+ }
+
+ public void assign(OngoingMatches matches) throws APIException {
+ for (OngoingMatch match : matches) {
+ assigner().assign(
+ match
+ );
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.APIException;
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.json.JsonRanking;
+
+/**
+ * Assigner for Entity fields of {@link Ranking}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RankingAssigner extends CacheIdAssigner<Ranking> {
+
+ private static RankingAssigner _instance;
+
+ private RankingAssigner() {
+ }
+
+ public static RankingAssigner getInstance() {
+ if (_instance == null)
+ _instance = new RankingAssigner();
+ return _instance;
+ }
+
+ @Override
+ public void assign(Ranking ranking) throws APIException {
+ JsonRanking jsonRanking = (JsonRanking) ranking;
+ jsonRanking.setPlayer(
+ cacheScore.getCachedPlayer(
+ ranking.playerId()
+ )
+ );
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.cache.assign;
+
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.api.Rankings;
+
+/**
+ * Assigner for Collections of Entities {@link Ranking}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class RankingsAssigner
+ extends CacheCollectionAssigner<Ranking, Rankings, RankingAssigner>
+{
+ private static RankingsAssigner _instance;
+
+ private RankingsAssigner() {
+ super(
+ RankingAssigner.getInstance()
+ );
+ }
+
+ public static RankingsAssigner getInstance() {
+ if (_instance == null)
+ _instance = new RankingsAssigner();
+ return _instance;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Event;
+
+/**
+ * Set of Comparators for {@link Event}.
+ * 1. Sorting by Date {@link DateComparator};
+ * 2. Sorting by WorldSnookerId {@link SnookerIdComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum EventComparators {
+
+ DATE ( new DateComparator() ),
+ SNOOKER_ID ( new SnookerIdComparator() );
+
+ private Comparator<Event> comparator;
+
+ EventComparators(Comparator<Event> comparator) {
+ this.comparator = comparator;
+ }
+
+ public Comparator<Event> comparator() {
+ return comparator;
+ }
+
+ static class DateComparator implements Comparator<Event> {
+
+ @Override
+ public int compare(Event event1, Event event2) {
+ return event1.startDate().compareTo(event2.startDate());
+ }
+
+ }
+
+ static class SnookerIdComparator implements Comparator<Event> {
+
+ @Override
+ public int compare(Event event1, Event event2) {
+ return event1.worldSnookerId() - event2.worldSnookerId();
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Match;
+
+/**
+ * Set of Comparators for {@link Match}.
+ * 1. Sorting by Round and Number of Match {@link RoundNumberComparator};
+ * 2. Sorting by Event {@link EventComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum MatchComparators {
+
+ ROUND_NUMBER ( new RoundNumberComparator() ),
+ EVENT ( new EventComparator() );
+
+ private Comparator<Match> comparator;
+
+ MatchComparators(Comparator<Match> comparator) {
+ this.comparator = comparator;
+ }
+
+ public Comparator<Match> comparator() {
+ return comparator;
+ }
+
+ static class RoundNumberComparator implements Comparator<Match> {
+
+ @Override
+ public int compare(Match match1, Match match2) {
+ return match1.round() == match2.round()
+ ? match1.number() - match2.round()
+ : match2.round() - match1.round();
+ }
+
+ }
+
+ static class EventComparator implements Comparator<Match> {
+
+ @Override
+ public int compare(Match match1, Match match2) {
+ return match1.eventId() - match2.eventId();
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Player;
+
+/**
+ * Set of Comparators for {@link Player}.
+ * 1. Sorting by Last Name of Player {@link NameComparator};
+ * 2. Sorting by Age of Player {@link AgeComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum PlayerComparators {
+
+ NAME ( new NameComparator() ),
+ AGE ( new AgeComparator() );
+
+ private Comparator<Player> comparator;
+
+ PlayerComparators(Comparator<Player> comparator) {
+ this.comparator = comparator;
+ }
+
+ public Comparator<Player> comparator() {
+ return comparator;
+ }
+
+ static class NameComparator implements Comparator<Player> {
+
+ @Override
+ public int compare(Player player1, Player player2) {
+ return player1.lastName().compareTo(player2.lastName());
+ }
+
+ }
+
+ static class AgeComparator implements Comparator<Player> {
+
+ @Override
+ public int compare(Player player1, Player player2) {
+ return player1.born().compareTo(player2.born());
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.compare;
+
+import java.util.Comparator;
+
+import org.hedgecode.snooker.api.Ranking;
+
+/**
+ * Set of Comparators for {@link Ranking}.
+ * 1. Sorting by Player Position {@link PositionComparator};
+ * 2. Sorting by Player Earned Money {@link SumComparator}.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public enum RankingComparators {
+
+ POSITION ( new PositionComparator() ),
+ SUM ( new SumComparator() );
+
+ private Comparator<Ranking> comparator;
+
+ RankingComparators(Comparator<Ranking> comparator) {
+ this.comparator = comparator;
+ }
+
+ public Comparator<Ranking> comparator() {
+ return comparator;
+ }
+
+ static class PositionComparator implements Comparator<Ranking> {
+
+ @Override
+ public int compare(Ranking ranking1, Ranking ranking2) {
+ return ranking1.position() - ranking2.position();
+ }
+
+ }
+
+ static class SumComparator implements Comparator<Ranking> {
+
+ @Override
+ public int compare(Ranking ranking1, Ranking ranking2) {
+ return ranking1.sum() < ranking2.sum()
+ ? 1 : ranking1.sum() > ranking2.sum()? -1 : 0;
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.gson;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.util.Date;
+import java.util.Locale;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.TypeAdapter;
+import com.google.gson.TypeAdapterFactory;
+import com.google.gson.internal.bind.util.ISO8601Utils;
+import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * GSON Adapter for Date including a check for an empty string.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class EmptyDateTypeAdapter extends TypeAdapter<Date> {
+
+ public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
+ return typeToken.getRawType() == Date.class
+ ? (TypeAdapter<T>) new EmptyDateTypeAdapter()
+ : null;
+ }
+ };
+
+ private final DateFormat enUsFormat =
+ DateFormat.getDateTimeInstance(
+ DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US
+ );
+ private final DateFormat localFormat =
+ DateFormat.getDateTimeInstance(
+ DateFormat.DEFAULT, DateFormat.DEFAULT
+ );
+
+ @Override
+ public Date read(JsonReader in) throws IOException {
+ if (in.peek() == JsonToken.NULL) {
+ in.nextNull();
+ return null;
+ }
+ return deserializeToDate(in.nextString());
+ }
+
+ private synchronized Date deserializeToDate(String json) {
+ if (json.isEmpty())
+ return null;
+ try {
+ return localFormat.parse(json);
+ } catch (ParseException ignored) {
+ }
+ try {
+ return enUsFormat.parse(json);
+ } catch (ParseException ignored) {
+ }
+ try {
+ return ISO8601Utils.parse(json, new ParsePosition(0));
+ } catch (ParseException ignored) {
+ }
+ try {
+ return new Date(Long.parseLong(json));
+ } catch (Exception e) {
+ throw new JsonSyntaxException(json, e);
+ }
+ }
+
+ @Override
+ public synchronized void write(JsonWriter out, Date value) throws IOException {
+ if (value == null) {
+ out.nullValue();
+ } else {
+ String dateFormatAsString = enUsFormat.format(value);
+ out.value(dateFormatAsString);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.json;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.hedgecode.snooker.api.CollectionEntity;
+import org.hedgecode.snooker.api.IdEntity;
+
+/**
+ * Abstract Collection Entity to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public abstract class JsonCollectionEntity<E extends IdEntity>
+ implements CollectionEntity<E>, JsonSerializable
+{
+ private final Map<Integer, E> entities = new LinkedHashMap<>();
+
+ protected JsonCollectionEntity(E[] entities) {
+ for (E entity : entities) {
+ if (entity != null)
+ this.entities.put(entity.getId(), entity);
+ }
+ }
+
+ protected JsonCollectionEntity(List<E> entities) {
+ for (E entity : entities) {
+ this.entities.put(entity.getId(), entity);
+ }
+ }
+
+ @Override
+ public int size() {
+ return entities.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return entities.isEmpty();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return entities.values().iterator();
+ }
+
+ @Override
+ public E byId(int id) {
+ return entities.get(id);
+ }
+
+ protected void sort(Comparator<E> comparator) {
+ List<E> entityList = new LinkedList<>(entities.values());
+ Collections.sort(
+ entityList, comparator
+ );
+ entities.clear();
+ for (E entity : entityList) {
+ entities.put(entity.getId(), entity);
+ }
+ }
+
+ @Override
+ public void sortById() {
+ sort(
+ (entity1, entity2) -> entity1.getId() - entity2.getId()
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Event;
+import org.hedgecode.snooker.api.Events;
+import org.hedgecode.snooker.api.Season;
+import org.hedgecode.snooker.compare.EventComparators;
+
+/**
+ * Events Entity (set of {@link Event}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonEvents extends JsonCollectionEntity<Event> implements Events {
+
+ protected JsonEvents(Event[] entities) {
+ super(entities);
+ }
+
+ protected JsonEvents(List<Event> entities) {
+ super(entities);
+ }
+
+ @Override
+ public Events bySeason(Season season) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.season().equals(season))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events byType(String type) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.type().equals(type))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events byCity(String city) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.city().equals(city))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events byCountry(String country) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.country().equals(country))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events bySex(String sex) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.sex().equals(sex))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events byStage(String stage) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.stage().equals(stage))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events byValueType(String valueType) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.valueType().equals(valueType))
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events bySnookerId(int worldSnookerId) {
+ List<Event> events = new ArrayList<>();
+ for (Event event : this)
+ if (event.worldSnookerId() == worldSnookerId)
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events ended() {
+ List<Event> events = new ArrayList<>();
+ long currentTime = System.currentTimeMillis();
+ for (Event event : this)
+ if (event.endDate().getTime() < currentTime)
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events current() {
+ List<Event> events = new ArrayList<>();
+ long currentTime = System.currentTimeMillis();
+ for (Event event : this)
+ if (event.startDate().getTime() < currentTime
+ && event.endDate().getTime() > currentTime)
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public Events upcoming() {
+ List<Event> events = new ArrayList<>();
+ long currentTime = System.currentTimeMillis();
+ for (Event event : this)
+ if (event.startDate().getTime() > currentTime)
+ events.add(event);
+ return events.isEmpty() ? null : new JsonEvents(events);
+ }
+
+ @Override
+ public void sortByDate() {
+ sort(
+ EventComparators.DATE.comparator()
+ );
+ }
+
+ @Override
+ public void sortBySnookerId() {
+ sort(
+ EventComparators.SNOOKER_ID.comparator()
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Match;
+import org.hedgecode.snooker.api.Matches;
+import org.hedgecode.snooker.compare.MatchComparators;
+
+/**
+ * Matches Entity (set of {@link Match}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonMatches extends JsonCollectionEntity<Match> implements Matches {
+
+ protected JsonMatches(Match[] entities) {
+ super(entities);
+ }
+
+ protected JsonMatches(List<Match> entities) {
+ super(entities);
+ }
+
+ @Override
+ public Matches byEvent(int eventId) {
+ List<Match> matches = new ArrayList<>();
+ for (Match match : this)
+ if (match.eventId() == eventId)
+ matches.add(match);
+ return matches.isEmpty() ? null : new JsonMatches(matches);
+ }
+
+ @Override
+ public Matches byRound(int eventId, int round) {
+ List<Match> matches = new ArrayList<>();
+ for (Match match : this)
+ if (match.eventId() == eventId && match.round() == round)
+ matches.add(match);
+ return matches.isEmpty() ? null : new JsonMatches(matches);
+ }
+
+ @Override
+ public Matches byPlayer(int playerId) {
+ List<Match> matches = new ArrayList<>();
+ for (Match match : this)
+ if (match.player1Id() == playerId || match.player2Id() == playerId)
+ matches.add(match);
+ return matches.isEmpty() ? null : new JsonMatches(matches);
+ }
+
+ @Override
+ public Matches ended() {
+ List<Match> matches = new ArrayList<>();
+ for (Match match : this)
+ if (match.endDate() != null)
+ matches.add(match);
+ return matches.isEmpty() ? null : new JsonMatches(matches);
+ }
+
+ @Override
+ public Matches current() {
+ List<Match> matches = new ArrayList<>();
+ for (Match match : this)
+ if (match.startDate() != null && match.endDate() == null)
+ matches.add(match);
+ return matches.isEmpty() ? null : new JsonMatches(matches);
+ }
+
+ @Override
+ public Matches upcoming() {
+ List<Match> matches = new ArrayList<>();
+ for (Match match : this)
+ if (match.startDate() == null)
+ matches.add(match);
+ return matches.isEmpty() ? null : new JsonMatches(matches);
+ }
+
+ @Override
+ public void sortByNumber() {
+ sort(
+ MatchComparators.ROUND_NUMBER.comparator()
+ );
+ }
+
+ @Override
+ public void sortByEvent() {
+ sort(
+ MatchComparators.EVENT.comparator()
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.json;
+
+import org.hedgecode.snooker.api.OngoingMatch;
+import org.hedgecode.snooker.api.OngoingMatches;
+
+/**
+ * Ongoing Matches Entity (set of {@link OngoingMatches}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonOngoingMatches
+ extends JsonCollectionEntity<OngoingMatch> implements OngoingMatches
+{
+ protected JsonOngoingMatches(OngoingMatch[] entities) {
+ super(entities);
+ }
+
+ @Override
+ public OngoingMatch byNumber(int number) {
+ for (OngoingMatch ongoingMatch : this)
+ if (ongoingMatch.number() == number)
+ return ongoingMatch;
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.api.Players;
+import org.hedgecode.snooker.compare.PlayerComparators;
+
+/**
+ * Players Entity (set of {@link Player}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonPlayers extends JsonCollectionEntity<Player> implements Players {
+
+ protected JsonPlayers(Player[] entities) {
+ super(entities);
+ }
+
+ protected JsonPlayers(List<Player> entities) {
+ super(entities);
+ }
+
+ @Override
+ public Players byType(int type) {
+ List<Player> players = new ArrayList<>();
+ for (Player player : this)
+ if (player.type() == type)
+ players.add(player);
+ return players.isEmpty() ? null : new JsonPlayers(players);
+ }
+
+ @Override
+ public Players byName(String name) {
+ List<Player> players = new ArrayList<>();
+ for (Player player : this)
+ if (player.shortName().contains(name))
+ players.add(player);
+ return players.isEmpty() ? null : new JsonPlayers(players);
+ }
+
+ @Override
+ public Players byNationality(String nationality) {
+ List<Player> players = new ArrayList<>();
+ for (Player player : this)
+ if (player.nationality().equals(nationality))
+ players.add(player);
+ return players.isEmpty() ? null : new JsonPlayers(players);
+ }
+
+ @Override
+ public Players bySex(String sex) {
+ List<Player> players = new ArrayList<>();
+ for (Player player : this)
+ if (player.nationality().equals(sex))
+ players.add(player);
+ return players.isEmpty() ? null : new JsonPlayers(players);
+ }
+
+ @Override
+ public void sortByName() {
+ sort(
+ PlayerComparators.NAME.comparator()
+ );
+ }
+
+ @Override
+ public void sortByAge() {
+ sort(
+ PlayerComparators.AGE.comparator()
+ );
+ }
+
+ @Override
+ public void sortByAgeDesc() {
+ sort(
+ PlayerComparators.AGE.comparator().reversed()
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017. Developed by Hedgecode.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.hedgecode.snooker.json;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgecode.snooker.api.Ranking;
+import org.hedgecode.snooker.api.Rankings;
+import org.hedgecode.snooker.compare.RankingComparators;
+
+/**
+ * Rankings Entity (set of {@link Ranking}) to JSON deserialize.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public class JsonRankings extends JsonCollectionEntity<Ranking> implements Rankings {
+
+ protected JsonRankings(Ranking[] entities) {
+ super(entities);
+ }
+
+ protected JsonRankings(List<Ranking> entities) {
+ super(entities);
+ }
+
+ @Override
+ public Ranking byPlayer(int playerId) {
+ for (Ranking ranking : this)
+ if (ranking.playerId() == playerId)
+ return ranking;
+ return null;
+ }
+
+ @Override
+ public Rankings bySum(long minSum, long maxSum) {
+ List<Ranking> rankings = new ArrayList<>();
+ for (Ranking ranking : this)
+ if (ranking.sum() >= minSum && ranking.sum() <= maxSum)
+ rankings.add(ranking);
+ return rankings.isEmpty() ? null : new JsonRankings(rankings);
+ }
+
+ @Override
+ public void sortByPosition() {
+ sort(
+ RankingComparators.POSITION.comparator()
+ );
+ }
+
+ @Override
+ public void sortBySum() {
+ sort(
+ RankingComparators.SUM.comparator()
+ );
+ }
+}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+/*
+ * 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"
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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())
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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)
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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());
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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());
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
+ );
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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());
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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());
+ }
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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)
+ );
+ }
+ }
+
+}
--- /dev/null
+[{"ID": 531,"Name": "Masters","StartDate": "2017-01-15","EndDate": "2017-01-22","Sponsor": "Dafabet","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Alexandra Palace","City": "London","Country": "England","Discipline": "snooker","Main": 531,"Sex": "Both","AgeGroup": "O","Url": "","Related": "masters","Stage": "F","ValueType": "Masters","ShortName": "","WorldSnookerId": 13913,"RankingType": "","EventPredictionID": 2630,"Team": false,"Format": 1,"Twitter": "","HashTag": "DafabetMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 8,"NumActive": 1,"NumResults": 6,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.bbc.co.uk\u002Fiplayer\u0022>BBC<\u002Fa>, <a href=\u0022http:\u002F\u002Feurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 5,"PreviousEdition": 417}]
\ No newline at end of file
--- /dev/null
+[{"ID": 528,"Name": "Indian Open Qualifiers","StartDate": "2016-05-28","EndDate": "2016-05-30","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 514,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "IO","ShortName": "","WorldSnookerId": 13898,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 510,"Name": "World Open Qualifiers","StartDate": "2016-05-31","EndDate": "2016-06-02","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 537,"Sex": "Both","AgeGroup": "O","Url": "","Related": "cc","Stage": "Q","ValueType": "CC","ShortName": "","WorldSnookerId": 13900,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 513,"Name": "Riga Masters Qualifiers","StartDate": "2016-06-03","EndDate": "2016-06-04","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 515,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "Q","ValueType": "","ShortName": "","WorldSnookerId": 13901,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 515,"Name": "Riga Masters","StartDate": "2016-06-22","EndDate": "2016-06-24","Sponsor": "Kaspersky","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Arena Riga","City": "Riga","Country": "Latvia","Discipline": "snooker","Main": 515,"Sex": "Both","AgeGroup": "O","Url": "https:\u002F\u002Fwww.facebook.com\u002FTheRigaOpen","Related": "ptc","Stage": "F","ValueType": "RM","ShortName": "","WorldSnookerId": 13902,"RankingType": "WR","EventPredictionID": 2601,"Team": false,"Format": 1,"Twitter": "","HashTag": "RigaOpen","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 63,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and\u002For selected betting sites","DefendingChampion": 16,"PreviousEdition": 397},{"ID": 514,"Name": "Indian Open","StartDate": "2016-07-05","EndDate": "2016-07-09","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "HICC Novotel Hotel","City": "Hyderabad","Country": "India","Discipline": "snooker","Main": 514,"Sex": "Both","AgeGroup": "","Url": "","Related": "","Stage": "F","ValueType": "IO","ShortName": "","WorldSnookerId": 13898,"RankingType": "WR","EventPredictionID": 2602,"Team": false,"Format": 1,"Twitter": "","HashTag": "IndianOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 134,"NumUpcoming": 0,"NumActive": 0,"NumResults": 69,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 171,"PreviousEdition": 349},{"ID": 537,"Name": "World Open","StartDate": "2016-07-25","EndDate": "2016-07-31","Sponsor": "Hanteng Autos","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Yushan Number One Middle School ","City": "Yushan","Country": "China","Discipline": "snooker","Main": 537,"Sex": "Both","AgeGroup": "O","Url": "","Related": "hwo","Stage": "F","ValueType": "HWO","ShortName": "","WorldSnookerId": 13900,"RankingType": "WR","EventPredictionID": 2603,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 132,"NumUpcoming": 0,"NumActive": 0,"NumResults": 67,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 97,"PreviousEdition": 285},{"ID": 518,"Name": "Paul Hunter Classic ","StartDate": "2016-08-24","EndDate": "2016-08-28","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Stadthalle","City": "FГјrth","Country": "Germany","Discipline": "snooker","Main": 518,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "F","ValueType": "PHC","ShortName": "","WorldSnookerId": 13904,"RankingType": "WR","EventPredictionID": 2604,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 242,"NumUpcoming": 0,"NumActive": 0,"NumResults": 241,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 158,"PreviousEdition": 399},{"ID": 572,"Name": "Paul Hunter Ladies Classic, Group A","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, A","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 573,"Name": "Paul Hunter Ladies Classic, Group B","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, B","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 577,"Name": "Paul Hunter Ladies Classic, Group F","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, F","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 578,"Name": "Paul Hunter Ladies Classic, Group G","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, G","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 579,"Name": "Paul Hunter Ladies Classic, Group H","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, H","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 575,"Name": "Paul Hunter Ladies Classic, Group D","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, D","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 576,"Name": "Paul Hunter Ladies Classic, Group E","StartDate": "2016-08-25","EndDate": "2016-08-25","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, E","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 574,"Name": "Paul Hunter Ladies Classic, Group C","StartDate": "2016-08-25","EndDate": "2016-08-26","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "","Related": "phl","Stage": "Q","ValueType": "PHLC","ShortName": "Paul Hunter Ladies Classic, C","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 570,"Name": "Paul Hunter Ladies Classic","StartDate": "2016-08-25","EndDate": "2016-08-28","Sponsor": "","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Ballroom","City": "NГјrnberg","Country": "Germany","Discipline": "snooker","Main": 570,"Sex": "Women","AgeGroup": "O","Url": "http:\u002F\u002Fwww.mysnookerstats.com\u002Ftournament\u002Ftrn468\u002F","Related": "phl","Stage": "F","ValueType": "PHLC","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "PHLC","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 31,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 519,"Name": "Shanghai Masters Qualifiers","StartDate": "2016-08-30","EndDate": "2016-09-02","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Barnsley Metrodome","City": "Barnsley","Country": "England","Discipline": "snooker","Main": 516,"Sex": "Both","AgeGroup": "O","Url": "","Related": "shanghai","Stage": "Q","ValueType": "SM","ShortName": "","WorldSnookerId": 13905,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerShanghaiMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 96,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 561,"Name": "6 Red World Championship, Group C","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, C","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 559,"Name": "6 Red World Championship, Group A","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, A","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 560,"Name": "6 Red World Championship Group B","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "6RED","ShortName": "6 Red, B","WorldSnookerId": 0,"RankingType": "Unknown","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 562,"Name": "6 Red World Championship, Group D","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, D","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 564,"Name": "6 Red World Championship, Group E","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, E","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 565,"Name": "6 Red World Championship, Group F","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, F","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 566,"Name": "6 Red World Championship, Group G","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, G","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 567,"Name": "6 Red World Championship, Group H","StartDate": "2016-09-05","EndDate": "2016-09-07","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Unknown","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "","ShortName": "6 Red, H","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 520,"Name": "6 Red World Championship","StartDate": "2016-09-05","EndDate": "2016-09-10","Sponsor": "SangSom","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Fashion Island","City": "Bangkok","Country": "Thailand","Discipline": "six-red snooker","Main": 520,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.thailandsnooker.org\u002Fdata\u002Fschedules\u002Ffiles\u002F1473417993_51.pdf","Related": "6red","Stage": "F","ValueType": "6RED","ShortName": "","WorldSnookerId": 0,"RankingType": "Unknown","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SixRedWorldChampionship","ConversionRate": 0.018,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 48,"NumUpcoming": 0,"NumActive": 0,"NumResults": 31,"Note": "","CommonNote": " Watch on selected betting sites","DefendingChampion": 217,"PreviousEdition": 402},{"ID": 516,"Name": "Shanghai Masters","StartDate": "2016-09-19","EndDate": "2016-09-25","Sponsor": "Bank of Communications OTO","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Shanghai Grand Stage","City": "Shanghai","Country": "China","Discipline": "snooker","Main": 516,"Sex": "Both","AgeGroup": "O","Url": "","Related": "shanghai","Stage": "F","ValueType": "SM","ShortName": "","WorldSnookerId": 13906,"RankingType": "WR","EventPredictionID": 2605,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerShanghaiMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 136,"NumUpcoming": 0,"NumActive": 0,"NumResults": 39,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 39,"PreviousEdition": 403},{"ID": 558,"Name": "European Masters Qualifiers","StartDate": "2016-09-26","EndDate": "2016-09-28","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 511,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "EM","ShortName": "","WorldSnookerId": 13925,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 96,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 512,"Name": "International Championship Qualifiers","StartDate": "2016-09-29","EndDate": "2016-10-01","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 517,"Sex": "Both","AgeGroup": "O","Url": "","Related": "international","Stage": "Q","ValueType": "IC","ShortName": "","WorldSnookerId": 13920,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "InternationalChampionship","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 64,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 511,"Name": "European Masters","StartDate": "2016-10-03","EndDate": "2016-10-09","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Circul Globus","City": "Bucharest","Country": "Romania","Discipline": "snooker","Main": 511,"Sex": "Both","AgeGroup": "O","Url": "","Related": "European","Stage": "F","ValueType": "EM","ShortName": "","WorldSnookerId": 13925,"RankingType": "WR","EventPredictionID": 2606,"Team": false,"Format": 1,"Twitter": "","HashTag": "EuropeanMasters","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 31,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 585,"Name": "UK Ladies Championship, Group E","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, E","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 586,"Name": "UK Ladies Championship, Group F","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, F","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 587,"Name": "UK Ladies Championship, Group G","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, G","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 588,"Name": "UK Ladies Championship, Group H","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, H","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 581,"Name": "UK Ladies Championship, Group A","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, A","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 582,"Name": "UK Ladies Championship, Group B","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, B","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 583,"Name": "UK Ladies Championship, Group C","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, C","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 584,"Name": "UK Ladies Championship, Group D","StartDate": "2016-10-08","EndDate": "2016-10-08","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "UKL","ShortName": "UK Ladies Championship, D","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 580,"Name": "UK Ladies Championship","StartDate": "2016-10-08","EndDate": "2016-10-09","Sponsor": "LITEtask","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Northern Snooker Centre","City": "Leeds","Country": "England","Discipline": "snooker","Main": 580,"Sex": "Women","AgeGroup": "O","Url": "http:\u002F\u002Fwww.mysnookerstats.com\u002Ftournament\u002Ftrn481\u002F","Related": "","Stage": "F","ValueType": "UKL","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "UKL","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 26,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "Watch on <a href=\u0022https:\u002F\u002Fwww.youtube.com\u002Fc\u002FMysnookerstats\u002Flive\u0022>YouTube<\u002Fa>","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 522,"Name": "English Open","StartDate": "2016-10-10","EndDate": "2016-10-16","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Event City","City": "Manchester","Country": "England","Discipline": "snooker","Main": 522,"Sex": "Both","AgeGroup": "O","Url": "","Related": "Home Nations Series","Stage": "F","ValueType": "EO","ShortName": "","WorldSnookerId": 13910,"RankingType": "WR","EventPredictionID": 2607,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>, <a href=\u0022http:\u002F\u002Fquesttv.co.uk\u002F\u0022>Quest<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 517,"Name": "International Championship","StartDate": "2016-10-23","EndDate": "2016-10-30","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Baihu Media Broadcasting Centre","City": "Daqing","Country": "China","Discipline": "snooker","Main": 517,"Sex": "Both","AgeGroup": "O","Url": "","Related": "international","Stage": "F","ValueType": "IC","ShortName": "","WorldSnookerId": 13920,"RankingType": "WR","EventPredictionID": 2608,"Team": false,"Format": 1,"Twitter": "","HashTag": "InternationalChampionship","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 132,"NumUpcoming": 0,"NumActive": 0,"NumResults": 67,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 237,"PreviousEdition": 407},{"ID": 568,"Name": "China Championship","StartDate": "2016-11-01","EndDate": "2016-11-05","Sponsor": "Evergrande","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Guangzhou Sports Venue (No.2)","City": "Guangzhou","Country": "China","Discipline": "snooker","Main": 568,"Sex": "Both","AgeGroup": "O","Url": "","Related": "cc","Stage": "F","ValueType": "CC","ShortName": "","WorldSnookerId": 13930,"RankingType": "","EventPredictionID": 2640,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 525,"Name": "Champion of Champions","StartDate": "2016-11-07","EndDate": "2016-11-12","Sponsor": "Dafabet","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 525,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championofchampionssnooker.co.uk\u002F","Related": "cc","Stage": "F","ValueType": "COC","ShortName": "","WorldSnookerId": 13931,"RankingType": "","EventPredictionID": 2620,"Team": false,"Format": 1,"Twitter": "","HashTag": "ChampionOfChampions","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.itv.com\u002Fhub\u002Fitv4\u0022>ITV 4<\u002Fa> and selected betting sites ","DefendingChampion": 154,"PreviousEdition": 408},{"ID": 523,"Name": "Northern Ireland Open","StartDate": "2016-11-14","EndDate": "2016-11-20","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Titanic Belfast ","City": "Belfast","Country": "Ireland","Discipline": "snooker","Main": 523,"Sex": "Both","AgeGroup": "O","Url": "","Related": "Home Nations Series","Stage": "F","ValueType": "NIO","ShortName": "","WorldSnookerId": 13911,"RankingType": "WR","EventPredictionID": 2609,"Team": false,"Format": 1,"Twitter": "","HashTag": "NorthernIrelandOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>, <a href=\u0022http:\u002F\u002Fquesttv.co.uk\u002F\u0022>Quest<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 526,"Name": "UK Championship","StartDate": "2016-11-22","EndDate": "2016-12-04","Sponsor": "Betway ","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Barbican Centre","City": "York","Country": "England","Discipline": "snooker","Main": 526,"Sex": "Both","AgeGroup": "O","Url": "","Related": "uk","Stage": "F","ValueType": "UK","ShortName": "","WorldSnookerId": 13914,"RankingType": "WR","EventPredictionID": 2610,"Team": false,"Format": 1,"Twitter": "","HashTag": "UKChampionship","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.bbc.co.uk\u002Fiplayer\u0022>BBC<\u002Fa>, <a href=\u0022http:\u002F\u002Feurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 154,"PreviousEdition": 410},{"ID": 527,"Name": "German Masters Qualifiers","StartDate": "2016-12-06","EndDate": "2016-12-09","Sponsor": "F66.com","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Barnsley Metrodome","City": "Barnsley","Country": "England","Discipline": "snooker","Main": 532,"Sex": "Both","AgeGroup": "O","Url": "","Related": "german","Stage": "Q","ValueType": "GM","ShortName": "","WorldSnookerId": 13915,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 96,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 524,"Name": "Scottish Open","StartDate": "2016-12-12","EndDate": "2016-12-18","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Emirates Arena","City": "Glasgow","Country": "Scotland","Discipline": "snooker","Main": 524,"Sex": "Both","AgeGroup": "O","Url": "","Related": "scottish","Stage": "F","ValueType": "SO","ShortName": "","WorldSnookerId": 13912,"RankingType": "WR","EventPredictionID": 2611,"Team": false,"Format": 1,"Twitter": "","HashTag": "ScottishOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 127,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport<\u002Fa>, <a href=\u0022http:\u002F\u002Fquesttv.co.uk\u002F\u0022>Quest<\u002Fa> and selected betting sites","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 539,"Name": "Championship League - Group 1","StartDate": "2017-01-02","EndDate": "2017-01-03","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 1,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championshipleaguesnooker.co.uk\u002F","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13933,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 430},{"ID": 540,"Name": "Championship League - Group 2","StartDate": "2017-01-04","EndDate": "2017-01-05","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 2,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championshipleaguesnooker.co.uk\u002F","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13934,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "Players placed 2-5 gets a new chance in Group Three","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 431},{"ID": 542,"Name": "Championship League - Group 3","StartDate": "2017-01-09","EndDate": "2017-01-10","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 3,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13935,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 434},{"ID": 543,"Name": "Championship League - Group 4","StartDate": "2017-01-11","EndDate": "2017-01-12","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 4,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13936,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 24,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 435},{"ID": 592,"Name": "Women's Masters, Group A","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 1,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 593,"Name": "Women's Masters, Group B","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 2,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 6,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 594,"Name": "Women's Masters, Group C","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 3,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 595,"Name": "Women's Masters, Group D","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 4,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 596,"Name": "Women's Masters, Group E","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 5,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 597,"Name": "Women's Masters, Group F","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 6,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 598,"Name": "Women's Masters, Group G","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 7,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 599,"Name": "Women's Masters, Group H","StartDate": "2017-01-14","EndDate": "2017-01-14","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 8,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "","Url": "","Related": "","Stage": "Q","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 2,"Twitter": "wlbsa","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 3,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 589,"Name": "Women's Masters","StartDate": "2017-01-14","EndDate": "2017-01-15","Sponsor": "Eden","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Cueball Derby","City": "Derby","Country": "England","Discipline": "snooker","Main": 589,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "WM","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "WomensMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 26,"NumUpcoming": 0,"NumActive": 0,"NumResults": 15,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 531,"Name": "Masters","StartDate": "2017-01-15","EndDate": "2017-01-22","Sponsor": "Dafabet","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Alexandra Palace","City": "London","Country": "England","Discipline": "snooker","Main": 531,"Sex": "Both","AgeGroup": "O","Url": "","Related": "masters","Stage": "F","ValueType": "Masters","ShortName": "","WorldSnookerId": 13913,"RankingType": "","EventPredictionID": 2630,"Team": false,"Format": 1,"Twitter": "","HashTag": "DafabetMasters","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 16,"NumUpcoming": 8,"NumActive": 1,"NumResults": 6,"Note": "","CommonNote": "<a href=\u0022http:\u002F\u002Fwww.bbc.co.uk\u002Fiplayer\u0022>BBC<\u002Fa>, <a href=\u0022http:\u002F\u002Feurosportplayer.com\u002F\u0022>Eurosport<\u002Fa> and selected betting sites","DefendingChampion": 5,"PreviousEdition": 417},{"ID": 548,"Name": "China Open Qualifiers","StartDate": "2017-01-24","EndDate": "2017-01-27","Sponsor": "","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 533,"Sex": "Both","AgeGroup": "O","Url": "","Related": "china","Stage": "Q","ValueType": "CO","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerChinaOpen","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 60,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 532,"Name": "German Masters","StartDate": "2017-02-01","EndDate": "2017-02-05","Sponsor": "F66.com","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Tempodrom","City": "Berlin","Country": "Germany","Discipline": "snooker","Main": 532,"Sex": "Both","AgeGroup": "O","Url": "","Related": "german","Stage": "F","ValueType": "GM","ShortName": "","WorldSnookerId": 13916,"RankingType": "WR","EventPredictionID": 2612,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 31,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "Watch on <a href=\u0022http:\u002F\u002Fwww.eurosportplayer.com\u002F\u0022>Eurosport Player<\u002Fa>","DefendingChampion": 27,"PreviousEdition": 420},{"ID": 556,"Name": "World Grand Prix","StartDate": "2017-02-06","EndDate": "2017-02-12","Sponsor": "Ladbrokes","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Guild Hall","City": "Preston","Country": "England","Discipline": "snooker","Main": 556,"Sex": "Both","AgeGroup": "O","Url": "","Related": "Unknown","Stage": "F","ValueType": "WGP","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "WorldGrandPrix","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 97,"PreviousEdition": 429},{"ID": 534,"Name": "Welsh Open","StartDate": "2017-02-13","EndDate": "2017-02-19","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Motorpoint Arena","City": "Cardiff","Country": "Wales","Discipline": "snooker","Main": 534,"Sex": "Both","AgeGroup": "O","Url": "","Related": "welsh","Stage": "F","ValueType": "WO","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 5,"PreviousEdition": 427},{"ID": 590,"Name": "Connie Gough Memorial Trophy","StartDate": "2017-02-18","EndDate": "2017-02-18","Sponsor": "","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Dunstable Snooker Club","City": "Dunstable","Country": "England","Discipline": "snooker","Main": 590,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "CGMT","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "CGMT","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 544,"Name": "Championship League - Group 5","StartDate": "2017-02-20","EndDate": "2017-02-21","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 5,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13937,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 24,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 436},{"ID": 545,"Name": "Championship League - Group 6","StartDate": "2017-02-22","EndDate": "2017-02-23","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 6,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13938,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "Will be joined by players placed 2-5 in Group Five","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 437},{"ID": 557,"Name": "Snooker Shoot-Out","StartDate": "2017-02-23","EndDate": "2017-02-26","Sponsor": "Coral","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Watford Colosseum","City": "Watford","Country": "England","Discipline": "snooker","Main": 557,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "ShootOut","ShortName": "Shoot-Out","WorldSnookerId": 0,"RankingType": "Unknown","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "SnookerShootOut","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 549,"PreviousEdition": 447},{"ID": 546,"Name": "Championship League - Group 7","StartDate": "2017-02-27","EndDate": "2017-02-28","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 7,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 13939,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "selected betting sites","DefendingChampion": 0,"PreviousEdition": 438},{"ID": 541,"Name": "Championship League - Winners' Group","StartDate": "2017-03-01","EndDate": "2017-03-02","Sponsor": "","Season": 2016,"Type": "Invitational","Num": 0,"Venue": "Ricoh Arena","City": "Coventry","Country": "England","Discipline": "snooker","Main": 541,"Sex": "Both","AgeGroup": "O","Url": "http:\u002F\u002Fwww.championshipleaguesnooker.co.uk\u002F","Related": "","Stage": "Q","ValueType": "CL","ShortName": "","WorldSnookerId": 0,"RankingType": "","EventPredictionID": 0,"Team": false,"Format": 3,"Twitter": "","HashTag": "ChampionshipLeague","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 25,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 12,"PreviousEdition": 431},{"ID": 547,"Name": "Gibraltar Open","StartDate": "2017-03-03","EndDate": "2017-03-05","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Tercentenary Sports Hall","City": "Gibraltar","Country": "Gibraltar","Discipline": "snooker","Main": 547,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "F","ValueType": "EPTC","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 0.75,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 4,"PreviousEdition": 411},{"ID": 555,"Name": "Players Championship","StartDate": "2017-03-06","EndDate": "2017-03-12","Sponsor": "Ladbrokes","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Venue Cymru","City": "Llandudno","Country": "Wales","Discipline": "snooker","Main": 555,"Sex": "Both","AgeGroup": "O","Url": "","Related": "ptc","Stage": "F","ValueType": "PTCF","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "PTCFinals","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 202,"PreviousEdition": 423},{"ID": 591,"Name": "Women's World Snooker Championship","StartDate": "2017-03-13","EndDate": "2017-03-19","Sponsor": "Eden","Season": 2016,"Type": "Ladies Ranking","Num": 0,"Venue": "Lagoon Billard Room, Safra Toa Payoh","City": "Singapore","Country": "Singapore","Discipline": "snooker","Main": 591,"Sex": "Women","AgeGroup": "O","Url": "","Related": "","Stage": "F","ValueType": "WWC","ShortName": "","WorldSnookerId": 0,"RankingType": "WWR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "wlbsa","HashTag": "LadiesWSC","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 0},{"ID": 533,"Name": "China Open","StartDate": "2017-03-27","EndDate": "2017-04-02","Sponsor": "","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Beijing University Students Gymnasium","City": "Beijing","Country": "China","Discipline": "snooker","Main": 533,"Sex": "Both","AgeGroup": "O","Url": "","Related": "china","Stage": "F","ValueType": "CO","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": true,"PhotoURLs": "","NumCompetitors": 128,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 12,"PreviousEdition": 422},{"ID": 535,"Name": "World Championship Qualifiers","StartDate": "2017-04-05","EndDate": "2017-04-12","Sponsor": "Betfred","Season": 2016,"Type": "Qualifying","Num": 0,"Venue": "Ponds Forge International Sports Centre","City": "Sheffield","Country": "England","Discipline": "snooker","Main": 536,"Sex": "Both","AgeGroup": "O","Url": "","Related": "world","Stage": "Q","ValueType": "WC","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 421},{"ID": 536,"Name": "World Championship","StartDate": "2017-04-15","EndDate": "2017-05-01","Sponsor": "Betfred","Season": 2016,"Type": "Ranking","Num": 0,"Venue": "Crucible Theatre","City": "Sheffield","Country": "England","Discipline": "snooker","Main": 536,"Sex": "Both","AgeGroup": "O","Url": "","Related": "world","Stage": "F","ValueType": "WC","ShortName": "","WorldSnookerId": 0,"RankingType": "WR","EventPredictionID": 0,"Team": false,"Format": 1,"Twitter": "","HashTag": "","ConversionRate": 1,"AllRoundsAdded": false,"PhotoURLs": "","NumCompetitors": 0,"NumUpcoming": 0,"NumActive": 0,"NumResults": 0,"Note": "","CommonNote": "","DefendingChampion": 0,"PreviousEdition": 416}]
\ No newline at end of file
--- /dev/null
+[{"ID": 3352358,"EventID": 531,"Round": 7,"Number": 3,"Player1ID": 12,"Score1": 5,"Walkover1": false,"Player2ID": 4,"Score2": 6,"Walkover2": false,"WinnerID": 4,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434075,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=U4Sut-Jtv1M","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T13:04:10Z","StartDate": "2017-01-17T13:04:10Z","EndDate": "2017-01-17T16:13:44Z","ScheduledDate": "2017-01-17T13:00:00Z","FrameScores": "","Sessions": "","Note": "Five centuries and nine half centuries!","ExtendedNote": ""}]
\ No newline at end of file
--- /dev/null
+[{"ID": 3351411,"EventID": 531,"Round": 15,"Number": 1,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:47:58Z","ModDate": "2016-12-04T20:55:14Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-22T13:00:00Z","FrameScores": "","Sessions": "<br \u002F>Second session 8 pm ","Note": "","ExtendedNote": ""},{"ID": 3351409,"EventID": 531,"Round": 14,"Number": 1,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:47:42Z","ModDate": "2016-12-05T01:27:13Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-21T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351410,"EventID": 531,"Round": 14,"Number": 2,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T20:54:39Z","ModDate": "2016-12-05T01:27:13Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-21T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351405,"EventID": 531,"Round": 13,"Number": 1,"Player1ID": 5,"Score1": 0,"Walkover1": false,"Player2ID": 154,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:46:53Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-19T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351406,"EventID": 531,"Round": 13,"Number": 2,"Player1ID": 4,"Score1": 0,"Walkover1": false,"Player2ID": 202,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:46:53Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-19T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351407,"EventID": 531,"Round": 13,"Number": 3,"Player1ID": 168,"Score1": 0,"Walkover1": false,"Player2ID": 224,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T20:52:11Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-20T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3351408,"EventID": 531,"Round": 13,"Number": 4,"Player1ID": 376,"Score1": 0,"Walkover1": false,"Player2ID": 376,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 0,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": false,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T20:52:11Z","ModDate": "2016-12-04T20:52:11Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-20T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352356,"EventID": 531,"Round": 7,"Number": 1,"Player1ID": 5,"Score1": 6,"Walkover1": false,"Player2ID": 200,"Score2": 5,"Walkover2": false,"WinnerID": 5,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434073,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002Fh-V4tlXRcFI","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-15T12:58:50Z","StartDate": "2017-01-15T12:58:50Z","EndDate": "2017-01-15T16:39:44Z","ScheduledDate": "2017-01-15T13:00:00Z","FrameScores": "","Sessions": "","Note": "Liang missed match ball black in frame 10. O'Sullivan made a 121 break in the decider.","ExtendedNote": ""},{"ID": 3352357,"EventID": 531,"Round": 7,"Number": 2,"Player1ID": 154,"Score1": 6,"Walkover1": false,"Player2ID": 158,"Score2": 3,"Walkover2": false,"WinnerID": 154,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434074,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FNEBEOlOYlOE","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T19:03:04Z","StartDate": "2017-01-17T19:03:04Z","EndDate": "2017-01-17T21:50:36Z","ScheduledDate": "2017-01-17T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352358,"EventID": 531,"Round": 7,"Number": 3,"Player1ID": 12,"Score1": 5,"Walkover1": false,"Player2ID": 4,"Score2": 6,"Walkover2": false,"WinnerID": 4,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434075,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=U4Sut-Jtv1M","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T13:04:10Z","StartDate": "2017-01-17T13:04:10Z","EndDate": "2017-01-17T16:13:44Z","ScheduledDate": "2017-01-17T13:00:00Z","FrameScores": "","Sessions": "","Note": "Five centuries and nine half centuries!","ExtendedNote": ""},{"ID": 3352359,"EventID": 531,"Round": 7,"Number": 4,"Player1ID": 237,"Score1": 5,"Walkover1": false,"Player2ID": 202,"Score2": 6,"Walkover2": false,"WinnerID": 202,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434076,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FxCVGf9dhDbs","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-16T13:00:46Z","StartDate": "2017-01-16T13:00:46Z","EndDate": "2017-01-16T16:22:33Z","ScheduledDate": "2017-01-16T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": "Re-rack in frame 2. Re-spotted black in frame 9 (67-67)."},{"ID": 3352360,"EventID": 531,"Round": 7,"Number": 5,"Player1ID": 30,"Score1": 1,"Walkover1": false,"Player2ID": 168,"Score2": 6,"Walkover2": false,"WinnerID": 168,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434077,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FVMakJBk540s","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-16T18:54:22Z","StartDate": "2017-01-16T18:54:22Z","EndDate": "2017-01-16T21:40:51Z","ScheduledDate": "2017-01-16T19:00:00Z","FrameScores": "","Sessions": "","Note": "132 by Bingham is the new highest break in the tournament ","ExtendedNote": "Re-spotted black in frame two."},{"ID": 3352361,"EventID": 531,"Round": 7,"Number": 6,"Player1ID": 224,"Score1": 6,"Walkover1": false,"Player2ID": 39,"Score2": 3,"Walkover2": false,"WinnerID": 224,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434078,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "https:\u002F\u002Fyoutu.be\u002FuwBHxoYEgEc","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-15T19:14:20Z","StartDate": "2017-01-15T19:14:20Z","EndDate": "2017-01-15T22:17:16Z","ScheduledDate": "2017-01-15T19:00:00Z","FrameScores": "","Sessions": "","Note": "Ding missed the yellow on the way to a maximum in the second frame","ExtendedNote": ""},{"ID": 3352362,"EventID": 531,"Round": 7,"Number": 7,"Player1ID": 97,"Score1": 0,"Walkover1": false,"Player2ID": 16,"Score2": 0,"Walkover2": false,"WinnerID": 0,"Unfinished": false,"OnBreak": false,"WorldSnookerID": 434079,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-17T22:48:55Z","StartDate": "","EndDate": "","ScheduledDate": "2017-01-18T19:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352363,"EventID": 531,"Round": 7,"Number": 8,"Player1ID": 17,"Score1": 3,"Walkover1": false,"Player2ID": 1,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 434080,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-18T14:19:13Z","StartDate": "2017-01-18T13:10:00Z","EndDate": "","ScheduledDate": "2017-01-18T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""}]
\ No newline at end of file
--- /dev/null
+[{"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
--- /dev/null
+[{"ID": 3352363,"EventID": 531,"Round": 7,"Number": 8,"Player1ID": 17,"Score1": 3,"Walkover1": false,"Player2ID": 1,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 434080,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:45:51Z","ModDate": "2017-01-18T14:19:13Z","StartDate": "2017-01-18T13:10:00Z","EndDate": "","ScheduledDate": "2017-01-18T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""},{"ID": 3352564,"EventID": 531,"Round": 13,"Number": 1,"Player1ID": 5,"Score1": 1,"Walkover1": false,"Player2ID": 154,"Score2": 1,"Walkover2": false,"WinnerID": 0,"Unfinished": true,"OnBreak": false,"WorldSnookerID": 481773,"LiveUrl": "","DetailsUrl": "","PointsDropped": false,"ShowCommonNote": true,"Estimated": false,"Type": 1,"TableNo": 0,"VideoURL": "","InitDate": "2016-12-04T14:46:53Z","ModDate": "2017-01-19T13:48:02Z","StartDate": "2017-01-19T13:10:06Z","EndDate": "","ScheduledDate": "2017-01-19T13:00:00Z","FrameScores": "","Sessions": "","Note": "","ExtendedNote": ""}]
\ No newline at end of file
--- /dev/null
+[{"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
--- /dev/null
+[{"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
--- /dev/null
+[{"ID": 12202013,"Position": 1,"PlayerID": 17,"Season": 2016,"Sum": 994942,"Type": "MoneyRankings"}]
\ No newline at end of file
--- /dev/null
+[{"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