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