run_ical 0.4.3 → 0.6.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.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +33 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +34 -1
  5. data/Gemfile +3 -1
  6. data/README.md +35 -0
  7. data/Rakefile +5 -1
  8. data/exe/run_ical +13 -22
  9. data/lib/run_ical/data/advanced_10_k.rb +2 -2
  10. data/lib/run_ical/data/advanced_10_k.yaml +57 -0
  11. data/lib/run_ical/data/advanced_15_k.rb +2 -2
  12. data/lib/run_ical/data/advanced_15_k.yaml +71 -0
  13. data/lib/run_ical/data/advanced_5_k.rb +1 -1
  14. data/lib/run_ical/data/advanced_5_k.yaml +57 -0
  15. data/lib/run_ical/data/advanced_8_k.rb +8 -0
  16. data/lib/run_ical/data/advanced_8_k.yaml +57 -0
  17. data/lib/run_ical/data/half_marathon_advanced.rb +2 -2
  18. data/lib/run_ical/data/half_marathon_advanced.yaml +85 -0
  19. data/lib/run_ical/data/half_marathon_hm3.rb +1 -1
  20. data/lib/run_ical/data/half_marathon_hm3.yaml +85 -0
  21. data/lib/run_ical/data/half_marathon_intermediate1.rb +2 -2
  22. data/lib/run_ical/data/half_marathon_intermediate1.yaml +85 -0
  23. data/lib/run_ical/data/half_marathon_intermediate2.rb +2 -2
  24. data/lib/run_ical/data/half_marathon_intermediate2.yaml +85 -0
  25. data/lib/run_ical/data/half_marathon_novice1.rb +2 -2
  26. data/lib/run_ical/data/half_marathon_novice1.yaml +85 -0
  27. data/lib/run_ical/data/half_marathon_novice2.rb +2 -2
  28. data/lib/run_ical/data/half_marathon_novice2.yaml +85 -0
  29. data/lib/run_ical/data/half_marathon_walkers.rb +8 -0
  30. data/lib/run_ical/data/half_marathon_walkers.yaml +85 -0
  31. data/lib/run_ical/data/intermediate_10_k.rb +2 -2
  32. data/lib/run_ical/data/intermediate_10_k.yaml +57 -0
  33. data/lib/run_ical/data/intermediate_15_k.rb +2 -2
  34. data/lib/run_ical/data/intermediate_15_k.yaml +71 -0
  35. data/lib/run_ical/data/intermediate_5_k.rb +1 -1
  36. data/lib/run_ical/data/intermediate_5_k.yaml +57 -0
  37. data/lib/run_ical/data/intermediate_8_k.rb +2 -2
  38. data/lib/run_ical/data/intermediate_8_k.yaml +57 -0
  39. data/lib/run_ical/data/marathon_3.rb +8 -0
  40. data/lib/run_ical/data/marathon_3.yaml +169 -0
  41. data/lib/run_ical/data/marathon_advanced1.rb +8 -0
  42. data/lib/run_ical/data/marathon_advanced1.yaml +127 -0
  43. data/lib/run_ical/data/marathon_advanced2.rb +8 -0
  44. data/lib/run_ical/data/marathon_advanced2.yaml +127 -0
  45. data/lib/run_ical/data/marathon_boston_bound.rb +8 -0
  46. data/lib/run_ical/data/marathon_boston_bound.yaml +86 -0
  47. data/lib/run_ical/data/marathon_dopey_challenge.rb +8 -0
  48. data/lib/run_ical/data/marathon_dopey_challenge.yaml +127 -0
  49. data/lib/run_ical/data/marathon_intermediate1.rb +8 -0
  50. data/lib/run_ical/data/marathon_intermediate1.yaml +127 -0
  51. data/lib/run_ical/data/marathon_intermediate2.rb +8 -0
  52. data/lib/run_ical/data/marathon_intermediate2.yaml +127 -0
  53. data/lib/run_ical/data/marathon_novice1.rb +2 -2
  54. data/lib/run_ical/data/marathon_novice1.yaml +127 -0
  55. data/lib/run_ical/data/marathon_novice2.rb +8 -0
  56. data/lib/run_ical/data/marathon_novice2.yaml +127 -0
  57. data/lib/run_ical/data/marathon_novice_supreme.rb +8 -0
  58. data/lib/run_ical/data/marathon_novice_supreme.yaml +211 -0
  59. data/lib/run_ical/data/marathon_personal_best.rb +8 -0
  60. data/lib/run_ical/data/marathon_personal_best.yaml +211 -0
  61. data/lib/run_ical/data/marathon_senior.rb +8 -0
  62. data/lib/run_ical/data/marathon_senior.yaml +57 -0
  63. data/lib/run_ical/data/novice_10_k.rb +2 -2
  64. data/lib/run_ical/data/novice_10_k.yaml +57 -0
  65. data/lib/run_ical/data/novice_15_k.rb +2 -2
  66. data/lib/run_ical/data/novice_15_k.yaml +71 -0
  67. data/lib/run_ical/data/novice_5_k.rb +1 -1
  68. data/lib/run_ical/data/novice_5_k.yaml +57 -0
  69. data/lib/run_ical/data/novice_8_k.rb +2 -2
  70. data/lib/run_ical/data/novice_8_k.yaml +57 -0
  71. data/lib/run_ical/data/walkers_5_k.rb +2 -2
  72. data/lib/run_ical/data/walkers_5_k.yaml +57 -0
  73. data/lib/run_ical/data/walking_10_k.rb +2 -2
  74. data/lib/run_ical/data/walking_10_k.yaml +57 -0
  75. data/lib/run_ical/version.rb +3 -1
  76. data/lib/run_ical.rb +50 -28
  77. data/run_ical.gemspec +20 -7
  78. data/tasks/higdon_programs.yml +179 -0
  79. data/tasks/refresh_data.rake +156 -0
  80. metadata +188 -20
  81. data/.travis.yml +0 -5
  82. data/Gemfile.lock +0 -52
@@ -0,0 +1,179 @@
1
+ # Source manifest for `rake data:refresh`.
2
+ #
3
+ # One entry per training program. `class` is the public API name passed to
4
+ # RunIcal::Generator.generate(program:) -- never rename an existing one.
5
+ # `weeks` is asserted against the scraped table so a silent site change fails loudly.
6
+ ---
7
+ - class: Novice5K
8
+ file: novice_5_k
9
+ description: "5-K : Novice"
10
+ weeks: 8
11
+ url: https://www.halhigdon.com/training-programs/5k-training/novice-5k/
12
+ - class: Intermediate5K
13
+ file: intermediate_5_k
14
+ description: "5-K : Intermediate"
15
+ weeks: 8
16
+ url: https://www.halhigdon.com/training-programs/5k-training/intermediate-5k/
17
+ - class: Advanced5K
18
+ file: advanced_5_k
19
+ description: "5-K : Advanced"
20
+ weeks: 8
21
+ url: https://www.halhigdon.com/training-programs/5k-training/advanced-5k/
22
+ - class: Walkers5K
23
+ file: walkers_5_k
24
+ description: "5-K - Walkers"
25
+ weeks: 8
26
+ url: https://www.halhigdon.com/training-programs/5k-training/walkers-5k/
27
+
28
+ - class: Novice8K
29
+ file: novice_8_k
30
+ description: "8-K - Novice"
31
+ weeks: 8
32
+ url: https://www.halhigdon.com/training-programs/8k-training/novice-8k/
33
+ - class: Intermediate8K
34
+ file: intermediate_8_k
35
+ description: "8-K - Intermediate"
36
+ weeks: 8
37
+ url: https://www.halhigdon.com/training-programs/8k-training/intermediate-8k/
38
+ - class: Advanced8K
39
+ file: advanced_8_k
40
+ description: "8-K - Advanced"
41
+ weeks: 8
42
+ url: https://www.halhigdon.com/training-programs/8k-training/advanced-8k/
43
+
44
+ - class: Novice10K
45
+ file: novice_10_k
46
+ description: "10-K - Novice"
47
+ weeks: 8
48
+ url: https://www.halhigdon.com/training-programs/10k-training/novice-10k/
49
+ - class: Intermediate10K
50
+ file: intermediate_10_k
51
+ description: "10-K - Intermediate"
52
+ weeks: 8
53
+ url: https://www.halhigdon.com/training-programs/10k-training/intermediate-10k/
54
+ - class: Advanced10K
55
+ file: advanced_10_k
56
+ description: "10-K - Advanced"
57
+ weeks: 8
58
+ url: https://www.halhigdon.com/training-programs/10k-training/advanced-10k/
59
+ - class: Walking10K
60
+ file: walking_10_k
61
+ description: "10-K - Walking"
62
+ weeks: 8
63
+ url: https://www.halhigdon.com/training-programs/10k-training/walkers-10k/
64
+
65
+ - class: Novice15K
66
+ file: novice_15_k
67
+ description: "15-K - Novice"
68
+ weeks: 10
69
+ url: https://www.halhigdon.com/training-programs/15k-10-mile-training/novice-15k-10-mile/
70
+ - class: Intermediate15K
71
+ file: intermediate_15_k
72
+ description: "15-K - Intermediate"
73
+ weeks: 10
74
+ url: https://www.halhigdon.com/training-programs/15k-10-mile-training/intermediate-15k-10-mile/
75
+ - class: Advanced15K
76
+ file: advanced_15_k
77
+ description: "15-K - Advanced"
78
+ weeks: 10
79
+ url: https://www.halhigdon.com/training-programs/15k-10-mile-training/advanced-15k-10-mile/
80
+
81
+ - class: HalfMarathonNovice1
82
+ file: half_marathon_novice1
83
+ description: "Half Marathon - Novice 1"
84
+ weeks: 12
85
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/novice-1-half-marathon/
86
+ - class: HalfMarathonNovice2
87
+ file: half_marathon_novice2
88
+ description: "Half Marathon - Novice 2"
89
+ weeks: 12
90
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/novice-2-half-marathon/
91
+ - class: HalfMarathonIntermediate1
92
+ file: half_marathon_intermediate1
93
+ description: "Half Marathon - Intermediate 1"
94
+ weeks: 12
95
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/intermediate-1-half-marathon/
96
+ - class: HalfMarathonIntermediate2
97
+ file: half_marathon_intermediate2
98
+ description: "Half Marathon - Intermediate 2"
99
+ weeks: 12
100
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/intermediate-2-half-marathon/
101
+ - class: HalfMarathonAdvanced
102
+ file: half_marathon_advanced
103
+ description: "Half Marathon - Advanced"
104
+ weeks: 12
105
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/advanced-half-marathon/
106
+ - class: HalfMarathonHM3
107
+ file: half_marathon_hm3
108
+ description: "Half Marathon - HM3"
109
+ weeks: 12
110
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/half-marathon-3/
111
+ - class: HalfMarathonWalkers
112
+ file: half_marathon_walkers
113
+ description: "Half Marathon - Walkers"
114
+ weeks: 12
115
+ url: https://www.halhigdon.com/training-programs/half-marathon-training/walkers-half-marathon/
116
+
117
+ - class: MarathonNovice1
118
+ file: marathon_novice1
119
+ description: "Marathon : Novice 1"
120
+ weeks: 18
121
+ url: https://www.halhigdon.com/training-programs/marathon-training/novice-1-marathon/
122
+ - class: MarathonNovice2
123
+ file: marathon_novice2
124
+ description: "Marathon : Novice 2"
125
+ weeks: 18
126
+ url: https://www.halhigdon.com/training-programs/marathon-training/novice-2-marathon/
127
+ - class: MarathonIntermediate1
128
+ file: marathon_intermediate1
129
+ description: "Marathon : Intermediate 1"
130
+ weeks: 18
131
+ url: https://www.halhigdon.com/training-programs/marathon-training/intermediate-1-marathon/
132
+ - class: MarathonIntermediate2
133
+ file: marathon_intermediate2
134
+ description: "Marathon : Intermediate 2"
135
+ weeks: 18
136
+ url: https://www.halhigdon.com/training-programs/marathon-training/intermediate-2-marathon/
137
+ - class: MarathonAdvanced1
138
+ file: marathon_advanced1
139
+ description: "Marathon : Advanced 1"
140
+ weeks: 18
141
+ url: https://www.halhigdon.com/training-programs/marathon-training/advanced-1-marathon/
142
+ - class: MarathonAdvanced2
143
+ file: marathon_advanced2
144
+ description: "Marathon : Advanced 2"
145
+ weeks: 18
146
+ url: https://www.halhigdon.com/training-programs/marathon-training/advanced-2-marathon/
147
+ - class: MarathonNoviceSupreme
148
+ file: marathon_novice_supreme
149
+ description: "Marathon : Novice Supreme"
150
+ weeks: 30
151
+ url: https://www.halhigdon.com/training-programs/marathon-training/novice-supreme/
152
+ - class: MarathonPersonalBest
153
+ file: marathon_personal_best
154
+ description: "Marathon : Personal Best"
155
+ weeks: 30
156
+ url: https://www.halhigdon.com/training-programs/marathon-training/personal-best/
157
+ - class: MarathonSenior
158
+ file: marathon_senior
159
+ description: "Marathon : Senior"
160
+ weeks: 8
161
+ url: https://www.halhigdon.com/training-programs/marathon-training/senior/
162
+ - class: Marathon3
163
+ file: marathon_3
164
+ description: "Marathon : Marathon 3"
165
+ weeks: 24
166
+ url: https://www.halhigdon.com/training-programs/marathon-training/marathon-3/
167
+ - class: MarathonDopeyChallenge
168
+ file: marathon_dopey_challenge
169
+ description: "Marathon : Dopey Challenge"
170
+ weeks: 18
171
+ url: https://www.halhigdon.com/training-programs/marathon-training/dopey-challenge/
172
+ # Boston is run on Patriots' Day (a Monday), so the final table row holds a single
173
+ # Monday cell instead of a full week. The scraper truncates to 12 full weeks + race day.
174
+ - class: MarathonBostonBound
175
+ file: marathon_boston_bound
176
+ description: "Marathon : Boston Bound"
177
+ weeks: 13
178
+ partial_final_week: true
179
+ url: https://www.halhigdon.com/training-programs/marathon-training/boston-bound/
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "yaml"
6
+
7
+ # Re-scrapes the training plans in lib/run_ical/data from halhigdon.com.
8
+ #
9
+ # rake data:refresh # every program in tasks/higdon_programs.yml
10
+ # rake data:refresh[Novice5K] # just one
11
+ #
12
+ # Every page renders the schedule as a static table with a `Week | Mon..Sun` header
13
+ # row, in miles first and kilometres second. We take the miles table, flatten it
14
+ # row-major into one activity per day, and write a YAML sidecar plus a loader stub.
15
+ module HigdonScraper
16
+ DATA_DIR = File.expand_path("../lib/run_ical/data", __dir__)
17
+ MANIFEST = File.expand_path("higdon_programs.yml", __dir__)
18
+ DAYS_PER_WEEK = 7
19
+
20
+ # The final cell of a plan is the race itself. Higdon isn't consistent about it:
21
+ # most read "<distance> Race", but Novice 10K ends on "10K Run", Walking 10K on
22
+ # "10K Walk", and the marathons on a bare "Marathon" / "Boston Marathon".
23
+ RACE = /\A(\d+K (Race|Run|Walk)|(Boston |Half )?Marathon)\z/i
24
+
25
+ class ScrapeError < StandardError; end
26
+
27
+ module_function
28
+
29
+ # Every program in the manifest, or the single one named.
30
+ def programs(only = nil)
31
+ all = YAML.safe_load_file(MANIFEST)
32
+ return all unless only
33
+
34
+ selected = all.select { |program| program["class"] == only }
35
+ raise ScrapeError, "unknown program #{only}" if selected.empty?
36
+
37
+ selected
38
+ end
39
+
40
+ def scrape(program)
41
+ rows = schedule_rows(Nokogiri::HTML(fetch(program["url"])), program)
42
+ unless rows.size == program["weeks"]
43
+ raise ScrapeError, "#{program['class']}: expected #{program['weeks']} weeks, got #{rows.size}"
44
+ end
45
+
46
+ activities = rows.flat_map { |row| week_activities(row) }
47
+ activities = trim_partial_final_week(activities) if program["partial_final_week"]
48
+ validate!(program, activities)
49
+ activities
50
+ end
51
+
52
+ def fetch(url)
53
+ uri = URI(url)
54
+ response = Net::HTTP.get_response(uri, "User-Agent" => "run_ical data refresh")
55
+ raise ScrapeError, "#{url}: HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
56
+
57
+ response.body
58
+ end
59
+
60
+ def schedule_rows(doc, program)
61
+ table = schedule_table(doc)
62
+ raise ScrapeError, "#{program['class']}: no schedule table found" unless table
63
+
64
+ table.css("tbody tr").map { |tr| tr.css("td").map { |td| cell_text(td) } }.reject(&:empty?)
65
+ end
66
+
67
+ # The first table whose header starts "Week | Mon" -- the walkers half marathon page
68
+ # leads with an unrelated pace legend, and the kilometre table always follows the
69
+ # miles one, so first-match gives us miles.
70
+ def schedule_table(doc)
71
+ doc.css("table").find do |candidate|
72
+ headers = candidate.css("th").map { |th| cell_text(th) }
73
+ headers[0] == "Week" && headers[1] == "Mon"
74
+ end
75
+ end
76
+
77
+ # Cells are taken by position, not by header: a few pages ship an empty <th> where
78
+ # "Wed" belongs. The 8K pages add a ninth "Miles" total column, and on the novice
79
+ # page the race sits in it rather than under Sunday -- pull it back onto race day.
80
+ def week_activities(row)
81
+ week = row[1, DAYS_PER_WEEK]
82
+ total = row[DAYS_PER_WEEK + 1]
83
+ week[-1] = total if total&.match?(RACE)
84
+ week
85
+ end
86
+
87
+ # Boston's last row is a lone Monday race day padded with six empty cells.
88
+ def trim_partial_final_week(activities)
89
+ race = activities.reverse.find { |activity| !activity.empty? }
90
+ activities.take(activities.size - DAYS_PER_WEEK) << race
91
+ end
92
+
93
+ def validate!(program, activities)
94
+ blank = activities.index(&:empty?)
95
+ raise ScrapeError, "#{program['class']}: empty activity at index #{blank}" if blank
96
+
97
+ expected = expected_size(program)
98
+ unless activities.size == expected
99
+ raise ScrapeError, "#{program['class']}: expected #{expected} days, got #{activities.size}"
100
+ end
101
+ return if activities.last.match?(RACE)
102
+
103
+ raise ScrapeError, "#{program['class']}: plan ends on #{activities.last.inspect}, not a race"
104
+ end
105
+
106
+ def expected_size(program)
107
+ weeks = program["weeks"]
108
+ return weeks * DAYS_PER_WEEK unless program["partial_final_week"]
109
+
110
+ ((weeks - 1) * DAYS_PER_WEEK) + 1
111
+ end
112
+
113
+ # Higdon's markup is littered with non-breaking spaces and hard line breaks.
114
+ def cell_text(node)
115
+ node.text.gsub(/[[:space:]]+/, " ").strip
116
+ end
117
+
118
+ def write(program, activities)
119
+ write_yaml(program, activities)
120
+ write_loader(program)
121
+ end
122
+
123
+ # Ruby's emitter quotes numeric-looking strings, which keeps the marathon plans'
124
+ # bare mileage cells ("6", "20") loading back as Strings.
125
+ def write_yaml(program, activities)
126
+ body = activities.map { |activity| { "activity" => activity } }
127
+ File.write(File.join(DATA_DIR, "#{program['file']}.yaml"), body.to_yaml)
128
+ end
129
+
130
+ def write_loader(program)
131
+ File.write(File.join(DATA_DIR, "#{program['file']}.rb"), <<~RUBY)
132
+ module RunIcal
133
+ module Data
134
+ class #{program['class']}
135
+ DESCRIPTION = #{program['description'].inspect}
136
+ DATA = YAML.safe_load_file(File.join(__dir__, '#{program['file']}.yaml'), symbolize_names: true)
137
+ end
138
+ end
139
+ end
140
+ RUBY
141
+ end
142
+ end
143
+
144
+ namespace :data do
145
+ desc "Re-scrape training plan data from halhigdon.com (optionally one program)"
146
+ task :refresh, [:program] do |_t, args|
147
+ require "nokogiri"
148
+
149
+ HigdonScraper.programs(args[:program]).each do |program|
150
+ activities = HigdonScraper.scrape(program)
151
+ HigdonScraper.write(program, activities)
152
+ puts format("%<name>-26s %<days>3d days %<race>s",
153
+ name: program["class"], days: activities.size, race: activities.last)
154
+ end
155
+ end
156
+ end
metadata CHANGED
@@ -1,15 +1,56 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_ical
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Cashin
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2019-06-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: activesupport
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 5.0.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 5.0.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: base64
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: bigdecimal
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
13
54
  - !ruby/object:Gem::Dependency
