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.
@@ -0,0 +1,9 @@
1
+ module Lightswitch
2
+ module Constants
3
+
4
+ END_OF_DAY_HOURS = nil
5
+ END_OF_DAY_MINUTES = nil
6
+ DEFAULT_TIME_OFFSET = [5, :minutes]
7
+
8
+ end
9
+ end
@@ -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: []