Add a scripting system.
This commit is contained in:
parent
6ea8f90903
commit
9718056260
2 changed files with 146 additions and 0 deletions
88
app/src/main/java/com/pixelized/rplexicon/script/Script.kt
Normal file
88
app/src/main/java/com/pixelized/rplexicon/script/Script.kt
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package com.pixelized.rplexicon.script
|
||||
|
||||
import com.pixelized.rplexicon.data.model.alteration.Alteration
|
||||
|
||||
sealed class Script(
|
||||
val predicate: ScriptExecutor.() -> Boolean
|
||||
) {
|
||||
class OR(
|
||||
private vararg val scripts: Script,
|
||||
) : Script(predicate = {
|
||||
scripts.any { it.predicate.invoke(this) }
|
||||
}) {
|
||||
override fun toString(): String {
|
||||
return scripts.joinToString(
|
||||
prefix = "(",
|
||||
postfix = ")",
|
||||
separator = " || "
|
||||
) { it.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
class AND(
|
||||
private vararg val scripts: Script,
|
||||
) : Script(predicate = {
|
||||
scripts.all { it.predicate.invoke(this) }
|
||||
}) {
|
||||
override fun toString(): String {
|
||||
return scripts.joinToString(
|
||||
prefix = "(",
|
||||
postfix = ")",
|
||||
separator = " && "
|
||||
) { it.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
class ACTIVE(
|
||||
val alteration: String,
|
||||
) : Script(predicate = {
|
||||
alterations.any { it.name == alteration }
|
||||
}) {
|
||||
override fun toString(): String {
|
||||
return "ACTIVE('$alteration')"
|
||||
}
|
||||
}
|
||||
|
||||
class ANY(
|
||||
val alteration: String,
|
||||
) : Script(predicate = {
|
||||
alterations.any { it.name.contains(alteration) }
|
||||
}) {
|
||||
override fun toString(): String {
|
||||
return "ANY('$alteration')"
|
||||
}
|
||||
}
|
||||
|
||||
class NOT(
|
||||
val alteration: String,
|
||||
) : Script(predicate = {
|
||||
alterations.none { it.name == alteration }
|
||||
}) {
|
||||
override fun toString(): String {
|
||||
return "NOT('$alteration')"
|
||||
}
|
||||
}
|
||||
|
||||
class NONE(
|
||||
val alteration: String,
|
||||
) : Script(predicate = {
|
||||
alterations.none { it.name.contains(alteration) }
|
||||
}) {
|
||||
override fun toString(): String {
|
||||
return "NONE('$alteration')"
|
||||
}
|
||||
}
|
||||
|
||||
operator fun ScriptExecutor.invoke() = predicate()
|
||||
}
|
||||
|
||||
class ScriptExecutor(
|
||||
val alterations: List<Alteration>,
|
||||
)
|
||||
|
||||
fun scriptExecutor(
|
||||
alterations: List<Alteration>,
|
||||
block: ScriptExecutor.() -> Boolean
|
||||
): Boolean {
|
||||
return ScriptExecutor(alterations = alterations).run(block)
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.pixelized.rplexicon.script
|
||||
|
||||
class ScriptParser {
|
||||
companion object {
|
||||
private val FUNCTION_REGEX = Regex("""^(\w+)\((?:(.*);(.*)|(.*))\)$""")
|
||||
|
||||
private const val AND = "AND"
|
||||
private const val OR = "OR"
|
||||
private const val IS_ACTIVE = "ACT"
|
||||
private const val ANY = "ANY"
|
||||
private const val NOT = "NOT"
|
||||
private const val NONE = "NONE"
|
||||
|
||||
fun check(function: String, vararg params: String?, block: () -> Script): Script {
|
||||
if (params.any { it.isNullOrEmpty() }) error("$function parameter malformed")
|
||||
return block.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun parse(value: String): Script {
|
||||
val result = FUNCTION_REGEX.findAll(value)
|
||||
|
||||
return result.firstOrNull()?.let { matchResult ->
|
||||
val (function, param1, param2, mono) = matchResult.destructured
|
||||
when (function) {
|
||||
AND -> check(AND, param1, param2) { Script.AND(parse(param1), parse(param2)) }
|
||||
OR -> check(OR, param1, param2) { Script.OR(parse(param1), parse(param2)) }
|
||||
IS_ACTIVE -> check(IS_ACTIVE, mono) { Script.ACTIVE(mono) }
|
||||
ANY -> check(ANY, mono) { Script.ANY(mono) }
|
||||
NOT -> check(NOT, mono) { Script.NOT(mono) }
|
||||
NONE -> check(NONE, mono) { Script.NONE(mono) }
|
||||
else -> error("Unrecognized function: $function")
|
||||
}
|
||||
} ?: error("Malformed script: should start with a function call.")
|
||||
}
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val parser = ScriptParser()
|
||||
val script = listOf(
|
||||
"""ACT(Hache de guerre en argent)""",
|
||||
"""ACT(Forme sauvage : Loup)""",
|
||||
"""ACT(Forme sauvage ; Chat)""",
|
||||
"""AND(ACT(Hache de guerre en argent);NOT(Bouclier))""",
|
||||
"""OR(AND(NOT(Hache);ACT(Épée));ACT(Bouclier))""",
|
||||
"""NONE(Forme sauvage)""",
|
||||
)
|
||||
script.forEach {
|
||||
println("Input << $it")
|
||||
try {
|
||||
println("Output >> ${parser.parse(it)}")
|
||||
} catch (e: Exception) {
|
||||
println("Output >> $e")
|
||||
} finally {
|
||||
println("")
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue