Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Last active September 12, 2015 02:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/6135bcca86a52bb346e5 to your computer and use it in GitHub Desktop.
Save xuwei-k/6135bcca86a52bb346e5 to your computer and use it in GitHub Desktop.
scalaVersion := "2.11.7"
libraryDependencies += "com.github.scalaprops" %% "scalaprops-gen" % "0.1.13"
libraryDependencies += "com.typesafe.play" %% "play-netty-server" % "2.4.3"
package scalaz
import java.io.{FileInputStream, File}
import java.nio.file.Files
import java.util.Collections.singletonList
import scalaprops.Gen
import scala.util.Random
object Tree2SVG {
def main(args: Array[String]): Unit = {
import play.core.server._
import play.api.routing.sird._
import play.api.mvc._
val server = NettyServer.fromRouter(ServerConfig(
mode = play.api.Mode.Test
)) {
case GET(p"/") => Action {
Results.Ok(generateSVG()).as("image/svg+xml")
}
}
}
def generateSVG(): String = {
val s = Stream.continually(Random.nextInt(128)).distinct
val i = s.iterator
def next(): Int = i.next
val uniqueIntTreeGen = Gen.treeGen(Gen.gen((_, r) => (r, next())))
val t = uniqueIntTreeGen.sample(seed = System.currentTimeMillis()).map(_.toString)
val g = graph(Foldable[Tree].toList(t), treeEdges(t))
val f = new File("tree.svg")
toSVG(g, f)
scala.io.Source.fromFile(f).getLines().mkString
}
def withTmpDir[T](action: File => T): T = {
val dir = Files.createTempDirectory(System.currentTimeMillis().toString).toFile
try {
action(dir)
}
finally {
dir.delete()
}
}
def toSVG(graph: String, output: File): Unit = withTmpDir { dir =>
import scala.sys.process._
val name = System.currentTimeMillis.toString
val dotFile = new File(dir, name + ".dot")
Files.write(dotFile.toPath, singletonList(graph))
// http://www.graphviz.org/
Seq("dot", "-o" + output.getAbsolutePath, "-Tsvg", dotFile.getAbsolutePath).!
}
def treeEdges[A](tree: Tree[A]): List[(A, A)] = {
def loop(s: Tree[A], parent: A): Stream[(A, A)] =
s.subForest.flatMap{ sub =>
loop(sub, sub.rootLabel) ++ List(parent -> sub.rootLabel)
}
loop(tree, tree.rootLabel).toList
}
val quote = "\"" + (_: String) + "\""
def graph(nodes: List[String], edges: List[(String, String)]): String = s"""
digraph "tree" {
node [
]
edge [
]
${nodes.iterator.map(quote).mkString("\n")}
${edges.iterator.map{case (a, b) => quote(a) + " -> " + quote(b)}.mkString("\n")}
}
"""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment