Skip to content

Easy build-able JS #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 5 additions & 18 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
*.class
*.log

# sbt specific
.cache
.history
.lib/
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/

# Scala-IDE specific
.scala_dependencies
.worksheet
.idea/
*.iml
.cache
.classpath
.project
.settings/
.idea
29 changes: 21 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
enablePlugins(ScalaJSPlugin)
// Build file for example applications written in ScalaJS using scala-js-dom and scala-js-workbench
lazy val root = (project in file(".")).enablePlugins(ScalaJSPlugin)
workbenchSettings

name := "A Star Maze Solver"

scalaVersion := "2.11.5"
// Name is a prefix in the object code filename.
name := "A*Star Maze Solver"
scalaVersion := "2.11.7"

// Optional, necessary to sbt run, needs phantomJS to be installed.
jsDependencies += RuntimeDOM
scalaJSStage in Global := FastOptStage

libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.0"
libraryDependencies += "org.scala-js" % "scalajs-tools_2.11" % "0.6.0"
libraryDependencies += "com.lihaoyi" %%% "utest" % "0.3.0" % "test"
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-dom" % "0.8.1",
"com.lihaoyi" %%% "scalatags" % "0.5.2",
"be.doeraene" %%% "scalajs-jquery" % "0.8.0",
"com.lihaoyi" %%% "utest" % "0.3.1" % "test"
)
skip in packageJSDependencies := false // All JavaScript dependencies to be concatenated to a single file

// Workbench has to know how to restart your application.
bootSnippet := "astar.AStarApp().doDynContent();"
// Update without refreshing the page every time fastOptJS completes
updateBrowsers <<= updateBrowsers.triggeredBy(fastOptJS in Compile)

testFrameworks += new TestFramework("utest.runner.Framework")
testFrameworks += new TestFramework("utest.runner.Framework")
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=0.13.7
sbt.version=0.13.9
3 changes: 2 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.1")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.4")
addSbtPlugin("com.lihaoyi" % "workbench" % "0.2.3")
17 changes: 0 additions & 17 deletions src/main/resources/astar-demo-20.html

This file was deleted.

