turba_chronos 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +6 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +68 -0
  8. data/Rakefile +11 -0
  9. data/lib/turba_chronos.rb +31 -0
  10. data/lib/turba_chronos/core_ext/range.rb +5 -0
  11. data/lib/turba_chronos/day.rb +71 -0
  12. data/lib/turba_chronos/period.rb +44 -0
  13. data/lib/turba_chronos/period_converter.rb +69 -0
  14. data/lib/turba_chronos/periods.rb +43 -0
  15. data/lib/turba_chronos/rule.rb +52 -0
  16. data/lib/turba_chronos/stored_periods.rb +68 -0
  17. data/lib/turba_chronos/timeline.rb +139 -0
  18. data/lib/turba_chronos/version.rb +3 -0
  19. data/spec/fixtures/base_fixture.rb +31 -0
  20. data/spec/fixtures/disney_fixture.rb +19 -0
  21. data/spec/fixtures/empty_periods_fixture.rb +13 -0
  22. data/spec/fixtures/future_reopen_fixture.rb +19 -0
  23. data/spec/fixtures/lcl_fixture.rb +18 -0
  24. data/spec/fixtures/november_bug_fixture.rb +13 -0
  25. data/spec/fixtures/opened_fixture.rb +12 -0
  26. data/spec/lib/alt_timeline_spec.rb +48 -0
  27. data/spec/lib/disney_2_spec.rb +21 -0
  28. data/spec/lib/disney_3_spec.rb +21 -0
  29. data/spec/lib/disney_spec.rb +21 -0
  30. data/spec/lib/empty_periods_spec.rb +21 -0
  31. data/spec/lib/future_reopen_spec.rb +21 -0
  32. data/spec/lib/lcl_spec.rb +28 -0
  33. data/spec/lib/november_bug_spec.rb +20 -0
  34. data/spec/lib/opened_spec.rb +21 -0
  35. data/spec/lib/timeline_spec.rb +70 -0
  36. data/spec/spec_helper.rb +8 -0
  37. data/test/fixtures/base_fixture.rb +31 -0
  38. data/test/test_helper.rb +6 -0
  39. data/test/test_periods.rb +16 -0
  40. data/test/test_periods_converter.rb +62 -0
  41. data/test/test_rule.rb +33 -0
  42. data/test/test_timeline.rb +51 -0
  43. data/turba_chronos.gemspec +30 -0
  44. metadata +236 -0
