diff options
| author | Xinhui | 2017-06-28 12:28:41 +0200 |
|---|---|---|
| committer | Xinhui | 2017-06-28 12:35:34 +0200 |
| commit | e954f7994d692919492c40b7bce4cce1e0293755 (patch) | |
| tree | 519730ddb78bdc8ffcfbd4cb81b8ad329de0610d | |
| parent | b112d6e5446ae1677e9afe527a5fefd30620b14c (diff) | |
| download | chouette-core-e954f7994d692919492c40b7bce4cce1e0293755.tar.bz2 | |
Refactoring time_table#merge
Refs #3788
| -rw-r--r-- | app/models/chouette/time_table.rb | 63 | ||||
| -rw-r--r-- | spec/models/chouette/time_table_spec.rb | 103 |
2 files changed, 70 insertions, 96 deletions
diff --git a/app/models/chouette/time_table.rb b/app/models/chouette/time_table.rb index 4186af6d2..c566452f4 100644 --- a/app/models/chouette/time_table.rb +++ b/app/models/chouette/time_table.rb @@ -477,63 +477,22 @@ class Chouette::TimeTable < Chouette::TridentActiveRecord # merge effective days from another timetable def merge!(another_tt) transaction do - # merge dates - self.dates ||= [] - another_tt.included_days.each do |d| - add_included_day d - end + self.periods = another_tt.clone_periods + self.periods + self.periods = self.optimize_periods - # if one tt has no period, just merge lists - if self.periods.empty? || another_tt.periods.empty? - if !another_tt.periods.empty? - # copy periods - self.periods = another_tt.clone_periods - end - else - # check if periods can be kept - common_day_types = self.int_day_types & another_tt.int_day_types & 508 - # if common day types : merge periods - if common_day_types != 0 - periods = self.optimize_periods - another_periods = another_tt.optimize_periods - # add not common days of both periods as peculiar days - self.effective_days_of_periods(self.class.valid_days(self.int_day_types ^ common_day_types)).each do |d| - self.dates |= [Chouette::TimeTableDate.new(:date => d, :in_out => true)] - end - another_tt.effective_days_of_periods(self.class.valid_days(another_tt.int_day_types ^ common_day_types)).each do |d| - add_included_day d - end - # merge periods - self.periods = periods | another_periods - self.int_day_types = common_day_types - self.periods = self.optimize_periods - else - # convert all period in days - self.effective_days_of_periods.each do |d| - self.dates << Chouette::TimeTableDate.new(:date => d, :in_out => true) unless self.include_in_dates?(d) - end - another_tt.effective_days_of_periods.each do |d| - add_included_day d + # For included dates + another_tt.included_days.map{ |d| add_included_day(d) } + + # For excluded dates + existing_out_date = self.dates.where(in_out: false).map(&:date) + another_tt.dates.where(in_out: false).each do |d| + unless existing_out_date.include?(d.date) + self.dates << Chouette::TimeTableDate.new(:date => d.date, :in_out => false) end end - end - # if remained excluded dates are valid in other tt , remove it from result - self.dates.each do |date| - date.in_out = true if date.in_out == false && another_tt.include_day?(date.date) + self.save! end - # if peculiar dates are valid in new periods, remove them - if !self.periods.empty? - days_in_period = self.effective_days_of_periods - dates = [] - self.dates.each do |date| - dates << date unless date.in_out && days_in_period.include?(date.date) - end - self.dates = dates - end - self.dates.to_a.sort! { |a,b| a.date <=> b.date} - self.save! - end self.convert_continuous_dates_to_periods end diff --git a/spec/models/chouette/time_table_spec.rb b/spec/models/chouette/time_table_spec.rb index 7a8863cb3..76c5def5c 100644 --- a/spec/models/chouette/time_table_spec.rb +++ b/spec/models/chouette/time_table_spec.rb @@ -2,18 +2,74 @@ require 'spec_helper' describe Chouette::TimeTable, :type => :model do subject { create(:time_table) } + let(:subject_periods_to_range) { subject.periods.map{|p| p.period_start..p.period_end } } it { is_expected.to validate_presence_of :comment } it { is_expected.to validate_uniqueness_of :objectid } - context "merge with calendar" do - let(:calendar) { create(:calendar) } + 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 } } + + # Make sur we don't have overlapping periods or dates + before do + another_tt.periods.each do |p| + p.period_start = p.period_start + 1.year + p.period_end = p.period_end + 1.year + end + another_tt.dates.each{| d| d.date = d.date + 1.year } + 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)) + end + + it 'should merge periods' do + subject.periods.clear + subject.merge!(another_tt) + + expect(subject_periods_to_range).to include(*another_tt_periods_to_range) + end + + it 'should not modify int_day_types' do + int_day_types = subject.int_day_types + subject.merge!(another_tt) + expect(subject.int_day_types).to eq int_day_types + end + + it 'should merge date in_out false' do + another_tt.dates.last.in_out = false + another_tt.save + + subject.merge!(another_tt) + expect(subject.dates.map(&:date)).to include(another_tt.dates.last.date) + end + end + + context "#merge! with calendar" do + let(:calendar) { create(:calendar, date_ranges: [Date.today + 1.year..Date.tomorrow + 1.year]) } - it 'should add calendar dates to time_table' do + 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) 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 describe "actualize" do @@ -981,47 +1037,6 @@ end end end - - describe "#merge!" do - context "timetables have periods with common day_types " do - before do - subject.periods.clear - subject.dates.clear - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,1), :period_end => Date.new(2014,8,5)) - subject.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,6,30), :period_end => Date.new(2014,7,6)) - subject.dates << Chouette::TimeTableDate.new( :date => Date.new(2014,7,16), :in_out => true) - subject.int_day_types = 4|16|32|128 - another_tt = create(:time_table , :int_day_types => (4|16|64|128) ) - another_tt.periods.clear - another_tt.dates.clear - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,8,5), :period_end => Date.new(2014,8,12)) - another_tt.periods << Chouette::TimeTablePeriod.new(:period_start => Date.new(2014,7,15), :period_end => Date.new(2014,7,25)) - subject.merge! another_tt - subject.reload - end - it "should have merged periods" do - expect(subject.periods.size).to eq(3) - expect(subject.periods[0].period_start).to eq(Date.new(2014, 6, 30)) - expect(subject.periods[0].period_end).to eq(Date.new(2014, 7, 6)) - expect(subject.periods[1].period_start).to eq(Date.new(2014, 7, 15)) - expect(subject.periods[1].period_end).to eq(Date.new(2014, 7, 25)) - expect(subject.periods[2].period_start).to eq(Date.new(2014, 8, 1)) - expect(subject.periods[2].period_end).to eq(Date.new(2014, 8, 12)) - end - it "should not modify day_types" do - expect(subject.int_day_types).to eq(4|16|128) - end - it "should have dates for thursdays and fridays" do - expect(subject.dates.size).to eq(4) - expect(subject.dates[0].date).to eq(Date.new(2014,7,3)) - expect(subject.dates[1].date).to eq(Date.new(2014,7,18)) - expect(subject.dates[2].date).to eq(Date.new(2014,7,25)) - expect(subject.dates[3].date).to eq(Date.new(2014,8,8)) - end - end - - end - describe "#intersect!" do context "timetables have periods with common day_types " do before do |