22 changes: 22 additions & 0 deletions src/main/resources/index-dev.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<!--[if lt IE 7 ]><html lang="en" class="ie6 ielt8"><![endif]-->
<!--[if IE 7 ]> <html lang="en" class="ie7 ielt8"><![endif]-->
<!--[if IE 8 ]> <html lang="en" class="ie8"><![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"><!--<![endif]-->
<head>
<meta charset="UTF-8">
<title>A*Star Maze Solver</title>
<script type="application/javascript" src="/workbench.js"></script>
<script type="application/javascript" src="../a-star-maze-solver-fastopt.js"></script>
<script type="application/javascript" src="../a-star-maze-solver-jsdeps.js"></script>
</head>

<body style="margin:32px;padding:0">
<div>
<canvas title="A*Star Maze Solver" style="border:.1em solid;" id="canvas" width="255" height="255">
Your browser does not support HTML 5 Canvas.
</canvas>
</div>
<script> astar.AStarApp().doDynContent(); </script>
</body>
</html>
57 changes: 24 additions & 33 deletions src/main/scala/astar/AStarApp.scala
Original file line number Diff line number Diff line change
@@ -1,69 +1,60 @@
package astar

import astar.maze.Mazes
import astar.maze.Cell
import astar.search.{Heuristics, Agent}
import astar.maze.{Cell, Mazes}
import astar.search.{Agent, Heuristics}
import org.scalajs.dom
import org.scalajs.dom.html

import scala.scalajs.js.JSApp
import org.scalajs.dom

import scala.scalajs.js.annotation.JSExport

@JSExport
object AStarApp extends JSApp {
object AStarApp {

private val GREY = "#333333"
private val BLUE = "#4682b4"
private val YELLOW = "#ffb958"
private val zoom = 10 //px
private val offset = 5 //px
private val drawRate = 10 //milliseconds
private val (grey, blue, yellow) = ("#333333", "#4682b4", "#ffb958")
private val (zoom, offset, drawRate) = (10 /*px*/ , 5 /*px*/ , 10 /*milliseconds*/ )

def main(): Unit = {
val canvas = dom.document
.getElementById("canvas")
.asInstanceOf[html.Canvas]
@JSExport
def doDynContent(): Unit = {
val canvas = dom.document.getElementById("canvas").asInstanceOf[html.Canvas]

val ctx = canvas.getContext("2d")
.asInstanceOf[dom.CanvasRenderingContext2D]
val ctx = canvas.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]

val maze = Mazes.maze20
val maze = Mazes.maze40

val agent = new Agent(maze, Heuristics.manhattan)

val solution:Option[List[Cell]] = agent.search()
val solution: Option[List[Cell]] = agent.search()

canvas.height = maze.height * zoom
canvas.width = maze.width * zoom
canvas.height = maze.height * zoom; canvas.width = maze.width * zoom

ctx.clearRect (0, 0, canvas.width, canvas.height)
ctx.clearRect(0, 0, canvas.width, canvas.height)

ctx.fillStyle = GREY
for(wall <- maze.walls) {
ctx.fillStyle = grey
for (wall <- maze.walls) {
ctx.fillRect(wall.x * zoom, wall.y * zoom, zoom, zoom)
}

if(solution.isDefined) {
if (solution.isDefined) {
dom.console.log("Nodes expanded:" + agent.searchHistory.size)
draw(agent.searchHistory)
}

def draw(fringe:Seq[List[Cell]]):Unit = {
if(fringe.nonEmpty) {
ctx.fillStyle = BLUE
def draw(fringe: Seq[List[Cell]]): Unit = {
if (fringe.nonEmpty) {
ctx.fillStyle = blue
for (cell <- fringe.head) {
ctx.beginPath()
ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom -2)/ 2, 0, 2 * math.Pi)
ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom - 2) / 2, 0, 2 * math.Pi)
ctx.fill()
}
dom.setTimeout(() => draw(fringe.tail), drawRate)
} else {
val path = solution.get
ctx.fillStyle = YELLOW
for(cell <- path) {
ctx.fillStyle = yellow
for (cell <- path) {
ctx.beginPath()
ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom -2)/ 2, 0, 2 * math.Pi)
ctx.arc(cell.x * zoom + offset, cell.y * zoom + offset, (zoom - 2) / 2, 0, 2 * math.Pi)
ctx.fill()
}
}
Expand Down
25 changes: 0 additions & 25 deletions src/main/scala/astar/maze/Cell.scala

This file was deleted.

59 changes: 32 additions & 27 deletions src/main/scala/astar/maze/Maze.scala
Original file line number Diff line number Diff line change
@@ -1,58 +1,63 @@
package astar.maze
package astar
package maze

/**
* A problem for the A* agent to traverse.
*
* Mazes are generated from text strings using:
* +- for horizontal walls
* | for vertical walls
* spaces for paths
* I for the entrance
* O for the exit
* +- for horizontal walls
* | for vertical walls
* spaces for paths
* I for the entrance
* O for the exit
*
* Author: Phillip Johnson
* Date: 3/14/15 (mmmm...π)
*/
class Maze(val pattern:String) {

require(pattern.contains("I"))
require(pattern.contains("O"))
case class Cell(x: Int, y: Int) {
override def toString = s"($x, $y)"
}

class Maze(val pattern: String) {
require(pattern.contains("I") && pattern.contains("O"), "Missing maze entrance or exit")

private val WALL_STRINGS = Set('+','-','|')
private val PATH_STRINGS = Set(' ','I','O')
private val WALL_STRINGS = Set('+', '-', '|')
private val PATH_STRINGS = Set(' ', 'I', 'O')
private val ENTRANCE_STRING = 'I'
private val EXIT_STRING = 'O'

private val stringRows = pattern.split("\n")

val width = stringRows.head.length
val height = stringRows.size
//private val stringRows = pattern.split('\n')
val (width, height) = sizeOfMaze

lazy val walls:Set[Cell] = {
lazy val walls: Set[Cell] = {
searchMaze(WALL_STRINGS)
}

lazy val paths:Set[Cell] = {
lazy val paths: Set[Cell] = {
searchMaze(PATH_STRINGS)
}

lazy val entrance:(Cell) = {
lazy val entrance: (Cell) = {
searchMaze(Set(ENTRANCE_STRING)).head
}

lazy val exit:(Cell) = {
lazy val exit: (Cell) = {
searchMaze(Set(EXIT_STRING)).head
}

private def searchMaze(chars:Set[Char]) = {
val rows = stringRows
val results = for {
(rowStr:String, row:Int) <- rows.zipWithIndex
(char:Char, col:Int) <- rowStr.zipWithIndex
if chars.contains(char)
} yield new Cell(col, row)
def sizeOfMaze = {
val stringRows = pattern.split('\n')
(stringRows.head.length - 1, stringRows.length)
}

results.toSet
private def searchMaze(chars: Set[Char]) = {
val stringRows = pattern.split('\n')
(for {
(rowStr: String, row: Int) <- stringRows.zipWithIndex
(char: Char, col: Int) <- rowStr.zipWithIndex
if chars.contains(char)
} yield Cell(col, row)).toSet
}

}
Loading