turba_chronos 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +11 -0
- data/lib/turba_chronos.rb +31 -0
- data/lib/turba_chronos/core_ext/range.rb +5 -0
- data/lib/turba_chronos/day.rb +71 -0
- data/lib/turba_chronos/period.rb +44 -0
- data/lib/turba_chronos/period_converter.rb +69 -0
- data/lib/turba_chronos/periods.rb +43 -0
- data/lib/turba_chronos/rule.rb +52 -0
- data/lib/turba_chronos/stored_periods.rb +68 -0
- data/lib/turba_chronos/timeline.rb +139 -0
- data/lib/turba_chronos/version.rb +3 -0
- data/spec/fixtures/base_fixture.rb +31 -0
- data/spec/fixtures/disney_fixture.rb +19 -0
- data/spec/fixtures/empty_periods_fixture.rb +13 -0
- data/spec/fixtures/future_reopen_fixture.rb +19 -0
- data/spec/fixtures/lcl_fixture.rb +18 -0
- data/spec/fixtures/november_bug_fixture.rb +13 -0
- data/spec/fixtures/opened_fixture.rb +12 -0
- data/spec/lib/alt_timeline_spec.rb +48 -0
- data/spec/lib/disney_2_spec.rb +21 -0
- data/spec/lib/disney_3_spec.rb +21 -0
- data/spec/lib/disney_spec.rb +21 -0
- data/spec/lib/empty_periods_spec.rb +21 -0
- data/spec/lib/future_reopen_spec.rb +21 -0
- data/spec/lib/lcl_spec.rb +28 -0
- data/spec/lib/november_bug_spec.rb +20 -0
- data/spec/lib/opened_spec.rb +21 -0
- data/spec/lib/timeline_spec.rb +70 -0
- data/spec/spec_helper.rb +8 -0
- data/test/fixtures/base_fixture.rb +31 -0
- data/test/test_helper.rb +6 -0
- data/test/test_periods.rb +16 -0
- data/test/test_periods_converter.rb +62 -0
- data/test/test_rule.rb +33 -0
- data/test/test_timeline.rb +51 -0
- data/turba_chronos.gemspec +30 -0
- 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,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,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,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
|