diff --git a/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorInt.tjava b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorInt.tjava
new file mode 100644
index 0000000..e3c54e8
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorInt.tjava
@@ -0,0 +1,21 @@
+package com.r35157.libs.random;
+
+/**
+ * This interface provides a way to generate random integers.
+ */
+public interface RandomValueGeneratorInt {
+ /**
+ * Returns a random integer in the full range (min -231. to max 231-1)
+ *
+ * @return a random integer in full range
+ */
+ int getSomeInt();
+
+ /**
+ * Returns a random integer in the range provided by the parameters. Both parameters are included in the range and
+ * {@code minInclusive} must be less than {@code maxInclusive}.
+ *
+ * @return a random integer in the provided range
+ */
+ int getSomeInt(int minInclusive, int maxInclusive);
+}
diff --git a/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorString.tjava b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorString.tjava
new file mode 100644
index 0000000..d83c9c0
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/random/RandomValueGeneratorString.tjava
@@ -0,0 +1,14 @@
+package com.r35157.libs.random;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface RandomValueGeneratorString {
+ /**
+ * Generate a random Alpha Numeric String of exactly the length given as the parameter.
+ *
+ * @param length Length of generated String - cannot be negative
+ * @return A non-null random String of the length given
+ * @throws IllegalArgumentException If length is negative
+ */
+ @NotNull String getSomeStringAlphaNumericOnly(int length) throws IllegalArgumentException;
+}
diff --git a/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorIntImpl.tjava b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorIntImpl.tjava
new file mode 100644
index 0000000..def82c8
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorIntImpl.tjava
@@ -0,0 +1,54 @@
+package com.r35157.libs.random.impl.ref;
+
+import com.r35157.libs.random.RandomValueGeneratorInt;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import static java.lang.Integer.MAX_VALUE;
+import static java.lang.Integer.MIN_VALUE;
+
+public class RandomValueGeneratorIntImpl implements RandomValueGeneratorInt {
+ @Override
+ public int getSomeInt() {
+ // Default: use the full int range
+ return getSomeInt(MIN_VALUE, MAX_VALUE);
+ }
+
+ @Override
+ public int getSomeInt(int minInclusive, int maxInclusive) {
+ if (minInclusive > maxInclusive) {
+ String errorMessage = String.format("'minInclusive' (%d) must be less than or equal to 'maxInclusive' (%d)",
+ minInclusive, maxInclusive);
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ if (minInclusive == maxInclusive) {
+ // Edge case: only one possible value
+ return minInclusive;
+ }
+
+ // Fast path: full int range – ThreadLocalRandom.nextInt() already covers it
+ if (minInclusive == MIN_VALUE && maxInclusive == MAX_VALUE) {
+ return ThreadLocalRandom.current().nextInt();
+ }
+
+ // Use long to avoid overflow when calculating range size
+ long bound = ((long) maxInclusive - (long) minInclusive) + 1L;
+
+ if (bound <= Integer.MAX_VALUE) {
+ // Normal case: the range fits in an int
+ // nextInt(bound) gives a uniform value in [0, bound],
+ // then shift it into the target range by adding minInclusive
+ return minInclusive + ThreadLocalRandom.current().nextInt((int) bound);
+ } else {
+ // Rare case: the range is larger than Integer.MAX_VALUE
+ // (e.g. almost the full int space). Use rejection sampling:
+ // draw values until one falls within the desired interval.
+ int r;
+ do {
+ r = ThreadLocalRandom.current().nextInt();
+ } while (r < minInclusive || r > maxInclusive);
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorStringImpl.tjava b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorStringImpl.tjava
new file mode 100644
index 0000000..661720e
--- /dev/null
+++ b/src/main/tjava/com/r35157/libs/random/impl/ref/RandomValueGeneratorStringImpl.tjava
@@ -0,0 +1,54 @@
+package com.r35157.libs.random.impl.ref;
+
+import com.r35157.libs.random.RandomValueGeneratorInt;
+import com.r35157.libs.random.RandomValueGeneratorString;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+public class RandomValueGeneratorStringImpl implements RandomValueGeneratorString {
+ public RandomValueGeneratorStringImpl(@NotNull RandomValueGeneratorInt rvgi) {
+ Objects.requireNonNull(rvgi, "Cannot initialize with RandomValueGeneratorInt!");
+ this.rvgi = rvgi;
+ }
+
+ public @NotNull String getSomeStringAlphaNumericOnly(int length) throws IllegalArgumentException {
+ if(length < 0) {
+ throw new IllegalArgumentException("Cannot generate random Strings of size " + length + "!");
+ }
+
+ // ASCII Range size
+ // Numeric 48-57 10
+ // Alpha upper 65-90 26
+ // Alpha lower 97-122 26
+ int totalNumberOfCandidates = 10 + 26 + 26;
+
+ StringBuilder buffer = new StringBuilder(length);
+ for (int i = 0; i < length; i++) {
+ int randomInt = rvgi.getSomeInt(0, totalNumberOfCandidates - 1);
+ int asciiIndex = convertRandomIndexToASCIIIndex(randomInt);
+
+ buffer.append((char) asciiIndex);
+ }
+
+ return buffer.toString();
+ }
+
+ private static int convertRandomIndexToASCIIIndex(int randomIndex) {
+ // RandomIndex 0... ...9 - 10... ...35 - 36... ... 61
+ // ASCII values: 48......57 - 65......90 - 97......122
+ int asciiIndex;
+
+ if(randomIndex >= 36) {
+ asciiIndex = 97 + (randomIndex - 36);
+ } else if(randomIndex >= 10) {
+ asciiIndex = 65 + (randomIndex - 10);
+ } else {
+ asciiIndex = 48 + randomIndex;
+ }
+
+ return asciiIndex;
+ }
+
+ private RandomValueGeneratorInt rvgi;
+}