--- /dev/null
+/*
+ * Copyright (c) 2017-2019. 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.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Date and Time Utils for Matches and Events.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class SnookerDateUtils {
+
+ public static final String DATE_PATTERN = "dd.MM.yyyy";
+ public static final String TIME_PATTERN = "HH:mm";
+ public static final String DATETIME_PATTERN = TIME_PATTERN + " " + DATE_PATTERN;
+
+ private static final TimeZone CTZ = TimeZone.getTimeZone("CET");
+ private static final TimeZone LTZ = TimeZone.getDefault();
+
+ private static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_PATTERN);
+ private static final DateFormat CET_TIME_FORMAT = new SimpleDateFormat(TIME_PATTERN);
+ private static final DateFormat CET_DATETIME_FORMAT = new SimpleDateFormat(DATETIME_PATTERN);
+ private static final DateFormat LOCAL_TIME_FORMAT = new SimpleDateFormat(TIME_PATTERN);
+ private static final DateFormat LOCAL_DATETIME_FORMAT = new SimpleDateFormat(DATETIME_PATTERN);
+
+ static {
+ CET_TIME_FORMAT.setTimeZone(CTZ);
+ CET_DATETIME_FORMAT.setTimeZone(CTZ);
+ LOCAL_TIME_FORMAT.setTimeZone(LTZ);
+ LOCAL_DATETIME_FORMAT.setTimeZone(LTZ);
+ }
+
+ public static String formatDate(Date date) {
+ return DATE_FORMAT.format(date);
+ }
+
+ public static String formatTime(Date date) {
+ return formatTime(date, false);
+ }
+
+ public static String formatTime(Date date, boolean withDate) {
+ return withDate ? CET_DATETIME_FORMAT.format(date) : CET_TIME_FORMAT.format(date);
+ }
+
+ public static String formatLocalTime(Date date) {
+ return formatLocalTime(date, false);
+ }
+
+ public static String formatLocalTime(Date date, boolean withDate) {
+ return withDate ? LOCAL_DATETIME_FORMAT.format(date) : LOCAL_TIME_FORMAT.format(date);
+ }
+
+}
/*
- * Copyright (c) 2017. Developed by Hedgecode.
+ * Copyright (c) 2017-2019. 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.
package org.hedgecode.snooker;
-import java.text.DateFormat;
-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.Match;
+import org.hedgecode.snooker.api.Player;
+import org.hedgecode.snooker.api.Round;
+import org.hedgecode.snooker.api.Rounds;
import org.hedgecode.snooker.api.Season;
+import org.hedgecode.snooker.api.Seeding;
+import org.hedgecode.snooker.api.Seedings;
+import org.hedgecode.snooker.api.SnookerScoreAPI;
/**
* Snooker Score Main Application.
*/
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 final String DATE_FORMAT = "dd.MM.yyyy";
+ private static final String ARG_PREFIX = "^[-/]";
+ private static final String ARG_POSTFIX = "$";
+ private static final String ARG_QUIET_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_QUIET + ARG_POSTFIX;
+ private static final String ARG_SERVER_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_SERVER + ARG_POSTFIX;
+ private static final String ARG_PORT_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_PORT + ARG_POSTFIX;
+ private static final String ARG_HELP_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_HELP + ARG_POSTFIX;
+
+ private static final int INVALID_PORT = -1;
+ private static final int PORT_RANGE_MIN = 0;
+ private static final int PORT_RANGE_MAX = 65535;
+ private static final int PORT_RANGE_SYSTEM = 1024;
+ private static final String PORT_NUMBER_REGEX = "[0-9]+";
private static final int UPCOMING_COUNT = 5;
+ private static final int TOP_SEEDING_COUNT = 10;
+
+ private static final String INDENT = " ";
+ private static final String CURRENT_EVENTS = "Current Snooker Events:";
+ private static final String UPCOMING_EVENTS = "Upcoming Snooker Events:";
+ private static final String EVENT_ROUNDS = "Rounds of";
+ private static final String EVENT_SEEDING = "Seeding of";
public static void main(String[] args) throws APIException
{
- System.out.println(EMPTY);
- System.out.println(DELIMITER);
- for (String line : WELCOME) {
- System.out.println(line);
+ if (isHelpMode(args)) {
+
+ if (!isQuietMode(args)) {
+ printWelcome();
+ }
+ printHelp();
+
+ } else if (!isQuietMode(args)) {
+
+ printWelcome();
+
+ Events events = Snooker.uncachedAPI().getSeasonEvents(
+ Season.CURRENT_SEASON
+ );
+ events.sortByDate();
+
+ printCurrentEvents(events);
+ printUpcomingEvents(events);
+
+ }
+
+ int serverPort = serverMode(args);
+ if (isValidPort(serverPort)) {
+ // todo: server mode
+ }
+ }
+
+ private static boolean isQuietMode(String[] args) {
+ for (String arg : args) {
+ if (arg.matches(ARG_QUIET_REGEX)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isHelpMode(String[] args) {
+ for (String arg : args) {
+ if (arg.matches(ARG_HELP_REGEX)) {
+ return true;
+ }
}
+ return false;
+ }
- Events events = Snooker.uncachedAPI().getSeasonEvents(
- Season.CURRENT_SEASON
+
+ private static int serverMode(String[] args) {
+ boolean isServerMode = false;
+ int serverPort = Integer.parseInt(
+ SnookerScoreProperties.get("snooker.port.number")
);
- events.sortByDate();
+ boolean isPortArg = false;
+ for (String arg : args) {
+ if (isPortArg) {
+ if (arg.matches(PORT_NUMBER_REGEX)) {
+ serverPort = Integer.parseInt(arg);
+ }
+ isPortArg = false;
+ } else if (arg.matches(ARG_PORT_REGEX)) {
+ isPortArg = true;
+ } else if (arg.matches(ARG_SERVER_REGEX)) {
+ isServerMode = true;
+ }
+ }
+ return isServerMode ? serverPort : INVALID_PORT;
+ }
+
+ private static boolean isValidPort(int portNumber) {
+ if (portNumber >= PORT_RANGE_MIN && portNumber <= PORT_RANGE_MAX) {
+ if (portNumber < PORT_RANGE_SYSTEM) {
+ SnookerScoreConsole.console(
+ String.format(
+ "%s: %s %d",
+ "Warning",
+ "Don't recommend using port numbers less than",
+ PORT_RANGE_SYSTEM
+ )
+ );
+ }
+ return true;
+ }
+ return false;
+ }
+ private static void printWelcome() {
+ SnookerScoreConsole.init();
+ SnookerScoreConsole.welcome();
+ SnookerScoreConsole.empty();
+ SnookerScoreConsole.delimiter();
+ }
+
+ private static void printHelp() {
+ SnookerScoreConsole.empty();
+ SnookerScoreConsole.help();
+ SnookerScoreConsole.empty();
+ }
+
+ private static void printCurrentEvents(Events events) {
Events currentEvents = events.current();
if (!currentEvents.isEmpty()) {
- System.out.println(DELIMITER);
- System.out.println(CURRENT_EVENTS);
+ SnookerScoreConsole.console(
+ String.format("%s%s", INDENT, CURRENT_EVENTS)
+ );
+ for (Event currentEvent : currentEvents) {
+ printEvent(currentEvent, INDENT.concat(INDENT));
+ }
+ SnookerScoreConsole.delimiter();
}
- for (Event currentEvent : currentEvents) {
- printEvent(currentEvent);
+ }
+
+ private static void printUpcomingEvents(Events events) {
+ Events upcomingEvents = events.upcoming();
+ if (!upcomingEvents.isEmpty()) {
+ SnookerScoreConsole.console(
+ String.format("%s%s", INDENT, UPCOMING_EVENTS)
+ );
+ int count = 0;
+ for (Event upcomingEvent : upcomingEvents) {
+ printEvent(upcomingEvent, INDENT.concat(INDENT));
+ ++count;
+ if (count >= UPCOMING_COUNT) break;
+ }
+ SnookerScoreConsole.delimiter();
}
+ }
- System.out.println(DELIMITER);
- System.out.println(UPCOMING_EVENTS);
+ private static void printEvent(Event event, String indent) {
+ SnookerScoreConsole.console(
+ String.format(
+ "%s%s [%s - %s] (%s, %s)",
+ indent,
+ event.name(),
+ SnookerDateUtils.formatDate(event.startDate()),
+ SnookerDateUtils.formatDate(event.endDate()),
+ event.country(),
+ event.city()
+ )
+ );
+ }
- int count = 0;
- Events upcomingEvents = events.upcoming();
- for (Event upcomingEvent : upcomingEvents) {
- printEvent(upcomingEvent);
- ++count;
- if (count >= UPCOMING_COUNT) break;
+ private static void printPlayer(Player player) {
+ SnookerScoreConsole.console(
+ String.format(
+ "%s%s %s [%s] (%s)",
+ INDENT,
+ player.surnameFirst() ? player.lastName() : player.firstName(),
+ player.surnameFirst() ? player.firstName() : player.lastName(),
+ SnookerDateUtils.formatDate(player.born()),
+ player.nationality()
+ )
+ );
+ }
+
+ private static void printMatch(Match match) throws APIException {
+ SnookerScoreAPI api = Snooker.uncachedAPI();
+ Player player1 = api.getPlayer(match.player1Id());
+ Player player2 = api.getPlayer(match.player2Id());
+ SnookerScoreConsole.console(
+ String.format(
+ "%s[%s %s - %s] %s %s %s-%s %s %s",
+ INDENT,
+ SnookerDateUtils.formatDate(match.startDate()),
+ SnookerDateUtils.formatTime(match.startDate()),
+ SnookerDateUtils.formatTime(match.endDate()),
+ player1.surnameFirst() ? player1.lastName() : player1.firstName(),
+ player1.surnameFirst() ? player1.firstName() : player1.lastName(),
+ match.score1(),
+ match.score2(),
+ player2.surnameFirst() ? player2.lastName() : player2.firstName(),
+ player2.surnameFirst() ? player2.firstName() : player2.lastName()
+ )
+ );
+ }
+
+ private static void printRounds(Rounds rounds, Event event) throws APIException {
+ if (!rounds.isEmpty()) {
+ rounds.sortByRound();
+ if (event != null) {
+ SnookerScoreConsole.console(
+ String.format("%s%s %s:", INDENT, EVENT_ROUNDS, event.name())
+ );
+ }
+ for (Round round : rounds) {
+ printRound(round, event, INDENT.concat(INDENT));
+ }
+ SnookerScoreConsole.delimiter();
+ }
+ }
+
+ private static void printRound(Round round, Event event, String indent) throws APIException {
+ if (event == null || event.getId() != round.eventId()) {
+ SnookerScoreAPI api = Snooker.uncachedAPI();
+ Event roundEvent = api.getEvent(round.eventId());
+ SnookerScoreConsole.console(
+ String.format(
+ "%s%s. %s (%s)",
+ indent,
+ round.round(),
+ round.roundName(),
+ roundEvent.name()
+ )
+ );
+ } else {
+ SnookerScoreConsole.console(
+ String.format(
+ "%s%s. %s",
+ indent,
+ round.round(),
+ round.roundName()
+ )
+ );
+ }
+ }
+
+ private static void printSeedings(Seedings seedings, Event event) throws APIException {
+ if (!seedings.isEmpty()) {
+ seedings.sortBySeeding();
+ if (event != null) {
+ SnookerScoreConsole.console(
+ String.format(
+ "%s%s %s (top %d):",
+ INDENT,
+ EVENT_SEEDING,
+ event.name(),
+ TOP_SEEDING_COUNT
+ )
+ );
+ }
+ int count = 0;
+ for (Seeding seeding : seedings) {
+ printSeeding(seeding, INDENT.concat(INDENT));
+ ++count;
+ if (count >= TOP_SEEDING_COUNT) break;
+ }
+ SnookerScoreConsole.delimiter();
}
- System.out.println(DELIMITER);
- System.out.println(EMPTY);
}
- private static void printEvent(Event event) {
- final DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
- System.out.println(
- INDENT + event.name()
- + " [" + dateFormat.format(event.startDate())
- + " - " + dateFormat.format(event.endDate()) + "]"
- + " (" + event.country() + ", " + event.city() + ")"
+ private static void printSeeding(Seeding seeding, String indent) throws APIException {
+ SnookerScoreAPI api = Snooker.uncachedAPI();
+ Player player = api.getPlayer(seeding.playerId());
+ SnookerScoreConsole.console(
+ String.format(
+ "%s%s. %s %s",
+ indent,
+ seeding.seeding(),
+ player.surnameFirst() ? player.lastName() : player.firstName(),
+ player.surnameFirst() ? player.firstName() : player.lastName()
+ )
);
}
--- /dev/null
+/*
+ * Copyright (c) 2017-2019. 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.util.Calendar;
+
+/**
+ * Snooker Score utility class for working with console.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class SnookerScoreConsole {
+
+ private static final String[] ASCII_LOGO = {
+ " _______ _ _ ",
+ " | | _|_ _| |___ ___ ___ ___ _| |___ ",
+ " | | -_| . | . | -_| _| . | . | -_| ",
+ " | |___|___|_ |___|___|___|___|___| ",
+ " |___|___| _ |___| ",
+ " ___ ___ ___ ___| |_ ___ ___ ___ ___ ___ ___ ___ ",
+ " |_ -| | . | . | '_| -_| _| |_ -| _| . | _| -_| ",
+ " |___|_|_|___|___|_,_|___|_| |___|___|___|_| |___| ",
+ " _____ _____ _ ",
+ " | _ | _ |_| ",
+ " | | __| | ",
+ " |__|__|__| |_| "
+ };
+
+ private static final String COPYRIGHT = "Copyright (c) Hedgecode";
+
+ 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. "
+ };
+
+ public static final String ARG_QUIET = "quiet";
+ public static final String ARG_SERVER = "server";
+ public static final String ARG_PORT = "port";
+ public static final String ARG_HELP = "help";
+
+ private SnookerScoreConsole() {
+ }
+
+ public static void console(String message) {
+ System.out.println(
+ message == null ? "" : message
+ );
+ }
+
+ public static void empty() {
+ console(null);
+ }
+
+ public static void delimiter() {
+ console(
+ String.format(
+ "%" + length() + "s",
+ DELIMITER
+ ).replace(" ", DELIMITER)
+ );
+ }
+
+ public static void init() {
+ asciiLogo();
+ empty();
+ copyright();
+ version();
+ empty();
+ }
+
+ public static void welcome() {
+ for (String line : WELCOME) {
+ console(line);
+ }
+ }
+
+ public static void help() {
+ console(
+ String.format(
+ "Usage: java -jar %s-%s.jar -[%s|%s|%s XXXX|%s]",
+ SnookerScoreProperties.get("snooker.name"),
+ SnookerScoreProperties.get("snooker.version"),
+ ARG_QUIET,
+ ARG_SERVER,
+ ARG_PORT,
+ ARG_HELP
+ )
+ );
+ }
+
+ private static void asciiLogo() {
+ for (String line : ASCII_LOGO) {
+ console(line);
+ }
+ }
+
+ private static void copyright() {
+ int inceptionYear = Integer.parseInt(
+ SnookerScoreProperties.get("snooker.inception.year")
+ );
+ int currentYear = Calendar.getInstance().get(Calendar.YEAR);
+ String copyright = currentYear > inceptionYear
+ ? String.format("%s-%s %s", inceptionYear, currentYear, COPYRIGHT)
+ : String.format("%s %s", currentYear, COPYRIGHT);
+ console(
+ alignCenter(copyright)
+ );
+ }
+
+ private static void version() {
+ console(
+ alignCenter(
+ String.format(
+ "v. %s", SnookerScoreProperties.get("snooker.version")
+ )
+ )
+ );
+ }
+
+ private static String alignCenter(String message) {
+ int indent = (length() + message.length()) / 2;
+ return String.format(
+ "%" + indent + "s",
+ message
+ );
+ }
+
+ private static int length() {
+ return ASCII_LOGO[0].length();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017-2019. 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.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Snooker Score properties holder.
+ *
+ * @author Dmitry Samoshin aka gotty
+ */
+public final class SnookerScoreProperties {
+
+ /** Properties file. */
+ private static final String PROPERTIES_FILE = "snooker.properties";
+
+ /** Properties. */
+ private static final Properties PROPERTIES;
+
+ /**
+ * Static properties initialization.
+ */
+ static {
+ PROPERTIES = new Properties();
+ readProperties(PROPERTIES_FILE, PROPERTIES, true);
+ }
+
+ /**
+ * @param propsFile Properties file name.
+ * @param props Properties.
+ * @param throwExc Flag indicating whether to throw an exception or not.
+ */
+ public static void readProperties(String propsFile, Properties props, boolean throwExc) {
+ try (InputStream is = SnookerScoreProperties.class.getClassLoader().getResourceAsStream(propsFile)) {
+ if (is == null) {
+ if (throwExc)
+ throw new RuntimeException("Failed to find properties file: " + propsFile);
+ else
+ return;
+ }
+
+ props.load(is);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to read properties file: " + propsFile, e);
+ }
+ }
+
+ /**
+ * Empty string for not found properties.
+ */
+ private static final String EMPTY = "";
+
+ /**
+ * Gets property value.
+ *
+ * @param key Property key.
+ * @return Property value (possibly empty string, but never {@code null}).
+ */
+ public static String get(String key) {
+ return PROPERTIES.getProperty(key, EMPTY);
+ }
+
+ /**
+ * Private constructor.
+ */
+ private SnookerScoreProperties() {
+ }
+
+}