ocarina_of_time 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []