RosettaClock.scala

import java.util.Calendar; 
 
// setup - called once 
override def setup() { 
  size(400,400) 
  textFont(loadFont("CourierNew36.vlw")) 
} 
 
// draw - called every frame 
override def draw() { 
  background(180,180,160) 
 
  val c = Calendar.getInstance 
  val h = c.get(Calendar.HOUR_OF_DAY) 
  val m = c.get(Calendar.MINUTE) 
  val s = c.get(Calendar.SECOND) 
 
  val x1 = 120 
  val x2 = 260 
  val x3 = 400 
  var y = 50; 
  val b1 = new Binary(h, 5).draw(g, x1, y); 
  val b2 = new Binary(m, 6).draw(g, x2, y); 
  val b3 = new Binary(s, 6).draw(g, x3, y); 
 
  y = 125 
  val s1 = new SkewBinary(h, 4).draw(g, x1, y); 
  val s2 = new SkewBinary(m, 5).draw(g, x2, y); 
  val s3 = new SkewBinary(s, 5).draw(g, x3, y); 
 
  y = 200 
  val t1 = new Ternary(h, 3).draw(g, x1, y); 
  val t2 = new Ternary(m, 4).draw(g, x2, y); 
  val t3 = new Ternary(s, 4).draw(g, x3, y); 
 
  y = 275 
  val y1 = new BalancedTernary(h, 4).draw(g, x1, y); 
  val y2 = new BalancedTernary(m, 5).draw(g, x2, y); 
  val y3 = new BalancedTernary(s, 5).draw(g, x3, y); 
 
  y = 350 
  val d1 = new Decimal(h, 2).draw(g, x1, y); 
  val d2 = new Decimal(m, 2).draw(g, x2, y); 
  val d3 = new Decimal(s, 2).draw(g, x3, y); 
} 
 
class Dot(x: int, y: int, c: int) { 
 
  def draw(pg: processing.core.PGraphics) { 
    if (c == 0) 
      pg.fill(128,128,128); 
 
    else if (c == 1) 
      pg.fill(0,255,0); 
 
    else if (c == 2) 
      pg.fill(0,0,255); 
 
    else if (c == -1) 
      pg.fill(255,0,0) 
 
    pg.ellipse(x, y, 16, 16); 
  } 
} 
 
// Class which draws a number as a series of binary bits 
// @param v The number 
// @param n The number of digits 
class Binary(v: int, n: int) { 
  var bits = for (i <- 0 to n-1) yield bitColor(0 != (v & (1<<i))); 
 
  def draw(pg: processing.core.PGraphics, x: int, y: int) { 
    for (i <- 1 to n) { 
      val d = new Dot(x-20*i,y,bits(i-1)); 
      d.draw(pg) 
    } 
  } 
 
  def bitColor(b: Boolean) = b match { 
    case true => 1 
    case false => 0 
  } 
} 
 
// Class which draws a number as a series of skew binary trits 
// @param v The number 
// @param n The number of digits 
class SkewBinary(v: int, n: int) { 
  var trits = toTrits(v, n) 
 
  def draw(pg: processing.core.PGraphics, x: int, y: int) { 
    for (i <- 1 to n) { 
      val d = new Dot(x-20*i,y,trits(i-1)); 
      d.draw(pg) 
    } 
  } 
 
  def toTrits(v: Int, n: Int): List[Int] = { 
    var trits: List[Int] = List() 
    var remainder = v; 
    for (i <- 0 until n) { 
      val p = (1<<(n - i)) - 1 
      if (remainder >= 2*p) { 
        trits = trits ++ List(2) 
        remainder -= 2*p 
      } 
      else if (remainder >= p) { 
        trits = trits ++ List(1) 
        remainder -= p; 
      } 
      else { 
        trits = trits ++ List(0) 
      } 
    } 
    trits.reverse 
  } 
} 
 
// Class which draws a number as a series of ternary trits 
// @param v The number 
// @param n The number of digits 
class Ternary(v: int, n: int) { 
  var trits = for (i <- 0 to n-1) yield trit(v, i); 
 
  def draw(pg: processing.core.PGraphics, x: int, y: int) { 
    for (i <- 1 to n) { 
      val d = new Dot(x-20*i,y,trits(i-1)); 
      d.draw(pg) 
    } 
  } 
 
  def trit(v: Int, n: Int) = { 
    val t = v / Math.pow(3,n) 
    val x = t.toInt 
    x % 3 
  } 
} 
 
// Class which draws a number as a series of balanced ternary trits 
// 
// Ported from http://blog.garritys.org/2009/07/balanced-ternary-in-matlab.html 
// 
// @param v The number 
// @param n The number of digits 
class BalancedTernary(v: int, n: int) { 
  var trits = toTrits(v, n) 
 
  def draw(pg: processing.core.PGraphics, x: int, y: int) { 
    for (i <- 1 to n) { 
      val d = new Dot(x-20*i,y,trits(i-1)); 
      d.draw(pg) 
    } 
  } 
 
  def abs(v: Int) = if (v>=0) v else -v 
 
  def toTrits(v: Int, n: Int): List[Int] = { 
    var trits: List[Int] = List() 
    var target = v; 
 
    var tpos = 0 
    var value = 1; 
    var goal = abs(2*target); 
    while ((value<goal) && (tpos<10000)) { 
      value = 3*value; 
      tpos += 1; 
    } 
    if (target < 0) { 
      value = -value; 
    } 
    while (tpos >= 0) { 
      if (abs(target-value) < abs(target)) { 
        if (value > 0) { 
          trits = trits ++ List(1) 
          target = target-value; 
        } 
        else { 
          trits = trits ++ List(-1) 
          target = target-value; 
        } 
      } 
      else { 
        trits = trits ++ List(0) 
      } 
      value = value/3; 
      tpos -= 1 
      if ((target*value) < 0) { 
        value = -value; 
      } 
    } 
    // pad out with leading 0's 
    var i=trits.length 
    while (i < n) { 
      trits = 0 :: trits 
      i += 1 
    } 
    trits.reverse 
  } 
} 
 
// Class which draws a number as a series of decimal digits 
// @param v The number 
// @param n The number of digits 
class Decimal(v: int, n: int) { 
  var digits = for (i <- 0 to n-1) yield digit(v, i); 
 
  def draw(pg: processing.core.PGraphics, x: int, y: int) { 
    pg.fill(0,0,0) 
    for (i <- 1 to n) { 
      pg.text(digits(i-1).toString,x-20*i - 20,y) 
    } 
  } 
 
  def digit(v: Int, n: Int) = { 
    val t = v / Math.pow(10,n) 
    val x = t.toInt 
    x % 10 
  } 
}