From 18b2bd5b01c795f050d16cab86943694db0968de Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Mon, 4 Nov 2019 20:53:31 +0300 Subject: [PATCH] Add remaining time calculation --- spec/profile_spec.cr | 42 +++++++++++++++++++++++++++++++++++++- spec/spec_helper.cr | 2 +- src/dayoff/entities.cr | 46 ++++++++++++++++++++++++++++++++++++++++-- src/dayoff/profile.cr | 36 ++++++++++++++++++++------------- 4 files changed, 108 insertions(+), 18 deletions(-) diff --git a/spec/profile_spec.cr b/spec/profile_spec.cr index 2688027..343fddf 100644 --- a/spec/profile_spec.cr +++ b/spec/profile_spec.cr @@ -3,11 +3,30 @@ require "./spec_helper" module Dayoff::Test extend self + def d(day) + location = Time::Location.load("Europe/Moscow") + Time.local(2019, 1, day, location: location) + end + def t(day, hour, min = 0) location = Time::Location.load("Europe/Moscow") Time.local(2019, 1, day, hour, min, location: location) end + def create_profile + storage = MemoryStorage.new + storage.set_planned_dates [ + PlannedDate.new(d(1), 8), + PlannedDate.new(d(2), 8), + PlannedDate.new(d(3), 8), + ] + storage.set_work_records [ + WorkRecord.new(t(1, 10), t(1, 20)), + WorkRecord.new(t(2, 10), t(2, 20)), + ] + Profile.new(storage) + end + describe Profile do it "can calc work hours" do storage = MemoryStorage.new @@ -15,7 +34,7 @@ module Dayoff::Test WorkRecord.new(t(1, 10), t(1, 20)), ] prof = Profile.new(storage) - prof.get_work_hours.should eq 10 + prof.get_work_hours(t(2, 0)).total_hours.should eq 10 end it "can write new record" do @@ -44,5 +63,26 @@ module Dayoff::Test records.size.should eq 2 records.last.finish_time.should eq finish_time end + + it "can calc planned hours" do + prof = create_profile + s = prof.get_planned_hours t(3, 12) + expected = 8 * 3 + expected.should eq s.total_hours + end + + it "can calc work hours" do + prof = create_profile + s = prof.get_work_hours t(3, 12) + expected = 10 * 2 + expected.should eq s.total_hours + end + + it "can calc remaining time" do + prof = create_profile + s = prof.remaining_time t(3, 12) + expected = 8 * 3 - 10 * 2 + expected.should eq s.total_hours + end end end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 1527d2f..7365a7d 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -1,2 +1,2 @@ require "spec" -require "../src/**" +require "../src/dayoff/**" diff --git a/src/dayoff/entities.cr b/src/dayoff/entities.cr index 5572993..6cddd54 100644 --- a/src/dayoff/entities.cr +++ b/src/dayoff/entities.cr @@ -6,6 +6,22 @@ module Dayoff date: String, hours: Int32, ) + + FORMAT = "%Y-%m-%d" + + def initialize(date : Time, hours : Int32) + @date = date.to_s FORMAT + @hours = hours + end + + def date_time : Time + location = Time::Location.load("Europe/Moscow") + Time.parse(@date, FORMAT, location) + end + + def time_span : Time::Span + Time::Span.new(hours: hours, minutes: 0, seconds: 0) + end end class WorkRecord @@ -26,12 +42,12 @@ module Dayoff def start_time : Time location = Time::Location.load("Europe/Moscow") - Time.parse(start, FORMAT, location) + Time.parse(@start, FORMAT, location) end def finish_time : Time location = Time::Location.load("Europe/Moscow") - Time.parse(finish.as(String), FORMAT, location) + Time.parse(@finish.as(String), FORMAT, location) end def finish_time=(v : Time) @@ -41,5 +57,31 @@ module Dayoff def started? : Bool @finish.nil? end + + def finished? : Bool + !@finish.nil? + end + + def finished_to_time?(time : Time) : Bool + @finish && finish_time <= time + end + + def calc_span(time : Time) : Time::Span + if @finish.nil? + if start_time <= time + time - start_time + else + Time::Span.zero + end + else + if time > finish_time + finish_time - start_time + elsif time > start_time + time - start_time + else + Time::Span.zero + end + end + end end end diff --git a/src/dayoff/profile.cr b/src/dayoff/profile.cr index e893597..be8339c 100644 --- a/src/dayoff/profile.cr +++ b/src/dayoff/profile.cr @@ -19,22 +19,24 @@ module Dayoff @wrecords = @storage.get_work_records end - def get_planned_hours - sum = 0 - @pdates.each do |wd| - sum += wd.hours - end - sum - end - - def get_work_hours - @wrecords.reduce 0 do |acc, wr| - diff = wr.finish_time - wr.start_time - acc + diff.total_hours.to_i32 + def get_planned_hours(on_time : Time) : Time::Span + check_date = on_time.at_beginning_of_day + @pdates.reduce(Time::Span.zero) do |acc, wd| + if wd.date_time <= check_date + acc + wd.time_span + else + acc + end end end - def start(time : Time) + def get_work_hours(on_time : Time) : Time::Span + @wrecords.reduce(Time::Span.zero) do |acc, wr| + acc + wr.calc_span on_time + end + end + + def start(time : Time) : Nil @wrecords.each do |wr| if time <= wr.start_time || time <= wr.finish_time raise CrossedTimeSpan.new @@ -45,7 +47,7 @@ module Dayoff @storage.set_work_records @wrecords end - def finish(time : Time) + def finish(time : Time) : Nil started = @wrecords.find { |x| x.started? } if started.nil? raise StartedRecordNotFound.new @@ -53,5 +55,11 @@ module Dayoff started.finish_time = time @storage.set_work_records @wrecords end + + def remaining_time(on_time : Time) : Time::Span + planned = get_planned_hours on_time + worked = get_work_hours on_time + planned - worked + end end end