lightswitch-schedules 0.0.1
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.
- data/lib/lightswitch/constants.rb +9 -0
- data/lib/lightswitch/models.rb +34 -0
- data/lib/lightswitch/schedule_creation.rb +42 -0
- data/lib/lightswitch/schedule_mixins.rb +107 -0
- data/lib/lightswitch/schedules.rb +57 -0
- metadata +51 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'data_mapper'
|
2
|
+
require_relative 'schedule_mixins'
|
3
|
+
|
4
|
+
module Lightswitch
|
5
|
+
|
6
|
+
class ScheduleCollection
|
7
|
+
include DataMapper::Resource, ScheduleCollectionMixin
|
8
|
+
|
9
|
+
property :id, Serial
|
10
|
+
property :name, String, :required => true
|
11
|
+
|
12
|
+
has n, :schedules
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"Schedule collection #{name}" + (schedules.empty? ? "" : " with schedules: " + schedules.collect(&:to_s).join("\n"))
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
class Schedule
|
22
|
+
include DataMapper::Resource, ScheduleMixin
|
23
|
+
|
24
|
+
property :id, Serial
|
25
|
+
property :start_hour, Integer, :required => true
|
26
|
+
property :start_minutes, Integer, :required => true
|
27
|
+
property :end_hour, Integer
|
28
|
+
property :end_minutes, Integer
|
29
|
+
|
30
|
+
belongs_to :schedule_collection, :required => false
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative 'constants'
|
2
|
+
|
3
|
+
module Lightswitch
|
4
|
+
module ScheduleCreation
|
5
|
+
|
6
|
+
|
7
|
+
def get_hours_and_minutes(tod_string)
|
8
|
+
raise ArgumentError, "Please specify a time of day as 'hhmm', was given '#{tod_string}' instead" unless (tod_string and tod_string.length == 4)
|
9
|
+
|
10
|
+
hours = tod_string.slice(0, 2).to_i
|
11
|
+
raise ArgumentError, "Please specify a time in hours ranging from 0 to 23, was given '#{hours}' in '#{tod_string}' instead" unless (0..23).include? hours
|
12
|
+
|
13
|
+
minutes = tod_string.slice(2, 2).to_i
|
14
|
+
raise ArgumentError, "Please specify a time in minutes ranging from 0 to 59, was given '#{minutes}' in '#{tod_string}' instead" unless (0..59).include? minutes
|
15
|
+
|
16
|
+
[hours, minutes]
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def from_h(schedule_description)
|
21
|
+
start_time_of_day = schedule_description[:start]
|
22
|
+
start_hour, start_minutes = get_hours_and_minutes(start_time_of_day)
|
23
|
+
|
24
|
+
end_time_of_day = schedule_description[:end]
|
25
|
+
|
26
|
+
if end_time_of_day
|
27
|
+
end_hour, end_minutes = get_hours_and_minutes(end_time_of_day)
|
28
|
+
|
29
|
+
raise ArgumentError, "Ending time cannot precede start time" unless start_hour <= end_hour
|
30
|
+
if (start_hour == end_hour)
|
31
|
+
raise ArgumentError, "Ending time must follow start time" unless start_minutes < end_minutes
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end_hour, end_minutes = end_time_of_day ? [end_hour, end_minutes] : [Constants::END_OF_DAY_HOURS, Constants::END_OF_DAY_MINUTES]
|
36
|
+
|
37
|
+
{start_hour: start_hour, start_minutes: start_minutes, end_hour: end_hour, end_minutes: end_minutes}
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Lightswitch
|
2
|
+
module ScheduleCommon
|
3
|
+
|
4
|
+
def encode_state(up_boolean)
|
5
|
+
up_boolean ? 'up' : 'down'
|
6
|
+
end
|
7
|
+
|
8
|
+
def decode_state(state_string)
|
9
|
+
state_string == 'up'
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_schedule_state_change(reference_state, at_time)
|
13
|
+
scheduled_state_encoded = encode_state(up?(at_time))
|
14
|
+
if (scheduled_state_encoded != reference_state)
|
15
|
+
StateChange.new(scheduled_state_encoded, at_time)
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
module ScheduleCollectionMixin
|
25
|
+
include ScheduleCommon
|
26
|
+
|
27
|
+
|
28
|
+
def up?(at_time)
|
29
|
+
!(schedules.any? { |schedule| schedule.down?(at_time) })
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def down?(at_time)
|
34
|
+
!up?(at_time)
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
class StateChange
|
42
|
+
attr_accessor :state, :at_time
|
43
|
+
|
44
|
+
def initialize(state_string, at_time)
|
45
|
+
@state, @at_time = state_string, at_time
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_h
|
49
|
+
{state: state, at_time: at_time}
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_s; "State change to #{state} at #{at_time}"; end
|
53
|
+
|
54
|
+
def equal?(other)
|
55
|
+
other.is_a? StateChange and (other.state == state and other.at_time == at_time)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
module ScheduleMixin
|
61
|
+
include ScheduleCommon
|
62
|
+
|
63
|
+
def up?(at_time)
|
64
|
+
time_hour, time_minutes = at_time.hour, at_time.min
|
65
|
+
|
66
|
+
unless (end_hour and end_minutes)
|
67
|
+
return after_start_time(time_hour, time_minutes)
|
68
|
+
else
|
69
|
+
|
70
|
+
if (start_hour..end_hour).include? time_hour
|
71
|
+
return (start_minutes <= time_minutes) if (start_hour == time_hour)
|
72
|
+
return (time_minutes <= end_minutes) if (end_hour == time_hour)
|
73
|
+
true
|
74
|
+
else
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def after_start_time(hour, minutes)
|
83
|
+
(hour > start_hour) or ((hour == start_hour) and (minutes >= start_minutes))
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def down?(at_time)
|
88
|
+
!up?(at_time)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def to_s
|
93
|
+
"Daily uptime schedule: #{start_time_of_day} to #{end_time_of_day}"
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def start_time_of_day
|
98
|
+
"#{start_hour.to_s.rjust(2, '0')}:#{start_minutes.to_s.rjust(2, '0')}"
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def end_time_of_day
|
103
|
+
(end_hour and end_minutes) ? "#{end_hour.to_s.rjust(2, '0')}:#{end_minutes.to_s.rjust(2, '0')}" : "end of day"
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative 'schedule_creation'
|
2
|
+
require_relative 'models'
|
3
|
+
require_relative 'constants'
|
4
|
+
|
5
|
+
module Lightswitch
|
6
|
+
|
7
|
+
class Schedules
|
8
|
+
include ScheduleCreation
|
9
|
+
|
10
|
+
def make_schedule(schedule_description)
|
11
|
+
Lightswitch::Schedule.new(from_h(schedule_description))
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def create_schedule_collection(schedules_description)
|
16
|
+
schedule_collection = Lightswitch::ScheduleCollection.new({name: schedules_description[:name]})
|
17
|
+
|
18
|
+
schedules = schedules_description[:schedules]
|
19
|
+
uptime_schedules = schedules.collect { |schedule_description|
|
20
|
+
make_schedule(schedule_description)
|
21
|
+
}
|
22
|
+
|
23
|
+
uptime_schedules.each { |schedule|
|
24
|
+
schedule_collection.schedules << schedule
|
25
|
+
}
|
26
|
+
|
27
|
+
schedule_collection.save
|
28
|
+
schedule_collection.id
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def get_schedule_collection(id)
|
33
|
+
Lightswitch::ScheduleCollection.get(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def get_scheduled_state_changes(state, from_time, to_time, schedules_id)
|
38
|
+
at_from_time = get_scheduled_state_change_at_time(state, from_time, schedules_id)
|
39
|
+
|
40
|
+
state_for_to_time = at_from_time.nil? ? state : at_from_time.state
|
41
|
+
at_to_time = get_scheduled_state_change_at_time(state_for_to_time, to_time, schedules_id)
|
42
|
+
|
43
|
+
state_changes = []
|
44
|
+
state_changes << at_from_time if at_from_time
|
45
|
+
state_changes << at_to_time if at_to_time
|
46
|
+
|
47
|
+
state_changes
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def get_scheduled_state_change_at_time(state, at_time, schedules_id)
|
52
|
+
schedule_collection = get_schedule_collection(schedules_id)
|
53
|
+
schedule_collection.get_schedule_state_change(state, at_time)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lightswitch-schedules
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Krishnan M
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-04-19 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Create and persist schedules (such as daily and weekly) that lightswitch
|
15
|
+
can use to turn instances on and off
|
16
|
+
email: km@krishnanm.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/lightswitch/constants.rb
|
22
|
+
- lib/lightswitch/models.rb
|
23
|
+
- lib/lightswitch/schedule_creation.rb
|
24
|
+
- lib/lightswitch/schedule_mixins.rb
|
25
|
+
- lib/lightswitch/schedules.rb
|
26
|
+
homepage: http://rubygems.org/gems/lightswitch-schedules
|
27
|
+
licenses:
|
28
|
+
- MIT
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
require_paths:
|
32
|
+
- lib
|
33
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 1.8.24
|
48
|
+
signing_key:
|
49
|
+
specification_version: 3
|
50
|
+
summary: Create schedules for use in lightswitch
|
51
|
+
test_files: []
|