[LIB-8] Console output, properties, date utils
[snooker-score-api.git] / src / main / java / org / hedgecode / snooker / SnookerScoreApp.java
1 /*
2  * Copyright (c) 2017-2019. Developed by Hedgecode.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.hedgecode.snooker;
18
19 import org.hedgecode.snooker.api.APIException;
20 import org.hedgecode.snooker.api.Event;
21 import org.hedgecode.snooker.api.Events;
22 import org.hedgecode.snooker.api.Match;
23 import org.hedgecode.snooker.api.Player;
24 import org.hedgecode.snooker.api.Round;
25 import org.hedgecode.snooker.api.Rounds;
26 import org.hedgecode.snooker.api.Season;
27 import org.hedgecode.snooker.api.Seeding;
28 import org.hedgecode.snooker.api.Seedings;
29 import org.hedgecode.snooker.api.SnookerScoreAPI;
30
31 /**
32  * Snooker Score Main Application.
33  *
34  * @author Dmitry Samoshin aka gotty
35  */
36 public final class SnookerScoreApp {
37
38     private static final String ARG_PREFIX = "^[-/]";
39     private static final String ARG_POSTFIX = "$";
40     private static final String ARG_QUIET_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_QUIET + ARG_POSTFIX;
41     private static final String ARG_SERVER_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_SERVER + ARG_POSTFIX;
42     private static final String ARG_PORT_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_PORT + ARG_POSTFIX;
43     private static final String ARG_HELP_REGEX = ARG_PREFIX + SnookerScoreConsole.ARG_HELP + ARG_POSTFIX;
44
45     private static final int INVALID_PORT = -1;
46     private static final int PORT_RANGE_MIN = 0;
47     private static final int PORT_RANGE_MAX = 65535;
48     private static final int PORT_RANGE_SYSTEM = 1024;
49     private static final String PORT_NUMBER_REGEX = "[0-9]+";
50
51     private static final int UPCOMING_COUNT = 5;
52     private static final int TOP_SEEDING_COUNT = 10;
53
54     private static final String INDENT = "    ";
55     private static final String CURRENT_EVENTS = "Current Snooker Events:";
56     private static final String UPCOMING_EVENTS = "Upcoming Snooker Events:";
57     private static final String EVENT_ROUNDS = "Rounds of";
58     private static final String EVENT_SEEDING = "Seeding of";
59
60     public static void main(String[] args) throws APIException
61     {
62         if (isHelpMode(args)) {
63
64             if (!isQuietMode(args)) {
65                 printWelcome();
66             }
67             printHelp();
68
69         } else if (!isQuietMode(args)) {
70
71             printWelcome();
72
73             Events events = Snooker.uncachedAPI().getSeasonEvents(
74                     Season.CURRENT_SEASON
75             );
76             events.sortByDate();
77
78             printCurrentEvents(events);
79             printUpcomingEvents(events);
80
81         }
82
83         int serverPort = serverMode(args);
84         if (isValidPort(serverPort)) {
85             // todo: server mode
86         }
87     }
88
89     private static boolean isQuietMode(String[] args) {
90         for (String arg : args) {
91             if (arg.matches(ARG_QUIET_REGEX)) {
92                 return true;
93             }
94         }
95         return false;
96     }
97
98     private static boolean isHelpMode(String[] args) {
99         for (String arg : args) {
100             if (arg.matches(ARG_HELP_REGEX)) {
101                 return true;
102             }
103         }
104         return false;
105     }
106
107
108     private static int serverMode(String[] args) {
109         boolean isServerMode = false;
110         int serverPort = Integer.parseInt(
111                 SnookerScoreProperties.get("snooker.port.number")
112         );
113         boolean isPortArg = false;
114         for (String arg : args) {
115             if (isPortArg) {
116                 if (arg.matches(PORT_NUMBER_REGEX)) {
117                     serverPort = Integer.parseInt(arg);
118                 }
119                 isPortArg = false;
120             } else if (arg.matches(ARG_PORT_REGEX)) {
121                 isPortArg = true;
122             } else if (arg.matches(ARG_SERVER_REGEX)) {
123                 isServerMode = true;
124             }
125         }
126         return isServerMode ? serverPort : INVALID_PORT;
127     }
128
129     private static boolean isValidPort(int portNumber) {
130         if (portNumber >= PORT_RANGE_MIN && portNumber <= PORT_RANGE_MAX) {
131             if (portNumber < PORT_RANGE_SYSTEM) {
132                 SnookerScoreConsole.console(
133                         String.format(
134                                 "%s: %s %d",
135                                 "Warning",
136                                 "Don't recommend using port numbers less than",
137                                 PORT_RANGE_SYSTEM
138                         )
139                 );
140             }
141             return true;
142         }
143         return false;
144     }
145
146     private static void printWelcome() {
147         SnookerScoreConsole.init();
148         SnookerScoreConsole.welcome();
149         SnookerScoreConsole.empty();
150         SnookerScoreConsole.delimiter();
151     }
152
153     private static void printHelp() {
154         SnookerScoreConsole.empty();
155         SnookerScoreConsole.help();
156         SnookerScoreConsole.empty();
157     }
158
159     private static void printCurrentEvents(Events events) {
160         Events currentEvents = events.current();
161         if (!currentEvents.isEmpty()) {
162             SnookerScoreConsole.console(
163                     String.format("%s%s", INDENT, CURRENT_EVENTS)
164             );
165             for (Event currentEvent : currentEvents) {
166                 printEvent(currentEvent, INDENT.concat(INDENT));
167             }
168             SnookerScoreConsole.delimiter();
169         }
170     }
171
172     private static void printUpcomingEvents(Events events) {
173         Events upcomingEvents = events.upcoming();
174         if (!upcomingEvents.isEmpty()) {
175             SnookerScoreConsole.console(
176                     String.format("%s%s", INDENT, UPCOMING_EVENTS)
177             );
178             int count = 0;
179             for (Event upcomingEvent : upcomingEvents) {
180                 printEvent(upcomingEvent, INDENT.concat(INDENT));
181                 ++count;
182                 if (count >= UPCOMING_COUNT) break;
183             }
184             SnookerScoreConsole.delimiter();
185         }
186     }
187
188     private static void printEvent(Event event, String indent) {
189         SnookerScoreConsole.console(
190                 String.format(
191                         "%s%s [%s - %s] (%s, %s)",
192                         indent,
193                         event.name(),
194                         SnookerDateUtils.formatDate(event.startDate()),
195                         SnookerDateUtils.formatDate(event.endDate()),
196                         event.country(),
197                         event.city()
198                 )
199         );
200     }
201
202     private static void printPlayer(Player player) {
203         SnookerScoreConsole.console(
204                 String.format(
205                         "%s%s %s [%s] (%s)",
206                         INDENT,
207                         player.surnameFirst() ? player.lastName() : player.firstName(),
208                         player.surnameFirst() ? player.firstName() : player.lastName(),
209                         SnookerDateUtils.formatDate(player.born()),
210                         player.nationality()
211                 )
212         );
213     }
214
215     private static void printMatch(Match match) throws APIException {
216         SnookerScoreAPI api = Snooker.uncachedAPI();
217         Player player1 = api.getPlayer(match.player1Id());
218         Player player2 = api.getPlayer(match.player2Id());
219         SnookerScoreConsole.console(
220                 String.format(
221                         "%s[%s %s - %s] %s %s %s-%s %s %s",
222                         INDENT,
223                         SnookerDateUtils.formatDate(match.startDate()),
224                         SnookerDateUtils.formatTime(match.startDate()),
225                         SnookerDateUtils.formatTime(match.endDate()),
226                         player1.surnameFirst() ? player1.lastName() : player1.firstName(),
227                         player1.surnameFirst() ? player1.firstName() : player1.lastName(),
228                         match.score1(),
229                         match.score2(),
230                         player2.surnameFirst() ? player2.lastName() : player2.firstName(),
231                         player2.surnameFirst() ? player2.firstName() : player2.lastName()
232                 )
233         );
234     }
235
236     private static void printRounds(Rounds rounds, Event event) throws APIException {
237         if (!rounds.isEmpty()) {
238             rounds.sortByRound();
239             if (event != null) {
240                 SnookerScoreConsole.console(
241                         String.format("%s%s %s:", INDENT, EVENT_ROUNDS, event.name())
242                 );
243             }
244             for (Round round : rounds) {
245                 printRound(round, event, INDENT.concat(INDENT));
246             }
247             SnookerScoreConsole.delimiter();
248         }
249     }
250
251     private static void printRound(Round round, Event event, String indent) throws APIException {
252         if (event == null || event.getId() != round.eventId()) {
253             SnookerScoreAPI api = Snooker.uncachedAPI();
254             Event roundEvent = api.getEvent(round.eventId());
255             SnookerScoreConsole.console(
256                     String.format(
257                             "%s%s. %s (%s)",
258                             indent,
259                             round.round(),
260                             round.roundName(),
261                             roundEvent.name()
262                     )
263             );
264         } else {
265             SnookerScoreConsole.console(
266                     String.format(
267                             "%s%s. %s",
268                             indent,
269                             round.round(),
270                             round.roundName()
271                     )
272             );
273         }
274     }
275
276     private static void printSeedings(Seedings seedings, Event event) throws APIException {
277         if (!seedings.isEmpty()) {
278             seedings.sortBySeeding();
279             if (event != null) {
280                 SnookerScoreConsole.console(
281                         String.format(
282                                 "%s%s %s (top %d):",
283                                 INDENT,
284                                 EVENT_SEEDING,
285                                 event.name(),
286                                 TOP_SEEDING_COUNT
287                         )
288                 );
289             }
290             int count = 0;
291             for (Seeding seeding : seedings) {
292                 printSeeding(seeding, INDENT.concat(INDENT));
293                 ++count;
294                 if (count >= TOP_SEEDING_COUNT) break;
295             }
296             SnookerScoreConsole.delimiter();
297         }
298     }
299
300     private static void printSeeding(Seeding seeding, String indent) throws APIException {
301         SnookerScoreAPI api = Snooker.uncachedAPI();
302         Player player = api.getPlayer(seeding.playerId());
303         SnookerScoreConsole.console(
304                 String.format(
305                         "%s%s. %s %s",
306                         indent,
307                         seeding.seeding(),
308                         player.surnameFirst() ? player.lastName() : player.firstName(),
309                         player.surnameFirst() ? player.firstName() : player.lastName()
310                 )
311         );
312     }
313
314 }