ocarina_of_time 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c76b5c32fdda58e5ba617450ad0f9acee53b290a
4
+ data.tar.gz: caddfbedba3fe902dce0c19604a71388cd2633d5
5
+ SHA512:
6
+ metadata.gz: 297211847d7ab989b49df4ccdaa6fcf8955ea1abef018dcded9b0b0255a9706d8573e399fcadfd1bf332839b3f6e6bdfb725968db9d5c2210a8e86b4c89f7185
7
+ data.tar.gz: 581dd32dc21fa8bad047554d9dcdeed68207a0f6f2c072c108797014ba7cc62256e44545b3b724c4b7ffdc2ec9d2147e286461acf5ab48c7f0fec099668af44b
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.14.3
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at kgruber1@emich.edu. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ocarina_of_time.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Kent Gruber
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,167 @@
1
+ # Ocarina of Time
2
+ ![Alt Text](http://i.imgur.com/213eY1X.png)
3
+
4
+ Play this song near a blue Time Block.
5
+
6
+ ```
7
+ ------------------------------------------------
8
+ -( > )---------( > )----------------------------
9
+ ----------( v )-----------( > )-----------------
10
+ -----( A )-----------( A )----------------------
11
+ ```
12
+
13
+ ## Installation
14
+
15
+ $ gem install ocarina_of_time
16
+
17
+ ## Usage
18
+
19
+ ```ruby
20
+ require 'ocarina_of_time'
21
+
22
+ timeline = OcarinaOfTime::Timeline.new
23
+
24
+ # beginning of time
25
+ timeline.beginning
26
+ # => 2017-02-21 10:10:16 -0500
27
+
28
+ # check for beginning of time
29
+ timeline.beginning?
30
+
31
+ # end of time
32
+ timeline.ending
33
+ # => false
34
+
35
+ # check for end of time
36
+ timeline.ending?
37
+ # => false
38
+
39
+ # set beginning of end of time
40
+ timeline.ending = Time.now
41
+
42
+ timeline.ending?
43
+ # => true
44
+
45
+ timeline.ending
46
+ # => 2017-02-21 10:15:45 -0500
47
+ ```
48
+
49
+ ## Timeline
50
+ A timeline is a way of displaying a list of events in chronological order, sometimes described as a project artifact. Timelines can use any time scale, depending on the subject and data. Most timelines use a linear scale, where a unit of distance is equal to a set amount of time.
51
+
52
+ ```ruby
53
+ # will return a unique id number for the timeline event
54
+ timeline.events.add(label: "Example 1")
55
+ # => "e41fdc5c-6a8d-4d85-addb-27b6f81666e9"
56
+
57
+ # you can remove a timeline event by id number
58
+ timeline.events.delete(id: "e41fdc5c-6a8d-4d85-addb-27b6f81666e9")
59
+ # => true
60
+
61
+ # or you can remove a timeline event by time, if
62
+ # it exists -- maybe it's already been deleted ;)
63
+ timeline.events.delete(id: "e41fdc5c-6a8d-4d85-addb-27b6f81666e9")
64
+ # => false
65
+ ```
66
+
67
+ ## Events
68
+ Timelines events are stored in an events class which acts as a nice wrapped to our timeline Event objects.
69
+
70
+ ```ruby
71
+ # create new timeline
72
+ timeline = OcarinaOfTime::Line.new
73
+
74
+ # adding events is very straightforward
75
+ timeline.events.add(label: "Example 1")
76
+ # => OcarinaOfTime::Event:0x00000001fcd040.id
77
+ timeline.events.add(label: "Example 2")
78
+ # => OcarinaOfTime::Event:0x00000001cabce0.id
79
+
80
+ # you can easily update events
81
+ timeline.events.update(id: "2f6716b1-9a2f-46d2-8bcf-4db0212032f1", value: 1)
82
+
83
+ # you can easily delete events
84
+ timelines.events.delete(id: "2f6716b1-9a2f-46d2-8bcf-4db0212032f1")
85
+
86
+ # there's a nice little wrapped to sort_by
87
+ timeline.events.by(oldest: true)
88
+ # => OcarinaOfTime::Event:0x00000001cabce0, OcarinaOfTime::Event:0x00000001fcd040
89
+ timeline.events.by(newest: true)
90
+ # => OcarinaOfTime::Event:0x00000001fcd040, OcarinaOfTime::Event:0x00000001cabce0
91
+
92
+ # you can also find events based on different attributes
93
+ timeline.events.find(label: "Example 1")
94
+ timeline.events.find(labels: ["Example 1", "Example 2"])
95
+ timeline.events.find(event: timeline.events.all.first)
96
+ timeline.events.find(date: Time.now.to_date)
97
+
98
+ # you can also chain your find queries ( one option at a time )
99
+ timeline.events.find(date: Time.now.to_date).find(label: "Example 1")
100
+
101
+ # you can get a shortcut to all of the uniqe dates for each event
102
+ timeline.events.dates
103
+ # or a shortcut to all of the unique times for each event
104
+ timeline.events.times
105
+ # or you can get all of the unique labels
106
+ timelines.events.labels
107
+ # or you can get all of the unique ids
108
+ timelines.events.ids
109
+ # or you can get all of the unique tags
110
+ timelines.events.tags
111
+
112
+ # or if you don't want unique whatever, turn that off
113
+ timelines.events.tags(unique: false)
114
+ timelines.events.times(unique: false)
115
+ ```
116
+
117
+ ## Event
118
+ Timeline Events are made up of serveral Event objects. An event object is made up of its unique ID number,
119
+ its label, its tags ( as a set, unique ), the time of the event ( default to its creation time ), the time
120
+ the event was created ( defaults to its creation time ) and a value -- which can be whatever you like, if you
121
+ want to use that ( instead of just stuffing that data in tags ).
122
+
123
+ ```ruby
124
+ # create a new timeline event
125
+ event = OcarinaOfTime::Event.new
126
+
127
+ # accessing event data ( reading ) with data shortcuts
128
+ event.label
129
+ # => false
130
+
131
+ # accessing event data ( to change )
132
+ event.data.label = "Example 1"
133
+
134
+ event.label
135
+ # => "Example 1"
136
+
137
+ # check for tags
138
+ event.tags?
139
+ # => false
140
+
141
+ # add tags as an array or string
142
+ tags = ["Cool", "Sick", "Awesome"]
143
+ tag = "Gnarly"
144
+ event.add_tags(tags)
145
+ event.add_tags(tag)
146
+
147
+ # check for tags again
148
+ event.tags?
149
+ # => true
150
+
151
+ # check out tags data
152
+ event.tags
153
+ # => Set: {"Cool", "Sick", "Awesome", "Gnarly"}
154
+
155
+ # add the same event to two different timelines
156
+ timeline1 = OcarinaOfTime::Line.new
157
+ timeline2 = OcarinaOfTime::Line.new
158
+ timeline1.events.add(event: event)
159
+ # => "bb2aa0a0-68ee-469c-808b-875c7494a3c4"
160
+ timeline2.events.add(event: event)
161
+ # => "bb2aa0a0-68ee-469c-808b-875c7494a3c4"
162
+ ```
163
+
164
+ ## License
165
+
166
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
167
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "ocarina_of_time"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ $: << File.expand_path("../../lib", __FILE__)
2
+ require "ocarina_of_time"
3
+ require "pry"
4
+
5
+ binding.pry
@@ -0,0 +1,56 @@
1
+ # coding: utf-8
2
+ # This file is part of Ocarina of Time
3
+ # See https://github.com/picatz/ocarina_of_time for more information
4
+ # Copyright (C) 2017 Kent 'picat' Gruber
5
+ # This program is published under MIT license.
6
+
7
+ # TODO: Fix inline documentation.
8
+
9
+ require "ocarina_of_time/version"
10
+ require "ocarina_of_time/timeline"
11
+ require "ocarina_of_time/event"
12
+ require "ocarina_of_time/events"
13
+
14
+ require 'set'
15
+ require 'date'
16
+ require 'time'
17
+ require 'ostruct'
18
+ require 'securerandom'
19
+
20
+ # The Ocarina of Time is a ruby gem to manage timelines.
21
+ # @author Kent 'picat' Gruber
22
+ module OcarinaOfTime
23
+ # Easter Egg:
24
+ # /@
25
+ # __ __ /\/
26
+ # /==\ / \_/\/
27
+ # /======\ \/\__ \__
28
+ # /==/\ /\==\ /\_|__ \
29
+ # /==/ || \=\ / / / /_/
30
+ # /=/ /\ || /\ \=\/ /
31
+ # /===/ / \||/ \ \===\
32
+ # /===/ /_________________ \===\
33
+ # /====/ / | / \====\
34
+ # /====/ / | _________ / \ \===\ THE LEGEND OF
35
+ # /==/ / | / / \ / / / __________\_____ ______ ___
36
+ #|===| / |/ /____/ / / \ _____ |\ / \ _ \ \ \
37
+ # \==\ /\ / / / | | /= \| | | | | \ \ / _ \
38
+ # \===\__ \ / \ / / / / | | /===/ | | | | \ \ / / \ \
39
+ # \==\ \ \\ /____/ /_\ // | |_____/| | | | | | | / /___\ \
40
+ # \===\ \ \\\\\\\/ /////// /| _____ | | | | | | | | ___ |
41
+ # \==\/ \\\\/ / ////// \| |/==/ \| | | | | | | | / \ |
42
+ # \==\ _ \\/ / ///// _ | |==/ | | | | / / | | | |
43
+ # \==\ / \ / / /// /|\| |_____/| | |_____/| | |_/ / | | | |
44
+ # \==\ / / / /________/ |/_________|/_________|/_____/ /___\ /___\ ゼルダの伝説
45
+ # \==\ / | /==/
46
+ # \=\ /________________|/=/ OCARINA OF TIME
47
+ # \==\ _____ /==/
48
+ # / \===\ \ / /===/
49
+ # / / /\===\ \_/ /===/
50
+ # / / / \====\ /====/
51
+ # / / / \===|===/
52
+ # |/_/ \===/
53
+ # =
54
+ # credit : http://www.ascii-code.com/ascii-art/video-games/zelda.php
55
+ #
56
+ end
@@ -0,0 +1,64 @@
1
+ module OcarinaOfTime
2
+
3
+ Struct.new("EventData", :id, :label, :tags, :time, :created, :value)
4
+
5
+ class Event
6
+
7
+ attr_reader :data
8
+
9
+ def initialize(args={})
10
+ @data = Struct::EventData.new
11
+ @data.id = SecureRandom.uuid
12
+ @data.label = args[:label] || false
13
+ @data.value = args[:value] || false
14
+ @data.tags = Set.new
15
+ creation_time = Time.now
16
+ @data.time = args[:time] || creation_time
17
+ @data.created = args[:created] || creation_time
18
+ if args[:tags]
19
+ add_tags(args[:tags])
20
+ end
21
+ end
22
+
23
+ def id
24
+ @data.id
25
+ end
26
+
27
+ def label
28
+ @data.label
29
+ end
30
+
31
+ def time
32
+ @data.time
33
+ end
34
+
35
+ def created
36
+ @data.created
37
+ end
38
+
39
+ def time?
40
+ @data.tags.time ? true : false
41
+ end
42
+
43
+ def tags
44
+ @data.tags.to_a
45
+ end
46
+
47
+ def tags?
48
+ @data.tags.empty? ? false : true
49
+ end
50
+
51
+ def add_tags(tags)
52
+ if tags.is_a? Array
53
+ tags.each do |tag|
54
+ @data.tags << tag
55
+ end
56
+ elsif tags.is_a? String
57
+ @data.tags << tags
58
+ end
59
+ end
60
+
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,193 @@
1
+ module OcarinaOfTime
2
+
3
+ class Events
4
+
5
+ attr_reader :all
6
+
7
+ def initialize
8
+ @all = []
9
+ end
10
+
11
+ def by(args={})
12
+ results = []
13
+ if args[:newest]
14
+ @all.each.sort_by { |e| e.time }.each do |event|
15
+ results << event
16
+ end
17
+ elsif args[:oldest]
18
+ @all.each.sort_by { |e| e.time }.reverse.each do |event|
19
+ results << event
20
+ end
21
+ else
22
+ @all
23
+ end
24
+ results.empty? ? false : results
25
+ end
26
+
27
+ def add(args={})
28
+ if args[:event]
29
+ @all << args[:event]
30
+ return args[:event].id
31
+ end
32
+ event = Event.new
33
+ event.data.label = args[:label] || false
34
+ event.add_tags(args[:tags]) if args[:tags]
35
+ event.data.time = args[:time] if args[:time]
36
+ @all << event
37
+ event.id
38
+ end
39
+
40
+ def delete(args={})
41
+ if args[:id]
42
+ @all.delete_if { |e| e.id == args[:id] }
43
+ elsif args[:event]
44
+ @all.delete_if { |e| e == args[:event] }
45
+ else
46
+ return false
47
+ end
48
+ true
49
+ end
50
+
51
+ def update(args={})
52
+ if args[:id]
53
+ @all.each do |event|
54
+ if event.id == args[:id]
55
+ event.add_tags(args[:tags]) if args[:tags]
56
+ event.data.label = args[:label] if args[:label]
57
+ event.data.created = args[:created] if args[:created]
58
+ event.data.value = args[:value] if args[:value]
59
+ end
60
+ end
61
+ elsif args[:label]
62
+ @all.each do |event|
63
+ if event.label == args[:label]
64
+ event.add_tags(args[:tags]) if args[:tags]
65
+ event.data.label = args[:label] if args[:label]
66
+ event.data.created = args[:created] if args[:created]
67
+ event.data.value = args[:value] if args[:value]
68
+ end
69
+ end
70
+ elsif args[:tag]
71
+ @all.each do |event|
72
+ if event.tags.include?(args[:tag])
73
+ event.add_tags(args[:tags]) if args[:tags]
74
+ event.data.label = args[:label] if args[:label]
75
+ event.data.created = args[:created] if args[:created]
76
+ event.data.value = args[:value] if args[:value]
77
+ end
78
+ end
79
+ elsif args[:date]
80
+ @all.each do |event|
81
+ if event.time.to_date == args[:date]
82
+ event.add_tags(args[:tags]) if args[:tags]
83
+ event.data.label = args[:label] if args[:label]
84
+ event.data.created = args[:created] if args[:created]
85
+ event.data.value = args[:value] if args[:value]
86
+ end
87
+ end
88
+ elsif args[:time]
89
+ @all.each do |event|
90
+ if event.time == args[:time]
91
+ event.add_tags(args[:tags]) if args[:tags]
92
+ event.data.label = args[:label] if args[:label]
93
+ event.data.created = args[:created] if args[:created]
94
+ event.data.value = args[:value] if args[:value]
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def find(args={})
101
+ results = Events.new
102
+ if args[:id]
103
+ @all.each { |e| results.all << e if e.id == args[:id] }
104
+ elsif args[:time]
105
+ @all.each { |e| results.all << e if e.time == args[:time] }
106
+ elsif args[:date]
107
+ @all.each { |e| results.all << e if e.time.to_date == args[:date] }
108
+ elsif args[:event]
109
+ @all.each { |e| results.all << e if e == args[:event] }
110
+ elsif args[:label]
111
+ @all.each { |e| results.all << e if e.label == args[:label] }
112
+ elsif args[:labels]
113
+ args[:labels].each do |label|
114
+ @all.each { |e| results.all << e if e.label == label }
115
+ end
116
+ elsif args[:tags]
117
+ args[:tags].each do |tag|
118
+ @all.each { |e| results.all << e if e.tags.include?(tag) }
119
+ end
120
+ elsif args[:tag]
121
+ @all.each { |e| results.all << e if e.tag == args[:tag] }
122
+ else
123
+ return false
124
+ end
125
+ results
126
+ end
127
+
128
+ def ids(args={unique: true})
129
+ if args[:unique]
130
+ ids = Set.new
131
+ else
132
+ ids = []
133
+ end
134
+ @all.each { |e| ids << e.id }
135
+ ids.to_a
136
+ end
137
+
138
+ def times(args={unique: true})
139
+ if args[:unique]
140
+ times = Set.new
141
+ else
142
+ times = []
143
+ end
144
+ @all.each { |e| times << e.time }
145
+ times.to_a
146
+ end
147
+
148
+ def dates(args={unique: true})
149
+ if args[:unique]
150
+ dates = Set.new
151
+ else
152
+ dates = []
153
+ end
154
+ @all.each { |e| dates << e.time.to_date }
155
+ dates.to_a
156
+ end
157
+
158
+ def tags(args={unique: true})
159
+ if args[:unique]
160
+ tags = Set.new
161
+ else
162
+ tags = []
163
+ end
164
+ @all.each do |e|
165
+ e.tags.to_a.each { |t| tags << t }
166
+ end
167
+ tags.to_a
168
+ end
169
+
170
+ def labels(args={unique: true})
171
+ if args[:unique]
172
+ labels = Set.new
173
+ else
174
+ labels = []
175
+ end
176
+ @all.each { |e| labels << e.label }
177
+ labels.to_a
178
+ end
179
+
180
+ def values(args={unique: true})
181
+ if args[:unique]
182
+ values = Set.new
183
+ else
184
+ values = []
185
+ end
186
+ @all.each { |e| values << e.value }
187
+ labels.to_a
188
+ end
189
+
190
+
191
+ end
192
+
193
+ end
@@ -0,0 +1,243 @@
1
+ module OcarinaOfTime
2
+
3
+ # Respresent the logic of a Timeline.
4
+ # @author Kent 'picat' Gruber
5
+ class Timeline
6
+
7
+ attr_accessor :beginning
8
+ attr_accessor :ending
9
+ attr_accessor :events
10
+
11
+ # Create a new **Timeline** object.
12
+ #
13
+ # @param [Hash] args arguments for method
14
+ # @option args [Time] :begin beginning point in time (default: +Time.now+)
15
+ # @option args [Time] :end ending point in time (default: false)
16
+ # @return [void]
17
+ def initialize(args={})
18
+ @beginning = args[:begin] || Time.now
19
+ @ending = args[:end] || false
20
+ @flex = false # have a rigid timeline
21
+ @events = Events.new
22
+ end
23
+
24
+ # Turn on a flexible timeline, where events will change the potential
25
+ # range of the timeline. If a beginning is set, an unflexible timeline
26
+ # will not allow any new events to be set before that time. A flexible timeline
27
+ # would set the newest ending if the event is before the current one. The same logic
28
+ # applies to an ending time which may or may not be set. Meaning, an unflexible timeline
29
+ # makes it very easy to grow ( by moving forward in time ) if there is no ending set.
30
+ def flex(on = true)
31
+ on ? @flex = true : @flex = false
32
+ end
33
+
34
+ # Check if the Timeline is flexible or not.
35
+ #
36
+ # @return[Boolean]
37
+ def flex?
38
+ @flex ? true : false
39
+ end
40
+
41
+ # Check if there's currently a end of time
42
+ # associated with the timeline object.
43
+ #
44
+ # @return[Boolean]
45
+ def ending?
46
+ @ending ? true : false
47
+ end
48
+
49
+ # Check if there's currently a beginning of time
50
+ # associated with the timeline object.
51
+ #
52
+ # @return[Boolean]
53
+ def beginning?
54
+ @beginning ? true : false
55
+ end
56
+
57
+ # Get the difference in time between +two+ points in +time+.
58
+ #
59
+ # @param [Hash] args arguments for method
60
+ # @option args [Time] :begin beginning point in time
61
+ # @option args [Time] :end ending point in time
62
+ # @option args [Time] :seconds get difference in seconds ( default )
63
+ # @option args [Time] :minutes get difference in minutes
64
+ # @option args [Time] :hours get difference in hours
65
+ # @option args [Time] :days get difference in days
66
+ # @option args [Time] :weeks get difference in weeks
67
+ # @option args [Time] :years get difference in years
68
+ # @option args [Time] :decades get difference in decades
69
+ # @option args [Time] :centuries get difference in centuries
70
+ # @return [Float] the difference between two points
71
+ #
72
+ # == Example
73
+ # # generate new timeline
74
+ # timeline = OcarinaOfTime::Line.new
75
+ # # get days between two times
76
+ # timeline.time_between(end: Time.now+87654, days: true)
77
+ # # => 1.0150320438273612
78
+ # timeline.time_between(end: Time.now+8070654, days: true)
79
+ # # => 93.41134454091606
80
+ # timeline.time_between(end: Time.now+8070654, weeks: true)
81
+ # # => 13.344522046096547
82
+ #
83
+ # == Example
84
+ # # generate new time line
85
+ # time_line = OcarinaOfTime::Line.new
86
+ # # set end of time ( default is Time.now for beginning )
87
+ # time_line.end_of_time = Time.now+8070654
88
+ # # get time between the two points in minutes
89
+ # time_line.time_between(minutes: true)
90
+ # # => 134511.16985055877
91
+ #
92
+ def time_between(args={})
93
+ if args[:begin].is_a? Event
94
+ start = args[:begin].time
95
+ else
96
+ start = args[:begin] || @beginning
97
+ end
98
+ raise "unable to determine first (begin) point" unless start
99
+ if args[:end]
100
+ if args[:end].is_a? Event
101
+ stop = args[:end].time
102
+ else
103
+ stop = args[:end]
104
+ end
105
+ else
106
+ stop = @ending if @ending
107
+ raise "unable to determine second (end) point" unless stop
108
+ end
109
+ diff = stop - start
110
+ if args[:seconds]
111
+ return diff
112
+ elsif args[:minutes]
113
+ return diff / 60
114
+ elsif args[:hours]
115
+ return diff / 3600
116
+ elsif args[:days]
117
+ return diff / 86400
118
+ elsif args[:weeks]
119
+ return diff / 604800
120
+ elsif args[:years]
121
+ return diff / 31449600
122
+ elsif args[:decades]
123
+ return diff / 314496000
124
+ elsif args[:centuries]
125
+ return diff / 3144960000
126
+ else
127
+ return diff
128
+ end
129
+ end
130
+
131
+ # Get the days between +two+ points in +time+.
132
+ #
133
+ # @param [Hash] args arguments for method
134
+ # @option args [Time] :begin beginning point in time
135
+ # @option args [Time] :end ending point in time
136
+ # @return [Array<Date>] dates between two points in time
137
+ #
138
+ # == Example
139
+ # # generate new time line
140
+ # time_line = OcarinaOfTime::Line.new
141
+ # # get days between two times
142
+ # time_line.days_between(begin: Time.now - 100000, end: Time.now)
143
+ # # => [#<Date: 2017-02-19 ((2457804j,0s,0n),+0s,2299161j)>, #<Date: 2017-02-20 ((2457805j,0s,0n),+0s,2299161j)>]
144
+ def days_between(args={})
145
+ start = args[:begin] || @beginning
146
+ if args[:end]
147
+ stop = args[:end]
148
+ else
149
+ stop = @ending if @ending
150
+ end
151
+ (start.to_date..stop.to_date).to_a
152
+ end
153
+
154
+ # Parse an array of dates to filter out for specifc days
155
+ # of the week ( Monday .. Sunday ).
156
+ #
157
+ # @param [Hash] arguments for method
158
+ # @option args [Array<Date>] :days array of dates to work with
159
+ # @option args [Boolean] :mondays get mondays
160
+ # @option args [Boolean] :tuesdays get tuesdays
161
+ # @option args [Boolean] :wednesdays get wednesdays
162
+ # @option args [Boolean] :thursdays get thursdays
163
+ # @option args [Boolean] :fridays get fridays
164
+ # @option args [Boolean] :saturdays get saturdays
165
+ # @option args [Boolean] :sundays get sundays
166
+ # @option args [Array<Int>] :years get years
167
+ # @option args [Array<Int>] :months get months, represented as an int
168
+ # @return [Array<Date>] parsed dates
169
+ #
170
+ # == Example
171
+ # # generate new time line
172
+ # time_line = OcarinaOfTime::Line.new
173
+ # # get days between two times
174
+ # days = time_line.days_between(begin: Time.now - 10000000, end: Time.now)
175
+ # # parse days for mondays only
176
+ # time_line.find_days(days: days, mondays: true)
177
+ # # parse days for sundays only
178
+ # time_line.find_days(days: days, sundays: true)
179
+ # # parse days for wednesdays and fridays only
180
+ # time_line.find_days(days: days, wednesdays: true, fridays: true)
181
+ def find_days(args={})
182
+ unless args[:days]
183
+ if @ending and @beginning
184
+ all_days = days_between
185
+ else
186
+ raise "need to specify days to work with"
187
+ end
188
+ else
189
+ all_days = args[:days]
190
+ end
191
+ days = Set.new
192
+ all_days.each do |day|
193
+ days << day if day.monday? and args[:mondays]
194
+ days << day if day.tuesday? and args[:tuesdays]
195
+ days << day if day.wednesday? and args[:wednesdays]
196
+ days << day if day.thursday? and args[:thursdays]
197
+ days << day if day.friday? and args[:fridays]
198
+ days << day if day.saturday? and args[:saturdays]
199
+ days << day if day.sunday? and args[:sundays]
200
+ end
201
+ days.to_a
202
+ end
203
+
204
+ # Parse an array of dates to filter out for specifc dates
205
+ # that match a specific yeay ( 1970, 1994, 2017 .. ect ).
206
+ #
207
+ # @param [Hash] arguments for method
208
+ # @option args [Array<Date>] :days array of dates to work with
209
+ # @option args [Array, Integer] :years get specific years
210
+ # @return [Array<Date>] parsed years
211
+ #
212
+ # == Example
213
+ # # generate new time line
214
+ # time_line = OcarinaOfTime::Line.new
215
+ # time_line.end_of_time = Time.now+8070654
216
+ # # parse days for the year 2017
217
+ # time_line.find_years(years: 2017)
218
+ # # parse days for the year 2016 or 2017
219
+ # time_line.find_years(years: [2016, 2017])
220
+ def find_years(args={})
221
+ unless args[:days]
222
+ if @ending and @beginning
223
+ all_days = days_between
224
+ else
225
+ raise "need to specify days to work with"
226
+ end
227
+ else
228
+ all_days = args[:days]
229
+ end
230
+ days = Set.new
231
+ all_days.each do |day|
232
+ if args[:years]
233
+ if args[:years].is_a? Array
234
+ days << day if args[:years].include? day.year
235
+ elsif args[:years].is_a? Integer
236
+ days << day if args[:years] == day.year
237
+ end
238
+ end
239
+ end
240
+ days.to_a
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,3 @@
1
+ module OcarinaOfTime
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ocarina_of_time/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ocarina_of_time"
8
+ spec.version = OcarinaOfTime::VERSION
9
+ spec.authors = ["Kent Gruber"]
10
+ spec.email = ["kgruber1@emich.edu"]
11
+
12
+ spec.summary = %q{The Ocarina of Time is a ruby gem to manage timelines.}
13
+ spec.description = %q{The Ocarina of Time is a ruby gem to manage timelines through a simple API to contrsuct timelines and manage the events that happen during the liftime of a timeline.}
14
+ spec.homepage = "https://github.com/picatz/Ocarina-of-Time"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "bin"
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.14"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ocarina_of_time
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kent Gruber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: The Ocarina of Time is a ruby gem to manage timelines through a simple
56
+ API to contrsuct timelines and manage the events that happen during the liftime
57
+ of a timeline.
58
+ email:
59
+ - kgruber1@emich.edu
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".rspec"
66
+ - ".travis.yml"
67
+ - CODE_OF_CONDUCT.md
68
+ - Gemfile
69
+ - LICENSE.txt
70
+ - README.md
71
+ - Rakefile
72
+ - bin/console
73
+ - bin/setup
74
+ - examples/debug.rb
75
+ - lib/ocarina_of_time.rb
76
+ - lib/ocarina_of_time/event.rb
77
+ - lib/ocarina_of_time/events.rb
78
+ - lib/ocarina_of_time/timeline.rb
79
+ - lib/ocarina_of_time/version.rb
80
+ - ocarina_of_time.gemspec
81
+ homepage: https://github.com/picatz/Ocarina-of-Time
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.6.8
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: The Ocarina of Time is a ruby gem to manage timelines.
105
+ test_files: []