14
55
  name: icalendar
15
56
  requirement: !ruby/object:Gem::Requirement
@@ -25,47 +66,117 @@ dependencies:
25
66
  - !ruby/object:Gem::Version
26
67
  version: 2.0.0
27
68
  - !ruby/object:Gem::Dependency
28
- name: activesupport
69
+ name: logger
29
70
  requirement: !ruby/object:Gem::Requirement
30
71
  requirements:
31
72
  - - ">="
32
73
  - !ruby/object:Gem::Version
33
- version: 5.0.0
74
+ version: '0'
34
75
  type: :runtime
35
76
  prerelease: false
36
77
  version_requirements: !ruby/object:Gem::Requirement
37
78
  requirements:
38
79
  - - ">="
39
80
  - !ruby/object:Gem::Version
40
- version: 5.0.0
81
+ version: '0'
41
82
  - !ruby/object:Gem::Dependency
42
- name: bundler
83
+ name: mutex_m
43
84
  requirement: !ruby/object:Gem::Requirement
44
85
  requirements:
45
- - - "~>"
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: ostruct
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: yaml
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
46
122
  - !ruby/object:Gem::Version
47
- version: '2.0'
123
+ version: '0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: irb
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
48
131
  type: :development
49
132
  prerelease: false
50
133
  version_requirements: !ruby/object:Gem::Requirement
