Skip to content

Instantly share code, notes, and snippets.

@krishnanraman
Created August 20, 2014 21:28
Show Gist options
  • Save krishnanraman/56f7b0c4fbfd04427bed to your computer and use it in GitHub Desktop.
Save krishnanraman/56f7b0c4fbfd04427bed to your computer and use it in GitHub Desktop.
stuff for edwin
package example
import scala.scalajs.js
import js.annotation.JSExport
import org.scalajs.dom
import scala.util.Random
import scala.math.{sin, Pi}
object BarAndPieChart extends js.JSApp {
val H = 3000
val W = 1000
val ctx = dom.document
.getElementById("canvas")
.asInstanceOf[dom.HTMLCanvasElement]
.getContext("2d")
.asInstanceOf[dom.CanvasRenderingContext2D]
def mkcolor = {
val colors = Seq("#5DA5DA","#FAA43A","#60BD68","#F17CB0","#B2912F","#B276B2","DECF3F","#F15854",
"khaki", "aliceblue", "salmonblue", "mistyrose", "mocassin", "tan", "rosybrown", "royalblue", "sandybrown",
"sienna", "dodgerblue", "orange", "orchid", "hotpink", "crimson")
Random.shuffle(colors).head
}
def main(): Unit = {
val summary:String = dom.document.getElementById("playground").textContent
val items = summary
.replaceAll("[^a-z._A-Z0-9\\s]", " ")
.split("\\s+")
.map{_.trim}
.filter{_.size > 0}
.grouped(3)
.toSeq
// debug
items.zipWithIndex.foreach(item => println(item._2 + ":" + item._1.mkString(" ")))
//draw
drawBG
drawBarChart(items)
drawCumulativeBar(items)
drawPie(items)
dom.setInterval(() => animateBarChart(items), 200)
}
def drawBG = {
ctx.rect(0, 0, W-2,H-2)
// add linear gradient
val grd = ctx.createLinearGradient(0, 0, W-2,H-2);
// light blue
grd.addColorStop(1, "#000000")
// dark blue
grd.addColorStop(0, "#4D4D4D")
// light blue
ctx.fillStyle = grd
ctx.fill()
}
def drawBarChart(items: Seq[Array[String]]) = {
val M = 30
items.zipWithIndex.foreach { itemIdx =>
val (item,idx) = itemIdx
val size = item(0).toDouble
val name = item(2)
ctx.beginPath()
ctx.fillStyle = mkcolor
ctx.rect(0, 20*idx, (M*size).toInt, 18)
ctx.fill()
ctx.lineWidth = 2
ctx.strokeStyle = "black"
ctx.stroke()
ctx.fillStyle = "limegreen"
ctx.fillText(name + ": " + size + "%", M*size.toInt + 40, 15 + 20*idx)
}
}
var i = 0
def animateBarChart(items: Seq[Array[String]]) = {
val M = 30
if(i >= items.size) { i = 0 }
val item = items(i)
val size = item(0).toDouble
val name = item(2)
ctx.beginPath()
ctx.fillStyle = mkcolor
ctx.rect(0, 20*i, (M*size).toInt, 18)
ctx.fill()
ctx.lineWidth = 2
ctx.strokeStyle = "black"
ctx.stroke()
i = i+1
}
def drawCumulativeBar (items: Seq[Array[String]]) = {
val M = 7
val h = 1600
ctx.fillStyle = "limegreen"
ctx.font = "normal 14pt Lucinda Sans Typewriter"
ctx.fillText("Services Cumulative Bar", 300, 1580)
ctx.font = "normal 10pt Lucinda Sans Typewriter"
(0 to 100 by 10).foreach { scale =>
val w = (M*scale).toInt
ctx.beginPath()
ctx.lineWidth = 1
ctx.rect(10+ scale*M, h-4, 2, 26)
ctx.strokeStyle = "white"
ctx.stroke()
ctx.fillText(scale+"", scale*M, h+30)
}
var prev = 10
items.zipWithIndex.foreach { itemIdx =>
val (item,idx) = itemIdx
val size = item(0).toDouble
val name = item(2)
val w = (M*size).toInt
ctx.beginPath()
ctx.fillStyle = mkcolor
ctx.rect(prev, h, w, 20)
ctx.fill()
ctx.lineWidth = 1
ctx.strokeStyle = "black"
ctx.stroke()
prev += w
//ctx.fillStyle = "limegreen"
//ctx.fillText(name + ": " + size + "%", M*size.toInt + 40, 15 + 20*idx)
}
val cumsum = items.scanLeft(0.0){ (a,b) => a + b(0).toDouble}.tail
/* in:
0 28
1 32
2 45
out:
0 10
0 20
1 30
2 40
3 50
*/
val servicesperdecile = (10 to 100 by 10).toSeq.map {
num => (num, cumsum.filter{ x=> x <= num }.size)
}
ctx.fillStyle = "limegreen"
servicesperdecile.zipWithIndex.foreach { decileCountIdx =>
val (decileCount, idx) = decileCountIdx
val (decile, count) = decileCount
val str = "%d services export %d percent of stats".format(count, decile)
ctx.fillText(str, 20, h+50+idx*20)
}
}
def drawPie (items: Seq[Array[String]]) = {
val M = 7
val h = 2000
val (rx, ry, r) = (300,2100,200)
ctx.fillStyle = "limegreen"
ctx.font = "normal 14pt Lucinda Sans Typewriter"
ctx.fillText("Services Pie", 300, 1870)
val cumsum = items.scanLeft(0.0){ (a,b) => a + b(0).toDouble}
def degree2radians(d:Double) = d*math.Pi*2/100.0
cumsum.zip(cumsum.tail).foreach {
x =>
val (start, end) = x
val stheta = degree2radians(start)
val etheta = degree2radians(end)
println(stheta + "," + etheta)
ctx.beginPath
ctx.fillStyle = mkcolor
ctx.moveTo(rx,ry)
ctx.lineTo( rx + r*math.cos(stheta),ry+r*math.sin(stheta) )
ctx.arc(rx, ry, r, stheta, etheta)
ctx.moveTo(rx,ry)
ctx.lineTo( rx + r*math.cos(etheta),ry+r*math.sin(etheta) )
ctx.fill()
ctx.closePath
}
}
}
package example
import scala.scalajs.js
import js.annotation.JSExport
import org.scalajs.dom
import scala.util.Random
import scala.math.{sin, Pi}
object LineChart extends js.JSApp {
val H = 600
val W = 900
var XMAX = 0.0
var YMAX = 0.0
val ctx = dom.document
.getElementById("canvas")
.asInstanceOf[dom.HTMLCanvasElement]
.getContext("2d")
.asInstanceOf[dom.CanvasRenderingContext2D]
ctx.translate(0.5, 0.5)
def main(): Unit = {
val div = dom.document.getElementById("data")
val data:String = div.getAttribute("data-row")
val model:String = div.getAttribute("data-linearmodel")
val arr = data.trim.split("\t")
println(arr.size)
val name = arr(0)
val points:Seq[(Double,Double)] = arr(1).trim
.drop(5) // get rid of List(
.replace("(", "")
.replace(")", "")
.split(",")
.grouped(2)
.toSeq
.map{ case Array(x,y) => (x.trim.toDouble,y.trim.toDouble) }
val marr = model.trim
.drop(5) // get rid of List(
.replace("(", "")
.replace(")", "")
.split(",")
val (intercept, slope) = (marr(0).trim.toDouble, marr(1).trim.toDouble)
computeMax(points)
drawBG
drawGrid
drawScatter(scale(points, XMAX, YMAX), "hotpink", "pink", 3)
drawModel(intercept, slope)
}
def computeMax(points:Seq[(Double,Double)]) = {
val res = Seq(
points.map{ case(x,y) => x}.max * 1.5,
points.map{ case(x,y) => y}.max * 1.5
)
.map { pt =>
(math.round(pt/10.0)).toInt * 10.0 // get closest multiple of 10
}
XMAX = res(0)
YMAX = res(1)
}
def drawBG = {
ctx.rect(0, 0, W-2,H-2)
ctx.fillStyle = "black"
ctx.fill()
}
def scale(points: Seq[(Double,Double)], xScaler:Double = 1.0, yScaler:Double = 1.0) : Seq[(Int,Int)] =
points.map { pt => scale(pt,xScaler, yScaler) }
def scale(points: (Double,Double), xScaler:Double, yScaler:Double) : (Int,Int) = {
val (xx,yy) = points
val scaleX = (W-20)/xScaler
val scaleY = (H-20)/yScaler
(20 + (xx * scaleX).toInt, H - 20 - (yy * scaleY).toInt)
}
def drawModel(intercept:Double, slope:Double) = {
val pts = Seq(1.0,XMAX).map {
x =>
val y = intercept + slope * x
println(x+ ":" + y)
(x,y)
}
drawLine( pts(0), pts(1), XMAX, YMAX, "limegreen")
}
def drawGrid = {
val xgrid = XMAX/10.0
val xlines = (0.0 until XMAX by xgrid).foreach { x=>
val fromxy = (x,0.0)
val toxy = (x, YMAX)
drawLine( fromxy, toxy, XMAX, YMAX, "gray")
drawText(x+"", "khaki", (x, 0))
}
val ygrid = YMAX/10.0
val ylines = (0.0 to YMAX by ygrid).foreach { y=>
val fromxy = (0.0,y + 0.0)
val toxy = (XMAX,y + 0.0)
drawLine( fromxy, toxy, XMAX, YMAX, "gray")
if( y!= 0.0) drawText(y+"", "khaki", (XMAX-5, y))
}
}
def drawText(str:String, color:String, xy:(Double,Double)) = {
ctx.beginPath
ctx.fillStyle = color
val (x,y) = scale(xy, XMAX, YMAX)
ctx.fillText(str, x-10,y+10)
ctx.closePath
}
def drawLine( fromxy:(Double, Double),
toxy:(Double, Double),
xScaler:Double,
yScaler:Double,
lineColor:String) = {
ctx.strokeStyle =lineColor
ctx.lineWidth = 1
ctx.beginPath
val (x1,y1) = scale(fromxy, XMAX, YMAX)
val (x2,y2) = scale(toxy, XMAX, YMAX)
ctx.moveTo(x1,y1)
ctx.lineTo(x2,y2)
ctx.stroke
ctx.closePath
}
def drawScatter(pts: Seq[(Int,Int)], fillStyle:String, strokeStyle:String, scatterSize:Int) = {
ctx.fillStyle = fillStyle
ctx.strokeStyle = strokeStyle
ctx.lineWidth = 1
ctx.beginPath
pts.zip(pts.tail).foreach{ pt=>
val (pt1,pt2) = pt
val (x1,y1) = pt1
val (x2,y2) = pt2
ctx.moveTo(x1,y1)
ctx.lineTo(x2,y2)
ctx.stroke
}
ctx.closePath
pts.foreach{ pt=>
val (x,y) = pt
ctx.beginPath
ctx.arc(x, y, scatterSize, 0, 2 * math.Pi)
ctx.fill()
ctx.closePath
println(pt)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment