diff --git a/src/main/java/net/thauvin/erik/mobibot/modules/WorldTime.java b/src/main/java/net/thauvin/erik/mobibot/modules/WorldTime.java index a656ddc..2c9a78a 100644 --- a/src/main/java/net/thauvin/erik/mobibot/modules/WorldTime.java +++ b/src/main/java/net/thauvin/erik/mobibot/modules/WorldTime.java @@ -32,6 +32,9 @@ package net.thauvin.erik.mobibot.modules; import net.thauvin.erik.mobibot.Mobibot; +import net.thauvin.erik.mobibot.msg.ErrorMessage; +import net.thauvin.erik.mobibot.msg.Message; +import net.thauvin.erik.mobibot.msg.PublicMessage; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -48,23 +51,17 @@ import java.util.TreeMap; * @since 1.0 */ public final class WorldTime extends AbstractModule { + // The beats (Internet Time) keyword. + private static final String BEATS_KEYWORD = ".beats"; + // The supported countries. + private static final Map COUNTRIES_MAP = new TreeMap<>(); + /** * The time command. */ - public static final String TIME_CMD = "time"; - - // The beats (Internet Time) keyword. - private static final String BEATS_KEYWORD = ".beats"; - - // The supported countries. - private static final Map COUNTRIES_MAP = new TreeMap<>(); - - /** - * Creates a new {@link WorldTime} instance. - */ - public WorldTime() { - commands.add(TIME_CMD); + private static final String TIME_CMD = "time"; + static { // Initialize the countries map COUNTRIES_MAP.put("AE", "Asia/Dubai"); COUNTRIES_MAP.put("AF", "Asia/Kabul"); @@ -141,12 +138,50 @@ public final class WorldTime extends AbstractModule { COUNTRIES_MAP.put("ZULU", "Zulu"); COUNTRIES_MAP.put("INTERNET", BEATS_KEYWORD); COUNTRIES_MAP.put("BEATS", BEATS_KEYWORD); - + ZoneId.getAvailableZoneIds().stream().filter( tz -> !tz.contains("/") && tz.length() == 3 && !COUNTRIES_MAP.containsKey(tz)).forEach( tz -> COUNTRIES_MAP.put(tz, tz)); } + /** + * Creates a new {@link WorldTime} instance. + */ + public WorldTime() { + commands.add(TIME_CMD); + } + + /** + * Returns the current Internet (beat) Time. + * + * @return The Internet Time string. + */ + private static String internetTime() { + final ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("UTC+01:00")); + final int beats = (int) ((zdt.get(ChronoField.SECOND_OF_MINUTE) + (zdt.get(ChronoField.MINUTE_OF_HOUR) * 60) + + (zdt.get(ChronoField.HOUR_OF_DAY) * 3600)) / 86.4); + return String.format("%c%03d", '@', beats); + } + + static Message worldTime(String query) { + final String tz = (COUNTRIES_MAP.get((query.substring(query.indexOf(' ') + 1).trim().toUpperCase()))); + final String response; + + if (tz != null) { + if (tz.equals(BEATS_KEYWORD)) { + response = ("The current Internet Time is: " + internetTime() + ' ' + BEATS_KEYWORD); + } else { + response = ZonedDateTime.now().withZoneSameInstant(ZoneId.of(tz)).format( + DateTimeFormatter.ofPattern("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '")) + + tz.substring(tz.indexOf('/') + 1).replace('_', ' '); + } + } else { + return new ErrorMessage("The supported countries/zones are: " + COUNTRIES_MAP.keySet().toString()); + } + + return new PublicMessage(response); + } + /** * Responds with the current time in the specified timezone/country. * @@ -157,30 +192,15 @@ public final class WorldTime extends AbstractModule { */ @Override public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) { - boolean isInvalidTz = false; - final String tz = (COUNTRIES_MAP.get((args.substring(args.indexOf(' ') + 1).trim().toUpperCase()))); - final String response; - - if (tz != null) { - if (tz.equals(BEATS_KEYWORD)) { - response = ("The current Internet Time is: " + internetTime() + ' ' + BEATS_KEYWORD); - } else { - response = ZonedDateTime.now().withZoneSameInstant(ZoneId.of(tz)).format( - DateTimeFormatter.ofPattern("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '")) - + tz.substring(tz.indexOf('/') + 1).replace('_', ' '); - } - } else { - isInvalidTz = true; - response = "The supported countries/zones are: " + COUNTRIES_MAP.keySet().toString(); - } + final Message msg = worldTime(args); if (isPrivate) { - bot.send(sender, response, true); + bot.send(sender, msg.getMessage(), true); } else { - if (isInvalidTz) { - bot.send(sender, response); + if (msg.isError()) { + bot.send(sender, msg.getMessage()); } else { - bot.send(bot.getChannel(), response); + bot.send(bot.getChannel(), msg.getMessage()); } } } @@ -197,18 +217,6 @@ public final class WorldTime extends AbstractModule { bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TIME_CMD)); } - /** - * Returns the current Internet (beat) Time. - * - * @return The Internet Time string. - */ - private String internetTime() { - final ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("UTC+01:00")); - final int beats = (int) ((zdt.get(ChronoField.SECOND_OF_MINUTE) + (zdt.get(ChronoField.MINUTE_OF_HOUR) * 60) - + (zdt.get(ChronoField.HOUR_OF_DAY) * 3600)) / 86.4); - return String.format("%c%03d", '@', beats); - } - /** * {@inheritDoc} */ diff --git a/src/test/java/net/thauvin/erik/mobibot/modules/WordTimeTest.java b/src/test/java/net/thauvin/erik/mobibot/modules/WordTimeTest.java new file mode 100644 index 0000000..97d420a --- /dev/null +++ b/src/test/java/net/thauvin/erik/mobibot/modules/WordTimeTest.java @@ -0,0 +1,57 @@ +/* + * WordTimeTest.java + * + * Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of this project nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.thauvin.erik.mobibot.modules; + +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * The WordTimeTest class. + * + * @author Erik C. Thauvin + * @created 2019-04-07 + * @since 1.0 + */ +public class WordTimeTest { + @Test + public void testWorldTimeImpl() { + AbstractModuleTest.testAbstractModule(new Lookup()); + } + + @Test + public void testWorldTime() { + assertThat(WorldTime.worldTime("PST").getMessage()).as("PST").startsWith("The time is "); + assertThat(WorldTime.worldTime("BLAH").isError()).as("BLAH").isTrue(); + assertThat(WorldTime.worldTime("BEATS").getMessage()).as("BEATS").contains("@"); + } +}