run_ical 0.5.0 → 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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +33 -0
  3. data/.rubocop.yml +34 -1
  4. data/Gemfile +3 -1
  5. data/README.md +35 -0
  6. data/Rakefile +5 -1
  7. data/exe/run_ical +13 -22
  8. data/lib/run_ical/data/advanced_10_k.rb +2 -2
  9. data/lib/run_ical/data/advanced_10_k.yaml +57 -0
  10. data/lib/run_ical/data/advanced_15_k.rb +2 -2
  11. data/lib/run_ical/data/advanced_15_k.yaml +71 -0
  12. data/lib/run_ical/data/advanced_5_k.rb +1 -1
  13. data/lib/run_ical/data/advanced_5_k.yaml +57 -0
  14. data/lib/run_ical/data/advanced_8_k.rb +8 -0
  15. data/lib/run_ical/data/advanced_8_k.yaml +57 -0
  16. data/lib/run_ical/data/half_marathon_advanced.rb +2 -2
  17. data/lib/run_ical/data/half_marathon_advanced.yaml +85 -0
  18. data/lib/run_ical/data/half_marathon_hm3.rb +1 -1
  19. data/lib/run_ical/data/half_marathon_hm3.yaml +85 -0
  20. data/lib/run_ical/data/half_marathon_intermediate1.rb +2 -2
  21. data/lib/run_ical/data/half_marathon_intermediate1.yaml +85 -0
  22. data/lib/run_ical/data/half_marathon_intermediate2.rb +2 -2
  23. data/lib/run_ical/data/half_marathon_intermediate2.yaml +85 -0
  24. data/lib/run_ical/data/half_marathon_novice1.rb +2 -2
  25. data/lib/run_ical/data/half_marathon_novice1.yaml +85 -0
  26. data/lib/run_ical/data/half_marathon_novice2.rb +2 -2
  27. data/lib/run_ical/data/half_marathon_novice2.yaml +85 -0
  28. data/lib/run_ical/data/half_marathon_walkers.rb +8 -0
  29. data/lib/run_ical/data/half_marathon_walkers.yaml +85 -0
  30. data/lib/run_ical/data/intermediate_10_k.rb +2 -2
  31. data/lib/run_ical/data/intermediate_10_k.yaml +57 -0
  32. data/lib/run_ical/data/intermediate_15_k.rb +2 -2
  33. data/lib/run_ical/data/intermediate_15_k.yaml +71 -0
  34. data/lib/run_ical/data/intermediate_5_k.rb +1 -1
  35. data/lib/run_ical/data/intermediate_5_k.yaml +57 -0
  36. data/lib/run_ical/data/intermediate_8_k.rb +2 -2
  37. data/lib/run_ical/data/intermediate_8_k.yaml +57 -0
  38. data/lib/run_ical/data/marathon_3.rb +8 -0
  39. data/lib/run_ical/data/marathon_3.yaml +169 -0
  40. data/lib/run_ical/data/marathon_advanced1.rb +8 -0
  41. data/lib/run_ical/data/marathon_advanced1.yaml +127 -0
  42. data/lib/run_ical/data/marathon_advanced2.rb +8 -0
  43. data/lib/run_ical/data/marathon_advanced2.yaml +127 -0
  44. data/lib/run_ical/data/marathon_boston_bound.rb +8 -0
  45. data/lib/run_ical/data/marathon_boston_bound.yaml +86 -0
  46. data/lib/run_ical/data/marathon_dopey_challenge.rb +8 -0
  47. data/lib/run_ical/data/marathon_dopey_challenge.yaml +127 -0
  48. data/lib/run_ical/data/marathon_intermediate1.rb +8 -0
  49. data/lib/run_ical/data/marathon_intermediate1.yaml +127 -0
  50. data/lib/run_ical/data/marathon_intermediate2.rb +8 -0
  51. data/lib/run_ical/data/marathon_intermediate2.yaml +127 -0
  52. data/lib/run_ical/data/marathon_novice1.rb +2 -2
  53. data/lib/run_ical/data/marathon_novice1.yaml +127 -0
  54. data/lib/run_ical/data/marathon_novice2.rb +1 -1
  55. data/lib/run_ical/data/marathon_novice2.yaml +90 -89
  56. data/lib/run_ical/data/marathon_novice_supreme.rb +8 -0
  57. data/lib/run_ical/data/marathon_novice_supreme.yaml +211 -0
  58. data/lib/run_ical/data/marathon_personal_best.rb +8 -0
  59. data/lib/run_ical/data/marathon_personal_best.yaml +211 -0
  60. data/lib/run_ical/data/marathon_senior.rb +8 -0
  61. data/lib/run_ical/data/marathon_senior.yaml +57 -0
  62. data/lib/run_ical/data/novice_10_k.rb +2 -2
  63. data/lib/run_ical/data/novice_10_k.yaml +57 -0
  64. data/lib/run_ical/data/novice_15_k.rb +2 -2
  65. data/lib/run_ical/data/novice_15_k.yaml +71 -0
  66. data/lib/run_ical/data/novice_5_k.rb +1 -1
  67. data/lib/run_ical/data/novice_5_k.yaml +57 -0
  68. data/lib/run_ical/data/novice_8_k.rb +2 -2
  69. data/lib/run_ical/data/novice_8_k.yaml +57 -0
  70. data/lib/run_ical/data/walkers_5_k.rb +2 -2
  71. data/lib/run_ical/data/walkers_5_k.yaml +57 -0
  72. data/lib/run_ical/data/walking_10_k.rb +2 -2
  73. data/lib/run_ical/data/walking_10_k.yaml +57 -0
  74. data/lib/run_ical/version.rb +3 -1
  75. data/lib/run_ical.rb +46 -27
  76. data/run_ical.gemspec +15 -10
  77. data/tasks/higdon_programs.yml +179 -0
  78. data/tasks/refresh_data.rake +156 -0
  79. metadata +95 -36
  80. data/.travis.yml +0 -5