51
134
  requirements:
52
- - - "~>"
135
+ - - ">="
53
136
  - !ruby/object:Gem::Version
54
- version: '2.0'
137
+ version: '0'
138
+ - !ruby/object:Gem::Dependency
139
+ name: nokogiri
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
55
152
  - !ruby/object:Gem::Dependency
56
153
  name: rake
57
154
  requirement: !ruby/object:Gem::Requirement
58
155
  requirements:
59
156
  - - "~>"
60
157
  - !ruby/object:Gem::Version
61
- version: '10.0'
158
+ version: '13.0'
62
159
  type: :development
63
160
  prerelease: false
64
161
  version_requirements: !ruby/object:Gem::Requirement
65
162
  requirements:
66
163
  - - "~>"
67
164
  - !ruby/object:Gem::Version
68
- version: '10.0'
165
+ version: '13.0'
166
+ - !ruby/object:Gem::Dependency
167
+ name: rdoc
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
69
180
  - !ruby/object:Gem::Dependency
70
181
  name: rspec
71
182
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +191,20 @@ dependencies:
80
191
  - - "~>"
81
192
  - !ruby/object:Gem::Version
82
193
  version: '3.0'
194
+ - !ruby/object:Gem::Dependency
195
+ name: rubocop
196
+ requirement: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: '1.0'
201
+ type: :development
202
+ prerelease: false
203
+ version_requirements: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '1.0'
83
208
  description: Uses Hal Higdon's plans for creating a calendar
