forked from nova/jmonkey-test
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.9 KiB
164 lines
4.9 KiB
package wow.doge.mygame.subsystems.moddingsystem
|
|
import java.io.FileNotFoundException
|
|
import java.nio.file.NoSuchFileException
|
|
|
|
import scala.collection.View
|
|
import scala.collection.immutable.ArraySeq
|
|
import scala.util.Try
|
|
|
|
import cats.implicits._
|
|
import io.circe._
|
|
import io.circe.generic.JsonCodec
|
|
import io.circe.generic.semiauto._
|
|
import io.circe.parser._
|
|
import monix.bio.IO
|
|
import monix.bio.UIO
|
|
import monix.reactive.Consumer
|
|
import monix.reactive.Observable
|
|
import wow.doge.mygame.utils.IOUtils
|
|
|
|
@JsonCodec
|
|
final case class Test1(hello1: String, hello2: String)
|
|
@JsonCodec
|
|
final case class Test2(hello1: String)
|
|
final case class Plugin(name: String, priority: Int)
|
|
object Plugin {
|
|
implicit val pluginFormat: Decoder[Plugin] = deriveDecoder
|
|
}
|
|
|
|
object ModdingSystem {
|
|
sealed trait Error
|
|
final case class CouldNotDecode(cause: String) extends Error
|
|
final case class ParseFailure(cause: String) extends Error
|
|
final case class FileNotFound(fileName: String) extends Error
|
|
case object GenericError extends Error
|
|
|
|
def readPluginsList(dir: os.Path): Try[Either[Error, ArraySeq[Plugin]]] =
|
|
Try(
|
|
parse(os.read(dir / "plugins.json"))
|
|
.map(
|
|
_.as[ArraySeq[Plugin]]
|
|
.leftMap(e => CouldNotDecode(e.getMessage()))
|
|
)
|
|
.leftMap((e: ParsingFailure) => ParseFailure(e.message))
|
|
.flatten
|
|
)
|
|
// .toValidated
|
|
|
|
def findPluginFiles(dir: os.Path): View[os.Path] =
|
|
os.list(dir)
|
|
.view
|
|
.filter(f => f.ext == "json" && f.baseName.endsWith("plugin"))
|
|
|
|
def findAndReadPluginFiles(
|
|
dir: os.Path,
|
|
plugins: ArraySeq[Plugin]
|
|
): (View[(Plugin, Error)], View[(Plugin, String)]) =
|
|
plugins
|
|
.sortBy(_.priority)
|
|
.view
|
|
.map(p =>
|
|
p ->
|
|
Either
|
|
.catchNonFatal {
|
|
val path = dir / os.RelPath(p.name + ".plugin.json")
|
|
os.read(path)
|
|
}
|
|
.leftMap {
|
|
case _: FileNotFoundException =>
|
|
FileNotFound(p.name)
|
|
case _: NoSuchFileException => FileNotFound(p.name)
|
|
case e => GenericError
|
|
}
|
|
)
|
|
.partitionMap {
|
|
case (p, either) =>
|
|
either match {
|
|
case Left(value) => Left(p -> value)
|
|
case Right(value) => Right(p -> value)
|
|
}
|
|
}
|
|
|
|
def readPluginFiles(filePaths: View[os.Path]) =
|
|
filePaths.map(path => os.read(path))
|
|
|
|
def parsePluginFiles(files: View[(Plugin, String)]) =
|
|
files
|
|
.map {
|
|
case (p, s) => p -> parse(s)
|
|
}
|
|
.partitionMap {
|
|
case (p, Left(value)) => Left(p -> value)
|
|
case (p, Right(value)) => Right(p -> value)
|
|
}
|
|
|
|
def foldMerge(iterable: Iterable[Json]) =
|
|
iterable.foldLeft(Json.fromString("empty")) {
|
|
case (json, io.circe.Json.Null) => json //ignore null values
|
|
case (json, value) => json.deepMerge(value)
|
|
}
|
|
|
|
def mergePluginData(plugins: View[(Plugin, Json)]) =
|
|
foldMerge(plugins.map {
|
|
case (p, json) => json
|
|
})
|
|
|
|
def mergePluginDataConsumer =
|
|
Consumer.foldLeft[Json, Json](Json.fromString("empty")) {
|
|
case (json, io.circe.Json.Null) => json
|
|
case (json, that) => json.deepMerge(that)
|
|
}
|
|
|
|
def loadBalancedPluginDataMerger =
|
|
Consumer
|
|
.loadBalance(parallelism = 2, mergePluginDataConsumer)
|
|
.map(foldMerge)
|
|
|
|
// def test =
|
|
// for {
|
|
// filePaths <- Task(findPluginFiles(os.pwd))
|
|
// files <- Task(readPluginFiles(filePaths))
|
|
// (failures, successes) <- Task(parsePluginFiles(files))
|
|
// merged <- Task(mergePluginData(successes))
|
|
// _ <- Task {
|
|
// println(s"Successes = ${successes.to(Seq)}")
|
|
// println(s"Failure = ${failures.to(Seq)}")
|
|
// println(s"Merged = $merged")
|
|
// }
|
|
// } yield ()
|
|
|
|
def test(wd: os.Path = os.pwd) =
|
|
for {
|
|
plugins <- IO.fromTryEither(readPluginsList(wd))
|
|
(readFailures, readSuccesses) <- UIO(findAndReadPluginFiles(wd, plugins))
|
|
(parseFailures, parseSuccesses) <- UIO(parsePluginFiles(readSuccesses))
|
|
// res <- UIO(mergePluginData(parseSuccesses))
|
|
res <-
|
|
IOUtils
|
|
.toIO(
|
|
Observable
|
|
.fromIterable(parseSuccesses)
|
|
.map { case (p, json) => json }
|
|
.consumeWith(loadBalancedPluginDataMerger)
|
|
)
|
|
.hideErrors
|
|
_ <- UIO {
|
|
println(s"Read Successes = ${readSuccesses.to(Seq)}")
|
|
println(s"Read Failures = ${readFailures.to(Seq)}")
|
|
println(s"Parse Successes = ${parseSuccesses.to(Seq)}")
|
|
println(s"Parse Failures = ${parseFailures.to(Seq)}")
|
|
println(show"Merged = $res")
|
|
}
|
|
} yield ()
|
|
|
|
// monix.eval.Task.deferAction(implicit s =>
|
|
// ModdingSystem
|
|
// .test()
|
|
// .leftMap(e => new Throwable(e.toString()))
|
|
// .to[monix.eval.Task]
|
|
// )
|
|
|
|
// def test3(wd: os.Path = os.pwd) = {
|
|
// (readPluginsList(os.pwd).toValidatedNec)
|
|
// }
|
|
}
|