@@ -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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: run_ical
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Cashin
@@ -10,19 +10,19 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: yaml
13
+ name: activesupport
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
18
+ version: 5.0.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '0'
25
+ version: 5.0.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: base64
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -51,6 +51,20 @@ dependencies:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: icalendar
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 2.0.0
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.0.0
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: logger
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -94,103 +108,103 @@ dependencies:
94
108
  - !ruby/object:Gem::Version
95
109
  version: '0'
96
110
  - !ruby/object:Gem::Dependency
97
- name: icalendar
111
+ name: yaml
98
112
  requirement: !ruby/object:Gem::Requirement
99
113
  requirements:
100
114
  - - ">="
101
115
  - !ruby/object:Gem::Version
102
- version: 2.0.0
116
+ version: '0'
103
117
  type: :runtime
104
118
  prerelease: false
105
119
  version_requirements: !ruby/object:Gem::Requirement
106
120
  requirements:
107
121
  - - ">="
108
122
  - !ruby/object:Gem::Version
109
- version: 2.0.0
123
+ version: '0'
110
124
  - !ruby/object:Gem::Dependency
111
- name: activesupport
125
+ name: irb
112
126
  requirement: !ruby/object:Gem::Requirement
113
127
  requirements:
114
128
  - - ">="
115
129
  - !ruby/object:Gem::Version
116
- version: 5.0.0
117
- type: :runtime
130
+ version: '0'
131
+ type: :development
118
132
  prerelease: false
119
133
  version_requirements: !ruby/object:Gem::Requirement
120
134
  requirements:
121
135
  - - ">="
122
136
  - !ruby/object:Gem::Version
123
- version: 5.0.0
137
+ version: '0'
124
138
  - !ruby/object:Gem::Dependency
125
- name: bundler
139
+ name: nokogiri
126
140
  requirement: !ruby/object:Gem::Requirement
127
141
  requirements:
128
- - - "~>"
142
+ - - ">="
129
143
  - !ruby/object:Gem::Version
130
- version: '2.0'
144
+ version: '0'
131
145
  type: :development
132
146
  prerelease: false
133
147
  version_requirements: !ruby/object:Gem::Requirement
134
148
  requirements:
135
- - - "~>"
149
+ - - ">="
136
150
  - !ruby/object:Gem::Version
137
- version: '2.0'
151
+ version: '0'
138
152
  - !ruby/object:Gem::Dependency
139
153
  name: rake
140
154
  requirement: !ruby/object:Gem::Requirement
141
155
  requirements:
142
156
  - - "~>"
143
157
  - !ruby/object:Gem::Version
144
- version: '10.0'
158
+ version: '13.0'
145
159
  type: :development
146
160
  prerelease: false
147
161
  version_requirements: !ruby/object:Gem::Requirement
148
162
  requirements:
149
163
  - - "~>"
150
164
  - !ruby/object:Gem::Version
151
- version: '10.0'
165
+ version: '13.0'
152
166
  - !ruby/object:Gem::Dependency
153
- name: rspec
167
+ name: rdoc
154
168
  requirement: !ruby/object:Gem::Requirement
155
169
  requirements:
156
- - - "~>"
170
+ - - ">="
157
171
  - !ruby/object:Gem::Version
158
- version: '3.0'
172
+ version: '0'
159
173
  type: :development
160
174
  prerelease: false
161
175
  version_requirements: !ruby/object:Gem::Requirement
162
176
  requirements:
163
- - - "~>"
177
+ - - ">="
164
178
  - !ruby/object:Gem::Version
165
- version: '3.0'
179
+ version: '0'
166
180
  - !ruby/object:Gem::Dependency
167
- name: irb
181
+ name: rspec
168
182
  requirement: !ruby/object:Gem::Requirement
169
183
  requirements:
170
- - - ">="
184
+ - - "~>"
171
185
  - !ruby/object:Gem::Version
172
- version: '0'
186
+ version: '3.0'
173
187
  type: :development
174
188
  prerelease: false
175
189
  version_requirements: !ruby/object:Gem::Requirement
176
190
  requirements:
177
- - - ">="
191
+ - - "~>"
178
192
  - !ruby/object:Gem::Version
