RosettaCodeData/Task/Calendar/Scala/calendar-1.scala
Ingy döt Net 776bba907c Sync
2013-10-27 22:24:23 +00:00

153 lines
5.1 KiB
Scala

import java.util.{ Calendar, GregorianCalendar }
import language.postfixOps
import collection.mutable.ListBuffer
object CalendarPrint extends App {
val locd = java.util.Locale.getDefault()
val cal = new GregorianCalendar
val monthsMax = cal.getMaximum(Calendar.MONTH)
def JDKweekDaysToISO(dn: Int) = {
val nday = dn - Calendar.MONDAY
if (nday < 0) (dn + Calendar.THURSDAY) else nday
}
def daysInMonth(year: Int, monthMinusOne: Int): Int = {
cal.set(year, monthMinusOne, 1)
cal.getActualMaximum(Calendar.DAY_OF_MONTH)
}
def namesOfMonths() = {
def f1(i: Int): String = {
cal.set(2013, i, 1)
cal.getDisplayName(Calendar.MONTH, Calendar.LONG, locd)
}
(0 to monthsMax) map f1
}
def offsets(year: Int): List[Int] = {
val months = cal.getMaximum(Calendar.MONTH)
def get1stDayOfWeek(i: Int) = {
cal.set(year, i, 1)
cal.get(Calendar.DAY_OF_WEEK)
}
(0 to monthsMax).toList map get1stDayOfWeek map { i => JDKweekDaysToISO(i) }
}
def headerNameOfDays() = {
val mdow = cal.getDisplayNames(Calendar.DAY_OF_WEEK, Calendar.SHORT, locd) // map days of week
val it = mdow.keySet.iterator
val keySet = new ListBuffer[String]
while (it.hasNext) keySet += it.next
(keySet.map { key => (JDKweekDaysToISO(mdow.get(key)), key.take(2))
}.sortWith(_._1 < _._1) map (_._2)).mkString(" ")
}
def getGregCal(year: Int) = {
{
def dayOfMonth(month: Int) = new Iterator[(Int, Int)] {
cal.set(year, month, 1)
var ldom = 0
def next() = {
val res = (cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH))
ldom = res._2
cal.roll(Calendar.DAY_OF_MONTH, true)
res
}
def hasNext() = (cal.get(Calendar.DAY_OF_MONTH) > ldom)
}
var ret: List[(Int, Int)] = Nil
for (i <- 0 to monthsMax) ret = ret ++ (dayOfMonth(i).toSeq)
(ret, offsets(year))
}
}
def printCalendar(calendar: (List[(Int, Int)], List[Int]),
headerList: List[String] = Nil,
printerWidth: Int = 80) = {
val mw = 20 // month width
val gwf = 2 // gap width fixed
val gwm = 2 // gap width minimum
val fgw = true
val arr = Array.ofDim[String](6, 7)
def limits(printerWidth: Int): (Int, Int, Int, Int, Int) = {
val pw = if (printerWidth < 20) 20 else if (printerWidth > 300) 300 else printerWidth
// months side by side, gaps sum minimum
val (msbs, gsm) = {
val x1 = {
val c = if (pw / mw > 12) 12 else pw / mw
val a = (c - 1)
if (c * mw + a * gwm <= pw) c else a
} match {
case 5 => 4
case a if (a > 6 && a < 12) => 6
case other => other
}
(x1, (x1 - 1) * gwm)
}
def getFGW(msbs: Int, gsm: Int) = { val r = (pw - msbs * mw - gsm) / 2; (r, gwf, r) } // fixed gap width
def getVGW(msbs: Int, gsm: Int) = pw - msbs * mw - gsm match { // variable gap width
case a if (a < 2 * gwm) => (a / 2, gwm, a / 2)
case b => { val x = (b + gsm) / (msbs + 1); (x, x, x) }
}
// left margin, gap width, right margin
val (lm, gw, rm) = if (fgw) getFGW(msbs, gsm) else getVGW(msbs, gsm)
(pw, msbs, lm, gw, rm)
} // def limits(
val (pw, msbs, lm, gw, rm) = limits(printerWidth)
val monthsList = (0 to monthsMax).map { m => calendar._1.filter { _._1 == m } }
val nom = namesOfMonths()
val hnod = headerNameOfDays
def fsplit(list: List[(Int, Int)]): List[String] = {
def fap(p: Int) = (p / 7, p % 7)
for (i <- 0 until 6) for (j <- 0 until 7) arr(i)(j) = " "
for (i <- 0 until list.size)
arr(fap(i + calendar._2(list(i)._1))._1)(fap(i + calendar._2(list(i)._1))._2) =
f"${(list(i)._2)}%2d"
arr.toList.map(_.foldRight("")(_ + " " + _))
}
val monthsRows = monthsList.map(fsplit)
def center(s: String, l: Int): String = {
(if (s.size >= l) s
else " " * ((l - s.size) / 2) + s + " " * ((l - s.size) / 2) + " ").substring(0, l)
}
val maxMonths = monthsMax + 1
val rowblocks = (1 to maxMonths / msbs).map { i =>
(0 to 5).map { j =>
val lb = new ListBuffer[String]
val k = (i - 1) * msbs
(k to k + msbs - 1).map { l => lb += monthsRows(l)(j) }
lb
}
}
val mheaders = (1 to maxMonths / msbs).
map { i => (0 to msbs - 1).map { j => center(nom(j + (i - 1) * msbs), 20) } }
val dowheaders = (1 to maxMonths / msbs).
map { i => (0 to msbs - 1).map { j => center(hnod, 20) } }
headerList.foreach(xs => println(center(xs + '\n', pw)))
(1 to 12 / msbs).foreach { i =>
println(" " * lm + mheaders(i - 1).foldRight("")(_ + " " * gw + _))
println(" " * lm + dowheaders(i - 1).foldRight("")(_ + " " * gw + _))
rowblocks(i - 1).foreach { xs => println(" " * lm + xs.foldRight("")(_ + " " * (gw - 1) + _)) }
println
}
} // def printCal(
printCalendar(getGregCal(1969), List("[Snoopy Picture]", "1969"))
printCalendar(getGregCal(1582), List("[Snoopy Picture]", "1582"), printerWidth = 132)
}