84
209
  email:
85
210
  - scashin133@gmail.com
@@ -88,12 +213,11 @@ executables:
88
213
  extensions: []
89
214
  extra_rdoc_files: []
90
215
  files:
216
+ - ".github/workflows/ci.yml"
91
217
  - ".gitignore"
92
218
  - ".rspec"
93
219
  - ".rubocop.yml"
94
- - ".travis.yml"
95
220
  - Gemfile
96
- - Gemfile.lock
97
221
  - LICENSE.txt
98
222
  - README.md
99
223
  - Rakefile
@@ -102,33 +226,79 @@ files:
102
226
  - exe/run_ical
103
227
  - lib/run_ical.rb
104
228
  - lib/run_ical/data/advanced_10_k.rb
229
+ - lib/run_ical/data/advanced_10_k.yaml
105
230
  - lib/run_ical/data/advanced_15_k.rb
231
+ - lib/run_ical/data/advanced_15_k.yaml
106
232
  - lib/run_ical/data/advanced_5_k.rb
233
+ - lib/run_ical/data/advanced_5_k.yaml
107
234
  - lib/run_ical/data/advanced_8_k.rb
235
+ - lib/run_ical/data/advanced_8_k.yaml
108
236
  - lib/run_ical/data/half_marathon_advanced.rb
237
+ - lib/run_ical/data/half_marathon_advanced.yaml
109
238
  - lib/run_ical/data/half_marathon_hm3.rb
239
+ - lib/run_ical/data/half_marathon_hm3.yaml
110
240
  - lib/run_ical/data/half_marathon_intermediate1.rb
241
+ - lib/run_ical/data/half_marathon_intermediate1.yaml
111
242
  - lib/run_ical/data/half_marathon_intermediate2.rb
243
+ - lib/run_ical/data/half_marathon_intermediate2.yaml
112
244
  - lib/run_ical/data/half_marathon_novice1.rb
245
+ - lib/run_ical/data/half_marathon_novice1.yaml
113
246
  - lib/run_ical/data/half_marathon_novice2.rb
247
+ - lib/run_ical/data/half_marathon_novice2.yaml
248
+ - lib/run_ical/data/half_marathon_walkers.rb
249
+ - lib/run_ical/data/half_marathon_walkers.yaml
114
250
  - lib/run_ical/data/intermediate_10_k.rb
251
+ - lib/run_ical/data/intermediate_10_k.yaml
115
252
  - lib/run_ical/data/intermediate_15_k.rb
253
+ - lib/run_ical/data/intermediate_15_k.yaml
116
254
  - lib/run_ical/data/intermediate_5_k.rb
