From: PHO Date: Fri, 10 Oct 2014 03:48:18 +0000 (+0900) Subject: new tsv X-Git-Url: https://git.cielonegro.org/gitweb.cgi?a=commitdiff_plain;h=cb226bf20b21a6ebc1213152f96e7bcd465cda9d;p=task-reporter.git new tsv --- diff --git a/build.sbt b/build.sbt index f92aaa8..922e0ee 100644 --- a/build.sbt +++ b/build.sbt @@ -8,11 +8,11 @@ libraryDependencies <+= libraryDependencies += "org.scala-tools.sbinary" %% "sbinary" % "0.4.2" -/* There is also manual dependencies in ./lib: - * - * - JCalendar - */ +// There is also manual dependencies in ./lib: +// +// - JCalendar +// -scalacOptions ++= Seq("-deprecation", "-unchecked", "-encoding", "UTF-8") +scalacOptions ++= Seq("-deprecation", "-unchecked", "-encoding", "UTF-8", "-feature") assemblySettings diff --git a/src/main/scala/jp/ymir/taskReporter/core/Report.scala b/src/main/scala/jp/ymir/taskReporter/core/Report.scala index e147e66..1963b6c 100644 --- a/src/main/scala/jp/ymir/taskReporter/core/Report.scala +++ b/src/main/scala/jp/ymir/taskReporter/core/Report.scala @@ -35,22 +35,22 @@ class Report(private val _date: Calendar) extends AbstractTableModel { column match { case 0 => "チケットID" case 1 => "作業名" - case 2 => "仮期限" - case 3 => "期限" + case 2 => "作業完了予定年月日" + case 3 => "タスク期限" case 4 => "状態" - case 5 => "補足" + case 5 => "説明" } } def getValueAt(row: Int, column: Int) : Object = { val task = _tasks(row) column match { - case 0 => task.ticketID : Integer + case 0 => task.ticketID.map(_.toString).getOrElse("") case 1 => task.title - case 2 => task.tentativeDeadline.map(dateString).getOrElse("") - case 3 => task.deadline .map(dateString).getOrElse("") + case 2 => dateString(task.expectedCompletionDate) + case 3 => task.deadline.map(dateString).getOrElse("") case 4 => task.status - case 5 => task.supplement + case 5 => task.description.getOrElse("") } } } diff --git a/src/main/scala/jp/ymir/taskReporter/core/ReportSet.scala b/src/main/scala/jp/ymir/taskReporter/core/ReportSet.scala index 6285589..66a5d6d 100644 --- a/src/main/scala/jp/ymir/taskReporter/core/ReportSet.scala +++ b/src/main/scala/jp/ymir/taskReporter/core/ReportSet.scala @@ -16,9 +16,23 @@ class ReportSet(private var _file: Option[File]) _file.foreach { file => load(file) } def load(file: File) { + import Task._ + var reports = _reports.empty val src = Source.fromFile(file, "UTF-8") + TSV.decode(src.mkString).foreach { task => + if (reports.isDefinedAt(task.date)) { + reports(task.date) += task + } + else { + val report = new Report(task.date) + report += task + reports += (report.date -> report) + } + } + +/* for (line <- src.getLines) { if (!line.isEmpty) { val task = new Task(line) @@ -32,6 +46,7 @@ class ReportSet(private var _file: Option[File]) } } } + */ _file = Some(file) _reports = reports diff --git a/src/main/scala/jp/ymir/taskReporter/core/TSV.scala b/src/main/scala/jp/ymir/taskReporter/core/TSV.scala new file mode 100644 index 0000000..28d9833 --- /dev/null +++ b/src/main/scala/jp/ymir/taskReporter/core/TSV.scala @@ -0,0 +1,56 @@ +package jp.ymir.taskReporter.core +import scala.collection._ +import scala.collection.immutable.StringLike + +object TSV { + type Header = Seq[Symbol] + type Field = String + type Record = Map[Symbol, Field] + + def decode[A: FromRecord](tsv: StringLike[_]): Seq[A] = { + val lines = tsv.split('\n').filter(!_.isEmpty) + val header = lines.head.split('\t').map(Symbol(_)) + val body = lines.tail.map(line => (header zip line.split('\t')).toMap) + return body.map(implicitly[FromRecord[A]].parseRecord) + } + + trait FromRecord[A] { + def parseRecord(r: Record): A + } + + trait FromField[A] { + def parseField(f: Field): A + } + def parseField[A: FromField](f: Field): A + = implicitly[FromField[A]].parseField(f) + + trait ToRecord[A] { + def toRecord(a: A): Record + } + + trait ToField[A] { + def toField(a: A): Field + } + + // Option[A] + implicit def OptionFromField[A: FromField] = new FromField[Option[A]] { + def parseField(f: Field): Option[A] = { + if (f.isEmpty) { + return None + } + else { + return Some(implicitly[FromField[A]].parseField(f)) + } + } + } + + // String + implicit def StringFromField = new FromField[String] { + def parseField(f: Field): String = f + } + + // Int + implicit def IntFromField = new FromField[Int] { + def parseField(f: Field): Int = f.toInt + } +} diff --git a/src/main/scala/jp/ymir/taskReporter/core/Task.scala b/src/main/scala/jp/ymir/taskReporter/core/Task.scala index 7b38e0a..53e813d 100644 --- a/src/main/scala/jp/ymir/taskReporter/core/Task.scala +++ b/src/main/scala/jp/ymir/taskReporter/core/Task.scala @@ -3,6 +3,63 @@ import java.util.Calendar import java.util.GregorianCalendar import scala.util.matching.Regex +case class Task( + date: Calendar, + ticketID: Option[Int], + title: String, + expectedCompletionDate: Calendar, + deadline: Option[Calendar], + status: Task.Status, + description: Option[String] +) + +object Task { + import TSV._ + + sealed abstract class Status + object Status { + case object DoingFine extends Status + case object Lagging extends Status + case object DeadlineChanged extends Status + case object Completed extends Status + } + + implicit def CalendarFromField = new FromField[Calendar] { + val pattern = """^(\d{4})/(\d{2})/(\d{2})$""".r + + def parseField(f: Field): Calendar = { + f match { + case pattern(year, month, day) => + new GregorianCalendar(year.toInt, month.toInt, day.toInt) + } + } + } + + implicit def StatusFromField = new FromField[Status] { + def parseField(f: Field): Status = f match { + case "順調" => Status.DoingFine + case "遅延" => Status.Lagging + case "期限変更" => Status.DeadlineChanged + case "完了" => Status.Completed + } + } + + implicit def TaskFromRecord = new FromRecord[Task] { + def parseRecord(r: Record): Task = { + return Task( + date = parseField[Calendar](r('報告日)), + ticketID = parseField[Option[Int]](r('チケットID)), + title = parseField[String](r('作業名)), + expectedCompletionDate = parseField[Calendar](r('作業完了予定年月日)), + deadline = parseField[Option[Calendar]](r('タスク期限)), + status = parseField[Status](r('状態)), + description = parseField[Option[String]](r('説明)) + ) + } + } +} + +/* class Task(tsvLine: String) { sealed abstract class Status object Status { @@ -88,3 +145,4 @@ class Task(tsvLine: String) { } } } + */