179
- version: '0'
193
+ version: '3.0'
180
194
  - !ruby/object:Gem::Dependency
181
- name: rdoc
195
+ name: rubocop
182
196
  requirement: !ruby/object:Gem::Requirement
183
197
  requirements:
184
- - - ">="
198
+ - - "~>"
185
199
  - !ruby/object:Gem::Version
186
- version: '0'
200
+ version: '1.0'
187
201
  type: :development
188
202
  prerelease: false
189
203
  version_requirements: !ruby/object:Gem::Requirement
190
204
  requirements:
191
- - - ">="
205
+ - - "~>"
192
206
  - !ruby/object:Gem::Version
193
- version: '0'
207
+ version: '1.0'
194
208
  description: Uses Hal Higdon's plans for creating a calendar
195
209
  email:
196
210
  - scashin133@gmail.com
@@ -199,10 +213,10 @@ executables:
199
213
  extensions: []
200
214
  extra_rdoc_files: []
201
215
  files:
216
+ - ".github/workflows/ci.yml"
202
217
  - ".gitignore"
203
218
  - ".rspec"
204
219
  - ".rubocop.yml"
205
- - ".travis.yml"
206
220
  - Gemfile
207
221
  - LICENSE.txt
208
222
  - README.md
@@ -212,30 +226,75 @@ files:
212
226
  - exe/run_ical
213
227
  - lib/run_ical.rb
214
228
  - lib/run_ical/data/advanced_10_k.rb
229
+ - lib/run_ical/data/advanced_10_k.yaml
215
230
  - lib/run_ical/data/advanced_15_k.rb
231
+ - lib/run_ical/data/advanced_15_k.yaml
216
232
  - lib/run_ical/data/advanced_5_k.rb
233
+ - lib/run_ical/data/advanced_5_k.yaml
217
234
  - lib/run_ical/data/advanced_8_k.rb
235
+ - lib/run_ical/data/advanced_8_k.yaml
218
236
  - lib/run_ical/data/half_marathon_advanced.rb
237
+ - lib/run_ical/data/half_marathon_advanced.yaml
219
238
  - lib/run_ical/data/half_marathon_hm3.rb
239
+ - lib/run_ical/data/half_marathon_hm3.yaml
220
240
  - lib/run_ical/data/half_marathon_intermediate1.rb
241
+ - lib/run_ical/data/half_marathon_intermediate1.yaml
221
242
  - lib/run_ical/data/half_marathon_intermediate2.rb
243
+ - lib/run_ical/data/half_marathon_intermediate2.yaml
222
244
  - lib/run_ical/data/half_marathon_novice1.rb
245
+ - lib/run_ical/data/half_marathon_novice1.yaml
223
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
224
250
  - lib/run_ical/data/intermediate_10_k.rb
251
+ - lib/run_ical/data/intermediate_10_k.yaml
225
252
  - lib/run_ical/data/intermediate_15_k.rb
253
+ - lib/run_ical/data/intermediate_15_k.yaml
226
254
  - lib/run_ical/data/intermediate_5_k.rb
255
+ - lib/run_ical/data/intermediate_5_k.yaml
227
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
228
272
  - lib/run_ical/data/marathon_novice1.rb
273
+ - lib/run_ical/data/marathon_novice1.yaml
229
274
  - lib/run_ical/data/marathon_novice2.rb
230
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
231
282
  - lib/run_ical/data/novice_10_k.rb
283
+ - lib/run_ical/data/novice_10_k.yaml
232
284
  - lib/run_ical/data/novice_15_k.rb
285
+ - lib/run_ical/data/novice_15_k.yaml
233
286
  - lib/run_ical/data/novice_5_k.rb
287
+ - lib/run_ical/data/novice_5_k.yaml
234
288
  - lib/run_ical/data/novice_8_k.rb
289
+ - lib/run_ical/data/novice_8_k.yaml
235
290
  - lib/run_ical/data/walkers_5_k.rb
291
+ - lib/run_ical/data/walkers_5_k.yaml
236
292
  - lib/run_ical/data/walking_10_k.rb
293
+ - lib/run_ical/data/walking_10_k.yaml
237
294
  - lib/run_ical/version.rb
238
295
  - run_ical.gemspec
296
+ - tasks/higdon_programs.yml
297
+ - tasks/refresh_data.rake
239
298
  homepage: https://github.com/scashin133/run_ical
240
299
  licenses:
241
300
  - MIT
@@ -247,14 +306,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
247
306
  requirements:
248
307
  - - ">="
249
308
  - !ruby/object:Gem::Version
250
- version: '0'
309
+ version: '3.1'
251
310
  required_rubygems_version: !ruby/object:Gem::Requirement
252
311
  requirements:
253
312
  - - ">="
254
313
  - !ruby/object:Gem::Version
255
314
  version: '0'
256
315
  requirements: []
257
- rubygems_version: 3.6.9
316
+ rubygems_version: 4.0.16
258
317
  specification_version: 4
259
318
  summary: Generate an ical file for a race
260
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