diff options
| -rw-r--r-- | app/controllers/time_tables_controller.rb | 2 | ||||
| -rw-r--r-- | app/models/chouette/time_table.rb | 80 | ||||
| -rw-r--r-- | spec/models/chouette/time_table_spec.rb | 29 | ||||
| -rw-r--r-- | spec/models/time_table_combination_spec.rb | 22 |
4 files changed, 81 insertions, 52 deletions
diff --git a/app/controllers/time_tables_controller.rb b/app/controllers/time_tables_controller.rb index 8ece4c8ae..b0f346c5c 100644 --- a/app/controllers/time_tables_controller.rb +++ b/app/controllers/time_tables_controller.rb @@ -35,7 +35,7 @@ class TimeTablesController < ChouetteController def create tt_params = time_table_params - unless tt_params[:calendar_id].empty? + unless tt_params[:calendar_id] && tt_params[:calendar_id] == "" %i(monday tuesday wednesday thursday friday saturday sunday).map { |d| tt_params[d] = true } calendar = Calendar.find(tt_params[:calendar_id]) tt_params[:calendar_id] = nil if tt_params.has_key?(:dates_attributes) || tt_params.has_key?(:periods_attributes) diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index 0c5ebbbe0..f8d45f9b8 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -47,18 +47,17 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord chunk[group] ||= [] chunk[group] << date end - chunk.values + # Remove less than 2 continuous day chunk + chunk.values.delete_if {|dates| dates.count < 2} end def convert_continuous_dates_to_periods chunks = self.continuous_dates - # Remove less than 2 continuous day chunk - chunks.delete_if {|chunk| chunk.count < 2} transaction do chunks.each do |chunk| self.periods.create!(period_start: chunk.first.date, period_end: chunk.last.date) - chunk.map(&:destroy) + self.dates.delete(chunk) end end end @@ -462,41 +461,50 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord optimized.sort { |a,b| a.period_start <=> b.period_start} end - def optimize_continuous_periods - periods = self.clone_periods - optimized = [] - i = 0 - while i < periods.length - p1 = periods[i] - p2 = periods[i + 1] - if p1.period_end + 1.day === p2.try(:period_start) - p1.period_end = p2.period_end - optimized << p1 - periods.delete p2 + def continuous_periods + periods = self.periods.sort_by(&:period_start) + chunk = {} + group = nil + periods.each_with_index do |period, index| + group ||= index + group = (period.period_start - 1.day == periods[index - 1].period_end) ? group : group + 1 + chunk[group] ||= [] + chunk[group] << period + end + chunk.values.delete_if {|periods| periods.count < 2} + end + + def convert_continuous_periods_into_one + chunks = self.continuous_periods + + transaction do + chunks.each do |chunk| + self.periods.create!(period_start: chunk.first.period_start, period_end: chunk.last.period_end) + self.periods.delete(chunk) end - i += 1 end - optimized end + #update a period if a in_day is just before or after def optimize_continuous_dates_and_periods - days = self.included_days + + + in_days = self.dates.where(in_out: true).sort_by(&:date) periods = self.clone_periods optimized = [] - i = 0 - while i < days.length - day = days[i] - j = i - while j < periods.length - period = periods[j] - period.period_start = day if period.period_start - 1.day === day - period.period_end = day if period.period_end + 1.day === day - optimized << period - j += 1 + + periods.each do |period| + in_days.each do |day| + if period.period_start - 1.day === day.date + period.period_start = day.date + self.dates.delete(day) + elsif period.period_end + 1.day === day.date + period.period_end = day.date + self.dates.delete(day) + end end - i += 1 + optimized << period end - #update a period if a in_day is just before or after optimized end @@ -520,7 +528,6 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord # For included dates another_tt.included_days.map{ |d| add_included_day(d) } - # binding.pry # For excluded dates existing_out_date = self.dates.where(in_out: false).map(&:date) @@ -528,14 +535,13 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord unless existing_out_date.include?(d.date) self.dates << Chouette::TimeTableDate.new(:date => d.date, :in_out => false) end + self.save! end - self.save! + self.convert_continuous_dates_to_periods + self.periods = self.optimize_continuous_dates_and_periods + self.convert_continuous_periods_into_one + self.periods = self.optimize_overlapping_periods end - - self.convert_continuous_dates_to_periods - self.periods = self.optimize_continuous_dates_and_periods - self.periods = self.optimize_continuous_periods - self.periods = self.optimize_overlapping_periods end def included_days_in_dates_and_periods diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb index bd74a2d4c..fb59a75be 100644 --- a/spec/models/chouette/time_table_spec.rb +++ b/spec/models/chouette/time_table_spec.rb @@ -14,6 +14,8 @@ describe Chouette::TimeTable, :type => :model do describe "#merge! with time_table" do let(:another_tt) { create(:time_table) } let(:another_tt_periods_to_range) { another_tt.periods.map{|p| p.period_start..p.period_end } } + let(:dates) { another_tt.dates.map(&:date) } + let(:continuous_dates) { another_tt.continuous_dates.flatten.map(&:date) } # Make sur we don't have overlapping periods or dates before do @@ -22,12 +24,19 @@ describe Chouette::TimeTable, :type => :model do p.period_end = p.period_end + 1.year end another_tt.dates.each{| d| d.date = d.date + 1.year } + another_tt.save end it 'should merge dates' do subject.dates.clear subject.merge!(another_tt) - expect(subject.dates.map(&:date)).to include(*another_tt.dates.map(&:date)) + expect(subject.dates.map(&:date)).to match_array(dates - continuous_dates) + end + + it 'should not merge continuous dates' do + subject.dates.clear + subject.merge!(another_tt) + expect(subject.dates.map(&:date)).not_to include(*continuous_dates) end it 'should merge periods' do @@ -54,24 +63,30 @@ describe Chouette::TimeTable, :type => :model do context "#merge! with calendar" do let(:calendar) { create(:calendar, date_ranges: [Date.today + 1.year..Date.tomorrow + 1.year]) } + let(:another_tt) { calendar.convert_to_time_table } + let(:dates) { subject.dates.map(&:date) } + let(:continuous_dates) { subject.continuous_dates.flatten.map(&:date) } it 'should merge calendar dates' do subject.dates.clear - subject.merge!(calendar.convert_to_time_table) - expect(subject.dates.map(&:date)).to include(*calendar.dates) + subject.merge!(another_tt) + expect(subject.dates.map(&:date)).to match_array(dates - continuous_dates) + end + + it 'should not merge calendar continuous dates' do + subject.dates.clear + subject.merge!(another_tt) + expect(subject.dates.map(&:date)).not_to include(*continuous_dates) end it 'should merge calendar periods with no periods in source' do subject.periods.clear - another_tt = calendar.convert_to_time_table subject.merge!(another_tt) expect(subject_periods_to_range).to include(*calendar.date_ranges) end it 'should add calendar periods with existing periods in source' do - another_tt = calendar.convert_to_time_table subject.merge!(another_tt) - expect(subject_periods_to_range).to include(*calendar.date_ranges) end end @@ -1127,7 +1142,7 @@ end subject.int_day_types = 4|8|16 end it "should return 2 ordered periods" do - periods = subject.optimize_periods + periods = subject.optimize_overlapping_periods expect(periods.size).to eq(2) expect(periods[0].period_start).to eq(Date.new(2014, 6, 1)) expect(periods[0].period_end).to eq(Date.new(2014, 6, 14)) diff --git a/spec/models/time_table_combination_spec.rb b/spec/models/time_table_combination_spec.rb index 3e60fa444..81f9dd7a6 100644 --- a/spec/models/time_table_combination_spec.rb +++ b/spec/models/time_table_combination_spec.rb @@ -8,30 +8,39 @@ describe TimeTableCombination, :type => :model do describe '#continuous_dates' do it 'should group continuous dates' do dates = source.dates.where(in_out: true) - expect(source.continuous_dates[0].count).to eq(dates.count) + expect(source.continuous_dates.flatten.count).to eq(dates.count) - # 6 more continuous date, 1 isolated date + # 6 more continuous dates, 2 isolated dates (10..15).each do |n| source.dates.create(date: Date.today + n.day, in_out: true) end - source.dates.create(date: Date.today + 1.year, in_out: true) + + (1..2).each do |n| + source.dates.create(date: Date.today + n.day + 1.year, in_out: true) + end + expect(source.reload.continuous_dates[1].count).to eq(6) - expect(source.reload.continuous_dates[2].count).to eq(1) + expect(source.reload.continuous_dates[2].count).to eq(2) end end describe '#convert_continuous_dates_to_periods' do it 'should convert continuous dates to periods' do + source.dates.clear + (10..12).each do |n| source.dates.create(date: Date.today + n.day, in_out: true) end - source.dates.create(date: Date.today + 1.year, in_out: true) + + (1..3).each do |n| + source.dates.create(date: Date.today + n.day + 1.year, in_out: true) + end expect { source.reload.convert_continuous_dates_to_periods }.to change {source.periods.count}.by(2) - expect(source.reload.dates.where(in_out: true).count).to eq(1) + expect(source.reload.dates.where(in_out: true).count).to eq(0) end end @@ -129,4 +138,3 @@ describe TimeTableCombination, :type => :model do end end end - |
