ruling_timer/app/models/ruling_timer_history.rb

170 lines
6.3 KiB
Ruby
Raw Normal View History

2021-07-21 07:37:06 +00:00
class RulingTimerHistory
include Mongoid::Document
include Mongoid::Timestamps
field :work_time_str, type: String, default: "00:00:00"
field :rest_time_str, type: String, default: "00:00:00"
field :all_work_times_seconds, type: Integer, default: 0
field :all_rest_times_seconds, type: Integer, default: 0
field :work_times, type: Array, default: []
field :rest_times, type: Array, default: []
field :sub_task_ids, type: Array, default: [] #store RulingTimerSubTask id
field :tasks, type: Array, default: [] #store name only
field :tasks_finished, type: Array, default: [] #store index only
field :summary, type: String, default: ""
field :time_offset, type: String, default: "+8"
field :events, type: Array, default: []
field :date, type: String, default: ""
belongs_to :user
def fix_work_times(store=true)
time_now = DateTime.now.utc
work_times_range = self.work_times.each_slice(2).to_a.map{|a,b| convert_datetime(a)..(b.nil? ? time_now : convert_datetime(b))}
work_times_range = eliminate_intersection(work_times_range)
new_work_times_range = merge_ranges(work_times_range.uniq).flat_map{|range| [range.first,range.last]}
new_work_times_range = new_work_times_range[0...-1] if new_work_times_range.last == time_now
self.work_times = new_work_times_range
self.calc("work_times",false,true)
self.work_time_str = transform_second_to_time(self.all_work_times_seconds)
self.save if store
self.work_times
end
def merge_work_times(new_work_times,store=true)
time_now = DateTime.now.utc
work_times_range = self.work_times.each_slice(2).to_a.map{|a,b| convert_datetime(a)..(b.nil? ? time_now : convert_datetime(b))}
new_work_times_range = new_work_times.each_slice(2).to_a.map{|a,b| convert_datetime(a)..(b.nil? ? time_now : convert_datetime(b))}
work_times_range = eliminate_intersection(work_times_range)
new_work_times_range = eliminate_intersection(new_work_times_range)
new_work_times_range = work_times_range + new_work_times_range
new_work_times_range = eliminate_intersection(new_work_times_range).sort_by{|range| range.first.to_i}
new_work_times_range = merge_ranges(new_work_times_range.uniq).flat_map{|range| [range.first,range.last]}
new_work_times_range = new_work_times_range[0...-1] if new_work_times_range.last == time_now
self.work_times = new_work_times_range
self.calc("work_times",false,true)
self.work_time_str = transform_second_to_time(self.all_work_times_seconds)
self.save if store
self.work_times
end
def merge_ranges(ranges)
(0...(ranges.count)).each do |i|
next if ranges[i+1].nil?
if ranges[i].last == ranges[i+1].first
ranges[i+1] = (ranges[i].first .. ranges[i+1].last)
ranges[i] = nil
end
end
ranges.compact
end
def eliminate_intersection(times_range)
times_range = times_range.sort_by{|range| range.first.to_i}
times_range.each_with_index do |range,i|
next if range.nil?
intersects = times_range[i+1..-1].map{|r| range & r}
if intersects.compact.count != 0
intersects.each_with_index do |intersect,j|
next if intersect.nil?
if range.last > intersect.last #overlap all
times_range[i+1+j] = nil
else
if range.first == intersect.first
times_range[i] = nil
else
times_range[i] = (range.first..intersect.first)
end
end
end
end
end
times_range.compact
end
def update_task_name(task_id,new_name)
idx = self.sub_task_ids.index(task_id)
self.tasks[idx] = new_name
self.save
end
def remove_task(task_id)
sub_task = RulingTimerSubTask.find(task_id) rescue nil
idx = self.sub_task_ids.index(task_id)
self.sub_task_ids.delete(task_id)
self.tasks.delete_at(idx)
self.tasks_finished = self.tasks_finished.to_a.map do |task_idx|
if task_idx == idx
nil
elsif task_idx > idx
task_idx - 1
else
task_idx
end
end.compact
self.save!
sub_task.stop if sub_task
end
def get_work_times(display_seond=false)
work_times = self.work_times.clone
if display_seond
time_format = "%H:%M:%S"
else
time_format = "%H:%M"
end
work_times.map!{|t| convert_datetime(t).new_offset(self.time_offset).strftime(time_format)}
end
def convert_datetime(time)
if time.class == Time
return time.to_datetime
elsif time.class == DateTime
return time
elsif time.class == String
return DateTime.parse(time)
else
return Time.at(time).to_datetime #time is seconds
end
end
def get_infos
return {"work" => self.work_time_str, "rest" => self.rest_time_str}
end
def calc(field_name,padding=true,recalc=false)
time_infos = self.send(field_name).clone rescue []
record_field_name = "all_#{field_name}_seconds"
tmp_seconds = self.send(record_field_name)
all_seconds = 0
start_index = 0
if !recalc
all_seconds = tmp_seconds
start_index = time_infos.count - 1
start_index -= (start_index % 2)
time_infos = time_infos[start_index..-1].to_a
end
time_infos.push(DateTime.now.utc) if (padding && time_infos.count % 2 == 1)
time_infos.each_with_index do |t,i|
if i % 2 == 0
next_t = time_infos[i+1]
if !next_t.nil?
all_seconds += ((convert_datetime(next_t) - convert_datetime(t)) * 1.day).round
else
break
end
end
end
self.send("#{record_field_name}=",all_seconds)
return all_seconds
end
def recalc_all
self.calc("work_times",false,true)
self.calc("rest_times",false,true)
self.work_time_str = transform_second_to_time(self.all_work_times_seconds)
self.rest_time_str = transform_second_to_time(self.all_rest_times_seconds)
self.save
return self.to_json
end
def getPaddedComp(comp)
return ((comp.to_i < 10) ? ('0' + comp.to_s) : comp.to_s)
end
def transform_second_to_time(seconds)
seconds = 0 if seconds.nil?
hour = 3600
minute = 60
total_hour = getPaddedComp(seconds / hour)
rest_seconds = seconds % hour
total_minute = getPaddedComp(rest_seconds / minute)
total_second = getPaddedComp(rest_seconds % minute)
return (total_hour + ":" + total_minute + ":" + total_second)
end
end