From 962aa6a86c78199bf2fbc2ce3daa2d2f243613d2 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Sat, 11 May 2024 15:52:31 -0700 Subject: [PATCH] Added Config builder --- README.md | 25 +++++++ config/detekt/baseline.xml | 5 +- .../java/com/example/ReadingTimeSample.java | 8 +++ examples/gradle/build.gradle.kts | 2 +- .../java/com/example/ReadingTimeSample.java | 8 +++ .../net/thauvin/erik/readingtime/Config.kt | 69 +++++++++++++++++++ .../thauvin/erik/readingtime/ReadingTime.kt | 24 +++++-- .../erik/readingtime/ReadingTimeTest.kt | 43 ++++++++++++ 8 files changed, 174 insertions(+), 10 deletions(-) create mode 100644 src/main/kotlin/net/thauvin/erik/readingtime/Config.kt diff --git a/README.md b/README.md index 7dd06b6..1505d3a 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,11 @@ repositories = List.of(MAVEN_CENTRAL); scope(compile) .include(dependency("net.thauvin.erik:readingtime:0.9.2")); ``` + Be sure to use the [bld Kotlin extension](https://github.com/rife2/bld-kotlin) in your project. ### Gradle, Maven, etc. + To use with [Gradle](https://gradle.org/), include the following dependency in your [build](https://github.com/ethauvin/readingtime/blob/master/examples/gradle/build.gradle.kts) file: ```gradle @@ -54,6 +56,7 @@ dependencies { implementation("net.thauvin.erik:readingtime:0.9.2") } ``` + Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://search.maven.org/search?q=g:%22net.thauvin.erik%22%20AND%20a:%22readingtime%22). ## Properties @@ -108,6 +111,28 @@ A JSP tag is also available for easy incorporation into web applications: None of the attributes are required. +## Java + +In addition to setters, a configuration builder is also available: + +```java +final ReadingTime rt = new ReadingTime(Files.readString(text)); +rt.setPostfix("minute to read"); +rt.setPlural("minutes to read"); +``` + +or + +```java +final Config config = + new Config.Builder() + .text(Files.readString(text)) + .postfix("minute to read") + .plural("minutes to read") + .build(); +final ReadingTime rt = new ReadingTime(config); +``` + ## Contributing If you want to contribute to this project, all you have to do is clone the GitHub diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml index 24cc530..0a090bf 100644 --- a/config/detekt/baseline.xml +++ b/config/detekt/baseline.xml @@ -1,8 +1,9 @@ - + - + LongMethod:ReadingTimeTest.kt$ReadingTimeTest$@Test fun testReadingTimeInSec() + LongParameterList:Config.kt$Config$( val text: String, val wpm: Int, val postfix: String, val plural: String, val excludeImages: Boolean, val extra: Int, val roundingMode: RoundingMode ) LongParameterList:ReadingTime.kt$ReadingTime$( text: String, wpm: Int = 275, var postfix: String = "min read", var plural: String = "min read", excludeImages: Boolean = false, extra: Int = 0, var roundingMode: RoundingMode = RoundingMode.HALF_EVEN ) MagicNumber:ReadingTime.kt$ReadingTime$10 MagicNumber:ReadingTime.kt$ReadingTime$12 diff --git a/examples/bld/src/main/java/com/example/ReadingTimeSample.java b/examples/bld/src/main/java/com/example/ReadingTimeSample.java index faaf6a2..b7e78f1 100644 --- a/examples/bld/src/main/java/com/example/ReadingTimeSample.java +++ b/examples/bld/src/main/java/com/example/ReadingTimeSample.java @@ -15,6 +15,14 @@ public class ReadingTimeSample { rt.setPostfix("minute to read"); rt.setPlural("minutes to read"); +// final Config config = +// new Config.Builder() +// .text(Files.readString(text)) +// .postfix("minute to read") +// .plural("minutes to read") +// .build(); +// final ReadingTime rt = new ReadingTime(config); + System.out.println("It will take " + rt.calcReadingTime() + ' ' + ReadingTime.wordCount(rt.getText()) + " words and " + ReadingTime.imgCount(rt.getText()) + " images at " + rt.getWpm() + " words per minute."); diff --git a/examples/gradle/build.gradle.kts b/examples/gradle/build.gradle.kts index f5ec670..1dab54c 100644 --- a/examples/gradle/build.gradle.kts +++ b/examples/gradle/build.gradle.kts @@ -12,7 +12,7 @@ repositories { } dependencies { - implementation("net.thauvin.erik:readingtime:0.9.2") + implementation("net.thauvin.erik:readingtime:0.9.3-SNAPSHOT") } java { diff --git a/examples/gradle/src/main/java/com/example/ReadingTimeSample.java b/examples/gradle/src/main/java/com/example/ReadingTimeSample.java index faaf6a2..b7e78f1 100644 --- a/examples/gradle/src/main/java/com/example/ReadingTimeSample.java +++ b/examples/gradle/src/main/java/com/example/ReadingTimeSample.java @@ -15,6 +15,14 @@ public class ReadingTimeSample { rt.setPostfix("minute to read"); rt.setPlural("minutes to read"); +// final Config config = +// new Config.Builder() +// .text(Files.readString(text)) +// .postfix("minute to read") +// .plural("minutes to read") +// .build(); +// final ReadingTime rt = new ReadingTime(config); + System.out.println("It will take " + rt.calcReadingTime() + ' ' + ReadingTime.wordCount(rt.getText()) + " words and " + ReadingTime.imgCount(rt.getText()) + " images at " + rt.getWpm() + " words per minute."); diff --git a/src/main/kotlin/net/thauvin/erik/readingtime/Config.kt b/src/main/kotlin/net/thauvin/erik/readingtime/Config.kt new file mode 100644 index 0000000..bb66724 --- /dev/null +++ b/src/main/kotlin/net/thauvin/erik/readingtime/Config.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020-2024, 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.readingtime + +import java.math.RoundingMode + +/** + * Provides a configuration builder. + */ +class Config private constructor( + val text: String, + val wpm: Int, + val postfix: String, + val plural: String, + val excludeImages: Boolean, + val extra: Int, + val roundingMode: RoundingMode +) { + /** + * Configures the parameters. + */ + data class Builder( + private var text: String = "", + private var wpm: Int = 275, + private var postfix: String = "min read", + private var plural: String = "min read", + private var excludeImages: Boolean = false, + private var extra: Int = 0, + private var roundingMode: RoundingMode = RoundingMode.HALF_EVEN + ) { + fun text(text: String) = apply { this.text = text } + fun wpm(wpm: Int) = apply { this.wpm = wpm } + fun postfix(postfix: String) = apply { this.postfix = postfix } + fun plural(plural: String) = apply { this.plural = plural } + fun excludeImages(excludeImages: Boolean) = apply { this.excludeImages = excludeImages } + fun extra(extra: Int) = apply { this.extra = extra } + fun roundingMode(roundingMode: RoundingMode) = apply { this.roundingMode = roundingMode } + + fun build() = Config(text, wpm, postfix, plural, excludeImages, extra, roundingMode) + } +} diff --git a/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt b/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt index 77f0261..0f593cf 100644 --- a/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt +++ b/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt @@ -50,14 +50,24 @@ import java.math.RoundingMode * @param roundingMode The [RoundingMode] to apply. Default is [RoundingMode.HALF_DOWN]. */ class ReadingTime @JvmOverloads constructor( - text: String, - wpm: Int = 275, - var postfix: String = "min read", - var plural: String = "min read", - excludeImages: Boolean = false, - extra: Int = 0, - var roundingMode: RoundingMode = RoundingMode.HALF_EVEN + text: String, + wpm: Int = 275, + var postfix: String = "min read", + var plural: String = "min read", + excludeImages: Boolean = false, + extra: Int = 0, + var roundingMode: RoundingMode = RoundingMode.HALF_EVEN ) { + constructor(config: Config) : this( + config.text, + config.wpm, + config.postfix, + config.plural, + config.excludeImages, + config.extra, + config.roundingMode + ) + companion object { private const val INVALID: Double = -1.0 diff --git a/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt b/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt index ebb57bd..37b0ad9 100644 --- a/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt +++ b/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt @@ -186,6 +186,49 @@ class ReadingTimeTest { assertEquals("2", rt.calcReadingTime(), "calcReadingTime(275 * 2)") } + @Test + fun testReadingTimeConfig() { + var config = Config.Builder().text(blogPost) + + assertEquals("2 min read", ReadingTime(config.build()).calcReadingTime(), + "calcReadingTime(blogPost)") + + config = config.plural("mins read") + assertEquals("2 mins read", ReadingTime(config.build()).calcReadingTime(), + "calcReadingTime(plural)") + + config = config.text(mediumPost).plural("") + assertEquals("2", ReadingTime(config.build()).calcReadingTime(), "calcReadingTime(mediumPost)") + + config = config.text("This is a test.").postfix("") + assertEquals("0", ReadingTime(config.build()).calcReadingTime(), "calcReadingTime(test)") + + config = config.text("") + assertEquals("0", ReadingTime(config.build()).calcReadingTime(), "calcReadingTime(empty)") + + config = config.text(twoSeventyFive) + assertEquals("1", ReadingTime(config.build()).calcReadingTime(), "calcReadingTime(275)") + + config = config.text("$twoSeventyFive $twoSeventyFive") + assertEquals("2", ReadingTime(config.build()).calcReadingTime(), "calcReadingTime(275 * 2)") + + config = config.extra(60) + assertEquals("3", ReadingTime(config.build()).calcReadingTime(), "extra(60)") + + config = config.text(blogPost).roundingMode(RoundingMode.UP) + assertEquals("4", ReadingTime(config.build()).calcReadingTime(), "RoundingMode.UP") + + config = config.text(mediumPost).wpm(300).extra(0) + assertEquals( + calcReadingTime(mediumPost, 300) + calcImgTime(3), + ReadingTime(config.build()).calcReadingTimeInSec(), + "calcReadingTimeInSec(mediumPost 300 wpm)" + ) + + config = config.excludeImages(true) + assertEquals("1", ReadingTime(config.build()).calcReadingTime(), "excludeImages") + } + @Test fun testRoundingMode() { rt.text = blogPost