255
+ - lib/run_ical/data/intermediate_5_k.yaml
117
256
  - lib/run_ical/data/intermediate_8_k.rb
257
+ - lib/run_ical/data/intermediate_8_k.yaml
258
+ - lib/run_ical/data/marathon_3.rb
259
+ - lib/run_ical/data/marathon_3.yaml
260
+ - lib/run_ical/data/marathon_advanced1.rb
261
+ - lib/run_ical/data/marathon_advanced1.yaml
262
+ - lib/run_ical/data/marathon_advanced2.rb
263
+ - lib/run_ical/data/marathon_advanced2.yaml
264
+ - lib/run_ical/data/marathon_boston_bound.rb
265
+ - lib/run_ical/data/marathon_boston_bound.yaml
266
+ - lib/run_ical/data/marathon_dopey_challenge.rb
267
+ - lib/run_ical/data/marathon_dopey_challenge.yaml
268
+ - lib/run_ical/data/marathon_intermediate1.rb
269
+ - lib/run_ical/data/marathon_intermediate1.yaml
270
+ - lib/run_ical/data/marathon_intermediate2.rb
271
+ - lib/run_ical/data/marathon_intermediate2.yaml
118
272
  - lib/run_ical/data/marathon_novice1.rb
273
+ - lib/run_ical/data/marathon_novice1.yaml
274
+ - lib/run_ical/data/marathon_novice2.rb
275
+ - lib/run_ical/data/marathon_novice2.yaml
276
+ - lib/run_ical/data/marathon_novice_supreme.rb
277
+ - lib/run_ical/data/marathon_novice_supreme.yaml
278
+ - lib/run_ical/data/marathon_personal_best.rb
279
+ - lib/run_ical/data/marathon_personal_best.yaml
280
+ - lib/run_ical/data/marathon_senior.rb
281
+ - lib/run_ical/data/marathon_senior.yaml
119
282
  - lib/run_ical/data/novice_10_k.rb
283
+ - lib/run_ical/data/novice_10_k.yaml
120
284
  - lib/run_ical/data/novice_15_k.rb
285
+ - lib/run_ical/data/novice_15_k.yaml
121
286
  - lib/run_ical/data/novice_5_k.rb
287
+ - lib/run_ical/data/novice_5_k.yaml
122
288
  - lib/run_ical/data/novice_8_k.rb
289
+ - lib/run_ical/data/novice_8_k.yaml
123
290
  - lib/run_ical/data/walkers_5_k.rb
291
+ - lib/run_ical/data/walkers_5_k.yaml
124
292
  - lib/run_ical/data/walking_10_k.rb
293
+ - lib/run_ical/data/walking_10_k.yaml
125
294
  - lib/run_ical/version.rb
126
295
  - run_ical.gemspec
296
+ - tasks/higdon_programs.yml
297
+ - tasks/refresh_data.rake
127
298
  homepage: https://github.com/scashin133/run_ical
128
299
  licenses:
129
300
  - MIT
130
301
  metadata: {}
131
- post_install_message:
132
302
  rdoc_options: []
133
303
  require_paths:
134
304
  - lib
@@ -136,16 +306,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
306
  requirements:
137
307
  - - ">="
138
308
  - !ruby/object:Gem::Version
139
- version: '0'
309
+ version: '3.1'
140
310
  required_rubygems_version: !ruby/object:Gem::Requirement
141
311
  requirements:
142
312
  - - ">="
143
313
  - !ruby/object:Gem::Version
144
314
  version: '0'
145
315
  requirements: []
146
- rubyforge_project:
147
- rubygems_version: 2.5.2.1
148
- signing_key:
316
+ rubygems_version: 4.0.16
149
317
  specification_version: 4
150
318
  summary: Generate an ical file for a race
151
319
  test_files: []
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.3.5
5
- before_install: gem install bundler -v 1.16.0