mirror of
https://github.com/SOR2171/Kotlin_Puzzles_Template.git
synced 2026-10-23 18:21:16 +08:00
full basic functions
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package io.github.sor2171.puzzles.annotation
|
||||
|
||||
@Target(AnnotationTarget.FILE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class SkipCompile(val skip: Boolean = true)
|
||||
@@ -0,0 +1,33 @@
|
||||
package io.github.sor2171.puzzles.service
|
||||
|
||||
import io.github.sor2171.puzzles.utils.CompileDetector
|
||||
|
||||
class PuzzleNote(
|
||||
className: String,
|
||||
vararg notes: PuzzleNote? = arrayOf(null)
|
||||
) {
|
||||
val className = CompileDetector.getColoredName(className)
|
||||
val notes = notes
|
||||
|
||||
override fun toString(): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
sb.append(className)
|
||||
|
||||
if (notes.size > 1) {
|
||||
for (i in 1 until notes.size) {
|
||||
sb.append("\n │")
|
||||
notes[i]?.let { note ->
|
||||
sb.append("\n ├── ").append(note.className)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val nextNote = notes.firstOrNull()
|
||||
if (nextNote != null) {
|
||||
sb.append("\n │\n").append(nextNote.toString())
|
||||
}
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package io.github.sor2171.puzzles.service
|
||||
|
||||
import kotlin.random.Random
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class RandomGenerator(vararg keys: Pair<String, KClass<*>>) {
|
||||
val variableMap = mutableMapOf<String, Any>()
|
||||
|
||||
init {
|
||||
keys.forEach { (name, type) ->
|
||||
variableMap[name] = when (type) {
|
||||
String::class -> randomString()
|
||||
|
||||
Byte::class -> Random.nextInt(
|
||||
Byte.MIN_VALUE.toInt(),
|
||||
Byte.MAX_VALUE.toInt() + 1
|
||||
).toByte()
|
||||
|
||||
Short::class -> Random.nextInt(
|
||||
Short.MIN_VALUE.toInt(),
|
||||
Short.MAX_VALUE.toInt() + 1
|
||||
).toShort()
|
||||
|
||||
Int::class -> Random.nextInt()
|
||||
|
||||
Long::class -> Random.nextLong()
|
||||
// [0.0, 1.0)
|
||||
|
||||
Float::class -> Random.nextFloat()
|
||||
|
||||
Double::class -> Random.nextDouble()
|
||||
|
||||
UByte::class -> Random.nextInt(0, UByte.MAX_VALUE.toInt() + 1).toUByte()
|
||||
UShort::class -> Random.nextInt(0, UShort.MAX_VALUE.toInt() + 1).toUShort()
|
||||
UInt::class -> Random.nextInt().toUInt()
|
||||
ULong::class -> Random.nextLong().toULong()
|
||||
|
||||
else -> error("不支持的类型: ${type.qualifiedName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun randomString(length: Int = Random.nextInt(5, 16)): String {
|
||||
val chars = ('a'..'z') + ('A'..'Z').toList() + ('0'..'9').toList()
|
||||
return buildString(length) {
|
||||
repeat(length) {
|
||||
append(chars[Random.nextInt(chars.size)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(key: String) = variableMap[key]
|
||||
|
||||
operator fun set(key: String, value: Any) {
|
||||
variableMap[key] = value
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package io.github.sor2171.puzzles.utils
|
||||
|
||||
import io.github.sor2171.puzzles.service.PuzzleNote
|
||||
|
||||
object CatalogStructure {
|
||||
enum class Classification {
|
||||
ALPHABET,
|
||||
HYPER,
|
||||
EXTRA;
|
||||
|
||||
override fun toString(): String {
|
||||
return super.toString().lowercase()
|
||||
}
|
||||
}
|
||||
|
||||
val puzzlesArray = arrayOf(
|
||||
arrayOf(
|
||||
"${Classification.ALPHABET}.First",
|
||||
"${Classification.EXTRA}.FirstExtra",
|
||||
),
|
||||
arrayOf(
|
||||
"${Classification.HYPER}.Second",
|
||||
)
|
||||
)
|
||||
|
||||
val firstPuzzleNote: PuzzleNote
|
||||
get() {
|
||||
var nextMainNote: PuzzleNote? = null
|
||||
|
||||
for (i in puzzlesArray.indices.reversed()) {
|
||||
val array = puzzlesArray[i]
|
||||
|
||||
val children = Array(array.size) { index ->
|
||||
if (index == 0) {
|
||||
nextMainNote
|
||||
} else {
|
||||
PuzzleNote(array[index])
|
||||
}
|
||||
}
|
||||
|
||||
nextMainNote = PuzzleNote(array[0], *children)
|
||||
}
|
||||
return nextMainNote!!
|
||||
}
|
||||
|
||||
fun printAllMessage() = println(firstPuzzleNote)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.github.sor2171.puzzles.utils
|
||||
|
||||
object CompileDetector {
|
||||
const val ANSI_GREEN = "\u001b[32m"
|
||||
const val ANSI_RESET = "\u001b[0m"
|
||||
|
||||
fun detect(fullName: String): Boolean {
|
||||
return try {
|
||||
Class.forName(fullName)
|
||||
true
|
||||
} catch (_: ClassNotFoundException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun fullName(className: String): String =
|
||||
"io.github.sor2171.puzzles.$className"
|
||||
|
||||
fun getColoredName(className: String): String {
|
||||
val fullName = fullName(className)
|
||||
return if (detect(fullName)) "$ANSI_GREEN$className$ANSI_RESET"
|
||||
else className
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.github.sor2171.puzzles
|
||||
|
||||
import io.github.sor2171.puzzles.utils.CatalogStructure
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* 运行该测试类即可查询此 Kotlin Puzzle 的详细信息。
|
||||
*/
|
||||
class Catalog {
|
||||
@Test
|
||||
fun getCatalog() {
|
||||
CatalogStructure.printAllMessage()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
@file:SkipCompile(skip = false)
|
||||
|
||||
package io.github.sor2171.puzzles.alphabet
|
||||
|
||||
import io.github.sor2171.puzzles.annotation.SkipCompile
|
||||
import io.github.sor2171.puzzles.service.RandomGenerator
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class First {
|
||||
val randoms = RandomGenerator(
|
||||
"a" to Int::class,
|
||||
"b" to Double::class,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun puzzle() {
|
||||
// write start 1
|
||||
val a = randoms["a"]
|
||||
// write end 1
|
||||
|
||||
assert( a == randoms["a"])
|
||||
|
||||
// write start 2
|
||||
val b = randoms["b"]
|
||||
// write end 2
|
||||
|
||||
assert( b == randoms["b"])
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.github.sor2171.puzzles.extend
|
||||
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback
|
||||
import org.junit.jupiter.api.extension.ExtensionContext
|
||||
|
||||
class TestLifecycleLoggerExtension : BeforeAllCallback, AfterAllCallback {
|
||||
|
||||
override fun beforeAll(context: ExtensionContext) {
|
||||
val testClassName = context.requiredTestClass.simpleName
|
||||
println()
|
||||
println("=== [START] $testClassName ===")
|
||||
println()
|
||||
}
|
||||
|
||||
override fun afterAll(context: ExtensionContext) {
|
||||
val testClassName = context.requiredTestClass.simpleName
|
||||
println()
|
||||
println("=== [ END ] $testClassName ===")
|
||||
println()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@file:SkipCompile(skip = true)
|
||||
|
||||
package io.github.sor2171.puzzles.extra
|
||||
|
||||
import io.github.sor2171.puzzles.annotation.SkipCompile
|
||||
|
||||
class FirstExtra {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@file:SkipCompile(skip = true)
|
||||
|
||||
package io.github.sor2171.puzzles.hyper
|
||||
|
||||
import io.github.sor2171.puzzles.annotation.SkipCompile
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class Second {
|
||||
@Test
|
||||
fun () {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
io.github.sor2171.puzzles.extend.TestLifecycleLoggerExtension
|
||||
@@ -0,0 +1 @@
|
||||
junit.jupiter.extensions.autodetection.enabled=true
|
||||
Reference in New Issue
Block a user