package sanguo.timesheet import helpers._ abstract class Project(val name: String, val rate: Int) case class BillableProject(override val name: String) extends Project(name, 1) case class SIPProject(override val name: String) extends Project(name, 0) case class Holiday() extends Project("休假", 0) class Level(val chargePerHour: Int) object Level { def apply(chargePerHour: Int) = new Level(chargePerHour) } class Consultant(val name: String, val level: Level) { def chargePerHour = level.chargePerHour } object Consultant { def apply(name: String, level: Level) = new Consultant(name, level) } class TimeSheetItem( val consultant: Consultant, val project: Project, mon: Int, tue: Int, wed: Int, thu: Int, fri: Int) { def working_hours = mon + tue + wed + thu + fri def charge = consultant.chargePerHour * project.rate * working_hours } object TimeSheetItem { def apply(c: Consultant, p: Project, mon: Int, tue: Int, wed: Int, thu: Int, fri: Int) = new TimeSheetItem(c, p, mon, tue, wed, thu, fri) } class Timesheet(val items: Set[TimeSheetItem]) { private var consultants = Set.empty[Consultant] private var projects = Set.empty[Project] items foreach { item => consultants += item.consultant projects += item.project } private val sum_hours = (total: Int, item: TimeSheetItem) => total + item.working_hours private val sum_charges = (total: Int, item: TimeSheetItem) => total + item.charge def total_hours(_filter: (TimeSheetItem => Boolean)): Int = { (0 /: (items filter _filter)) { sum_hours } } def total_charge(_filter: (TimeSheetItem => Boolean)): Int = { (0 /: (items filter _filter)) { sum_charges } } def print_report = { projects foreach { p => p match { case BillableProject(name) => { println("项目名称:" + name) println("咨询师\t工作时间\t应收费用") var hours_all = 0 var charge_all = 0 consultants foreach { c => val filter = c at p val hours = total_hours(filter) val charge = total_charge(filter) if (hours > 0) println(c.name + "\t" + hours + "\t" + charge) hours_all += hours charge_all += charge } println("总计:\t" + hours_all + "\t" + charge_all) } case Holiday() => { println("休假情况:") println("咨询师\t时间") var hours_all = 0 consultants foreach { c => val filter = c at p val hours = total_hours(filter) if (hours > 0) println(c.name + "\t" + hours) } println("总计:\t" + hours_all) } case SIPProject(name) => { println("项目名称:" + name + " - 公益项目") println("咨询师\t工作时间") var hours_all = 0 consultants foreach { c => val filter = c at p val hours_of_cons = total_hours(filter) hours_all += hours_of_cons if (hours_of_cons > 0) println(c.name + "\t" + hours_of_cons) } println("总计:\t" + hours_all) } } println("-------------------------------------------------") } } } object helpers { implicit def consultant2Helper(consultant: Consultant): Consultant2TimesheetItem = new Consultant2TimesheetItem(consultant) implicit def helper(name: String): String2Consultant = new String2Consultant(name) } class Consultant2TimesheetItem(consultant: Consultant) { def at(project: Project): (TimeSheetItem => Boolean) = { item: TimeSheetItem => item.consultant == consultant && item.project == project } } class String2Consultant(name: String) { def level(_level: Level) = { Consultant(name, _level) } } object Timesheet extends App { val junior = Level(chargePerHour = 1000) val senior = Level(chargePerHour = 2000) val 张飞 = "张飞" level junior val 关羽 = "关羽" level junior val 刘备 = "刘备" level senior val 赵云 = "赵云" level junior val 火烧赤壁 = BillableProject("火烧赤壁") val 七擒孟获 = BillableProject("七擒孟获") val 都江堰 = SIPProject("都江堰") val 休假 = Holiday() import sanguo.timesheet.{TimeSheetItem => Item} val timesheet = new Timesheet( Set( Item(张飞, 火烧赤壁, 8, 0, 0, 8, 4), Item(张飞, 七擒孟获, 0, 8, 8, 0, 0), Item(张飞, 休假, 0, 8, 8, 0, 0), Item(关羽, 都江堰, 8, 8, 8, 0, 0), Item(关羽, 火烧赤壁, 8, 8, 8, 0, 0), Item(刘备, 七擒孟获, 8, 8, 0, 8, 8), Item(刘备, 都江堰, 0, 0, 8, 0, 0), Item(赵云, 休假, 8, 8, 8, 8, 8))) timesheet print_report }