@@ -0,0 +1,68 @@
1
+ module TurbaChronos
2
+ module StoredPeriods
3
+
4
+ def self.all
5
+ @all ||= [self.FR, self.DE, self.BR, self.RU, self.TR].reduce(:merge)
6
+ end
7
+
8
+ def self.FR
9
+ {
10
+ vacances_noel: [['20/12', '31/12'], ['01/01', '05/01']],
11
+ vacances_toussaint: [['18/10', '02/11']],
12
+ vacances_hiver_zone_a: [['07/02', '22/02']],
13
+ vacances_hiver_zone_b: [['21/02', '08/03']],
14
+ vacances_hiver_zone_c: [['14/02', '01/03']],
15
+ vacances_hiver: [['07/02', '08/03']],
16
+ vacances_printemps_zone_a: [['11/04', '26/04']],
17
+ vacances_printemps_zone_b: [['25/04', '10/05']],
18
+ vacances_printemps_zone_c: [['18/04', '03/05']],
19
+ vacances_printemps: [['11/04', '10/05']],
20
+ vacances_ete: [['05/07', '01/09']],
21
+ week_end_paques: [['04/04', '06/04']],
22
+ weekend_14_juillet: [['12/07', '14/07']],
23
+ premiere_semaine_juillet: [['30/06', '06/07']],
24
+ premiere_quinzaine_aout: [['01/08', '17/08']],
25
+ derniere_quinzaine_aout: [['18/08', '31/08']],
26
+ derniere_quinzaine_juillet: [['12/07', '31/07']],
27
+ premiere_quinzaine_juillet: [['01/07', '11/07']],
28
+ derniere_semaine_juillet: [['22/07', '31/07']],
29
+ pentecote: [['08/06', '09/06']],
30
+ carnaval_venise: [['22/02', '04/03']],
31
+ ponts_mai: [['01/05', '03/05'], ['08/05', '10/05'], ['23/05', '25/05'], ['25/06'], ['28/06']],
32
+ jours_feries: [['01/01'],['06/04'],['01/05'],['08/05'],['14/05'],['25/05'],['14/07'],['15/08'],['01/11'],['11/11'],['25/12']]
33
+ }
34
+ end
35
+
36
+ def self.DE
37
+ {
38
+ ostern: [['02/04', '05/05']],
39
+ pfingsten: [['08/06', '09/06']],
40
+ buss_und_bettag: [['19/11']],
41
+ himmelfahrt: [['29/05']],
42
+ tag_der_deutschen_einheit: [['03/10']]
43
+ }
44
+ end
45
+
46
+ def self.BR
47
+ {
48
+ pascoa: [['02/04', '05/05']],
49
+ ferias_escolares: [['01/07', '31/07']],
50
+ semana_dia_das_criancas: [['12/10']],
51
+ proclamacao_de_republica: [['15/11', '17/11']],
52
+ feriados_fixos: [['01/01'],['21/04'],['01/05'],['07/09'],['12/10'],['02/11'],['15/11'],['25/12']]
53
+ }
54
+ end
55
+
56
+ def self.GB
57
+ {}
58
+ end
59
+
60
+ def self.RU
61
+ {}
62
+ end
63
+
64
+ def self.TR
65
+ {}
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,139 @@
1
+ module TurbaChronos
2
+ class Timeline
3
+ def initialize(periods, from, to)
4
+ @periods = Periods.new(periods).complete
5
+ @from = from
6
+ @to = to
7
+ end
8
+
9
+ def business_timeranges
10
+ timeranges_for_days[:business_timeranges].map! {|x|
11
+ [x.min.to_s.rjust(4, '0').insert(2, ':'), x.max.to_s.rjust(4, '0').insert(2, ':')]
12
+ }
13
+ end
14
+
15
+ def levels
16
+ @levels ||= days.map(&:timeframes).flatten.map(&:level).uniq
17
+ end
18
+
19
+ def timeranges_for_days
20
+ @timeranges_for_days ||= get_timeranges_for_days(@from, @to)
21
+ end
22
+
23
+ def days
24
+ @days ||= get_days(@from, @to)
25
+ end
26
+
27
+ def current_day
28
+ @current_day ||= days.first
29
+ end
30
+
31
+ def opened?
32
+ current_day.opened?
33
+ end
34
+
35
+ def next
36
+ get_list(days)[0..2]
37
+ end
38
+
39
+ def reopen
40
+ get_list(days).each do |data|
41
+ return data if data.timeframe.level != 6
42
+ end
43
+
44
+ iteration = 14
45
+ count = 0
46
+ loop do
47
+ if count == 0
48
+ next_days = get_days(@to+1.day, @to+iteration.days)
49
+ else
50
+ next_days = get_days((@to+(count * iteration).days), (@to+((count+1) * iteration).days))
51
+ end
52
+ get_list(next_days).each do |data|
53
+ return data if data.timeframe.level != 6
54
+ end
55
+ count += 1
56
+ end
57
+ end
58
+
59
+ def current_timeframe
60
+ current_day.current_timeframe
61
+ end
62
+
63
+ protected
64
+
65
+ def get_uniq_periods_for_days(from, to)
66
+ (from.to_date..to.to_date).step(1).to_a.map! do |day|
67
+ get_periods_for_day(day).first
68
+ end.uniq.sort_by!(&:distance)
69
+ end
70
+
71
+ def get_periods_for_day(day)
72
+ periods = @periods.reject do |period|
73
+ ([day.yday] & period.yday_array).blank?
74
+ end
75
+ periods.push(default_period) if periods.empty?
76
+ periods
77
+ end
78
+
79
+ def default_period
80
+ start_year = Time.now.utc.beginning_of_year
81
+ end_year = Time.now.utc.end_of_year
82
+ Period.new(start_year, end_year, [[*FULL_DAY_TIMERANGE, *[6]*7]])
83
+ end
84
+
85
+ def get_days(from, to)
86
+ periods = get_uniq_periods_for_days(from, to)
87
+ rules = get_rules_for_periods(periods)
88
+ timeranges = get_timeranges_for_rules(rules)
89
+ (from.to_date..to.to_date).step(1).to_a.map do |day|
90
+ Day.new(day, periods, timeranges)
91
+ end
92
+ end
93
+
94
+ def get_rules_for_periods(periods)
95
+ periods.map(&:rules).flatten!
96
+ end
97
+
98
+ def get_timeranges_for_rules(rules)
99
+ business_timeranges = rules.select {|r| !r.business_hours}.flatten.uniq.map(&:range).sort
100
+ timeranges = rules.flatten.uniq.map(&:range).sort
101
+
102
+ {
103
+ timeranges: timeranges,
104
+ business_timeranges: business_timeranges.uniq
105
+ }
106
+ end
107
+
108
+ def get_timeranges_for_days(from, to)
109
+ rules = get_rules_for_days(from, to)
110
+ business_timeranges = rules.select {|r| !r.business_hours}.flatten.uniq.map(&:range).sort
111
+ timeranges = rules.flatten.uniq.map(&:range).sort
112
+ {
113
+ timeranges: timeranges,
114
+ business_timeranges: business_timeranges.uniq
115
+ }
116
+ end
117
+
118
+ def get_rules_for_days(from, to)
119
+ rules = []
120
+ get_uniq_periods_for_days(from, to).each do |period|
121
+ next if ([from.yday] & period.yday_array || [to.yday] & period.yday_array).blank?
122
+ rules.push(period.rules)
123
+ end
124
+ rules.flatten
125
+ end
126
+
127
+ TempTimeframe = Struct.new(:date, :timeframe)
128
+ def get_list(days)
129
+ list = []
130
+ days.each_with_index do |day, day_index|
131
+ day.timeframes.each do |timeframe|
132
+ next if day_index == 0 && timeframe.timerange.min < TurbaChronos.current_numeric_time
133
+ list.push TempTimeframe.new(day.date, timeframe)
134
+ end
135
+ end
136
+ list
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,3 @@
1
+ module TurbaChronos
2
+ VERSION = "5.2.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ def base
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '01/01:31/12',
6
+ rules: [
7
+ ['08:00', '10:00', 1, 1, 1, 1, 6, 6, 6],
8
+ ['10:00', '17:00', 1, 1, 1, 1, 6, 6, 6]
9
+ ]
10
+ },
11
+ {
12
+ dates: '18/05',
13
+ rules: [
14
+ ['06:00', '15:00', 3, 3, 3, 3, 3, 3, 3]
15
+ ]
16
+ },
17
+ {
18
+ dates: '01/05,25/08:28/08',
19
+ rules: [
20
+ ['08:00', '10:00', 6, 6, 6, 6, 6, 6, 6]
21
+ ]
22
+ },
23
+ {
24
+ dates: 'august,vacances_toussaint,vacances_noel',
25
+ rules: [
26
+ ['08:00', '10:00', 2, 2, 2, 2, 2, 2, 2]
27
+ ]
28
+ }
29
+ ]
30
+ crowd
31
+ end
@@ -0,0 +1,19 @@
1
+ def disney
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '01/01:31/12',
6
+ rules: [
7
+ ['07:00', '13:00', 4, 4, 4, 4, 4, 4, 4]
8
+ ]
9
+ },
10
+ {
11
+ dates: '03/11:30/11',
12
+ rules: [
13
+ ['08:00', '10:00', 8, 8, 8, 8, 8, 8, 8],
14
+ ['10:00', '21:00', 1, 1, 1, 1, 1, 3, 2]
15
+ ]
16
+ }
17
+ ]
18
+ crowd
19
+ end
@@ -0,0 +1,13 @@
1
+ def empty_periods
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '03/11:30/11',
6
+ rules: [
7
+ ['08:00', '10:00', 8, 8, 8, 8, 8, 8, 8],
8
+ ['10:00', '21:00', 1, 1, 1, 1, 1, 3, 2]
9
+ ]
10
+ }
11
+ ]
12
+ crowd
13
+ end
@@ -0,0 +1,19 @@
1
+ def future_reopen
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '01/01:31/12',
6
+ rules: [
7
+ ['08:00', '10:00', 6, 6, 6, 6, 6, 6, 6],
8
+ ['10:00', '17:00', 6, 6, 6, 6, 6, 6, 6]
9
+ ]
10
+ },
11
+ {
12
+ dates: '13/08:15/08',
13
+ rules: [
14
+ ['08:00', '10:00', 2, 2, 2, 2, 2, 2, 2]
15
+ ]
16
+ }
17
+ ]
18
+ crowd
19
+ end
@@ -0,0 +1,18 @@
1
+ def lcl
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '01/01:31/12',
6
+ rules: [
7
+ ['07:00', '08:00', 3, 3, 3, 3, 3, 6, 6],
8
+ ['08:00', '09:00', 1, 1, 1, 1, 1, 6, 6],
9
+ ['09:00', '12:00', 3, 3, 3, 3, 3, 3, 6],
10
+ ['12:00', '14:00', 1, 1, 1, 1, 1, 1, 6],
11
+ ['14:00', '17:00', 3, 3, 3, 3, 3, 1, 6],
12
+ ['17:00', '17:30', 1, 1, 1, 1, 1, 1, 6],
13
+ ['17:30', '19:00', 1, 1, 1, 1, 1, 3, 6]
14
+ ]
15
+ }
16
+ ]
17
+ crowd
18
+ end
@@ -0,0 +1,13 @@
1
+ def november_bug
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '01/01:31/12',
6
+ rules: [
7
+ ['12:00', '16:00', 1, 2, 2, 2, 2, 2, 2],
8
+ ['16:00', '18:00', 4, 3, 3, 3, 3, 3, 3]
9
+ ]
10
+ }
11
+ ]
12
+ crowd
13
+ end
@@ -0,0 +1,12 @@
1
+ def opened
2
+ crowd = OpenStruct.new
3
+ crowd.periods = [
4
+ {
5
+ dates: '01/01:31/12',
6
+ rules: [
7
+ ['12:00', '18:00', 7, 7, 7, 7, 7, 7, 7]
8
+ ]
9
+ }
10
+ ]
11
+ crowd
12
+ end
@@ -0,0 +1,48 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe TurbaChronos::Timeline do
4
+ before(:all) do
5
+ Timecop.freeze(Time.zone.parse("September 23 2014, 14:30").iso8601)
6
+ end
7
+
8
+ after(:all) do
9
+ Timecop.return
10
+ end
11
+
12
+ def default_timeline
13
+ Time.zone = 'Europe/Paris'
14
+ TurbaChronos.load([], Time.now.utc.iso8601, (Time.now.utc + 1.day).iso8601)
15
+ end
16
+
17
+ describe '.business_timeranges' do
18
+ it "returns the business timeranges" do
19
+ expect(default_timeline.business_timeranges).to eql([["00:00", "23:59"]])
20
+ end
21
+ end
22
+
23
+ describe '.levels' do
24
+ it "returns the levels" do
25
+ expect(default_timeline.levels).to eql([6])
26
+ end
27
+ end
28
+
29
+ describe '.days' do
30
+ it "returns the days" do
31
+ expect(default_timeline.days.count).to eql(2)
32
+ expect(default_timeline.days.first.instance_of?(TurbaChronos::Day)).to eql(true)
33
+ end
34
+ end
35
+
36
+ describe '.current_day' do
37
+ it "returns the current_day" do
38
+ expect(default_timeline.current_day.instance_of?(TurbaChronos::Day)).to eql(true)
39
+ end
40
+ end
41
+
42
+ describe '.opened?' do
43
+ it "returns boolean if the day is opened or not" do
44
+ expect(default_timeline.opened?).to eql(false)
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../spec_helper'
2
+ require_relative '../fixtures/disney_fixture'
3
+
4
+ describe TurbaChronos::Timeline do
5
+ before(:all) do
6
+ Timecop.freeze(Time.zone.parse("November 02 2014, 14:30"))
7
+ from = Time.zone.parse("November 04 2014, 00:00").iso8601
8
+ to = Time.zone.parse("November 05 2014, 23:59").iso8601
9
+ @subject = TurbaChronos.load(disney.periods, from, to)
10
+ end
11
+
12
+ after(:all) do
13
+ Timecop.return
14
+ end
15
+
16
+ describe '.days' do
17
+ it "returns the days" do
18
+ expect(@subject.days.first.timeframes.count).to eql(2)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../spec_helper'
2
+ require_relative '../fixtures/disney_fixture'
3
+
4
+ describe TurbaChronos::Timeline do
5
+ before(:all) do
6
+ Timecop.freeze(Time.zone.parse("November 30 2014, 14:30"))
7
+ from = Time.zone.parse("November 30 2014, 00:00").iso8601
8
+ to = Time.zone.parse("December 01 2014, 23:59").iso8601
9
+ @subject = TurbaChronos.load(disney.periods, from, to)
10
+ end
11
+
12
+ after(:all) do
13
+ Timecop.return
14
+ end
15
+
16
+ describe '.days' do
17
+ it "returns the days" do
18
+ expect(@subject.current_day.current_timeframe.level).to eql(2)
19
+ end
20
+ end
21
+ end