Created
August 20, 2014 21:28
-
-
Save krishnanraman/56f7b0c4fbfd04427bed to your computer and use it in GitHub Desktop.
stuff for edwin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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