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 - | 
