aoc_cli 0.2.2 → 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.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +88 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +187 -0
  8. data/README.md +88 -282
  9. data/Rakefile +9 -2
  10. data/Steepfile +13 -0
  11. data/aoc_cli.gemspec +36 -26
  12. data/db/migrate/1_create_events.rb +14 -0
  13. data/db/migrate/2_create_puzzles.rb +21 -0
  14. data/db/migrate/3_create_stats.rb +19 -0
  15. data/db/migrate/4_create_attempts.rb +19 -0
  16. data/db/migrate/5_create_locations.rb +17 -0
  17. data/db/migrate/6_create_puzzle_dir_sync_logs.rb +18 -0
  18. data/exe/aoc +5 -0
  19. data/lib/aoc_cli/components/attempts_table.erb +5 -0
  20. data/lib/aoc_cli/components/attempts_table.rb +58 -0
  21. data/lib/aoc_cli/components/docs_component.erb +19 -0
  22. data/lib/aoc_cli/components/docs_component.rb +41 -0
  23. data/lib/aoc_cli/components/errors_component.erb +8 -0
  24. data/lib/aoc_cli/components/errors_component.rb +36 -0
  25. data/lib/aoc_cli/components/progress_table.erb +1 -0
  26. data/lib/aoc_cli/components/progress_table.rb +43 -0
  27. data/lib/aoc_cli/components/puzzle_sync_component.erb +2 -0
  28. data/lib/aoc_cli/components/puzzle_sync_component.rb +26 -0
  29. data/lib/aoc_cli/configurators/session_configurator.rb +7 -0
  30. data/lib/aoc_cli/controllers/application_controller.rb +27 -0
  31. data/lib/aoc_cli/controllers/concerns/error_concern.rb +17 -0
  32. data/lib/aoc_cli/controllers/concerns/location_concern.rb +79 -0
  33. data/lib/aoc_cli/controllers/default_controller.rb +9 -0
  34. data/lib/aoc_cli/controllers/event_controller.rb +35 -0
  35. data/lib/aoc_cli/controllers/help/event_controller.rb +11 -0
  36. data/lib/aoc_cli/controllers/help/puzzle_controller.rb +13 -0
  37. data/lib/aoc_cli/controllers/puzzle_controller.rb +39 -0
  38. data/lib/aoc_cli/core/attempt_parser.rb +69 -0
  39. data/lib/aoc_cli/core/processor.rb +32 -0
  40. data/lib/aoc_cli/core/repository.rb +74 -0
  41. data/lib/aoc_cli/core/request.rb +37 -0
  42. data/lib/aoc_cli/core/resource.rb +39 -0
  43. data/lib/aoc_cli/core/stats_parser.rb +43 -0
  44. data/lib/aoc_cli/helpers/table_generator.rb +64 -0
  45. data/lib/aoc_cli/helpers/view_helper.rb +35 -0
  46. data/lib/aoc_cli/models/attempt.rb +67 -0
  47. data/lib/aoc_cli/models/event.rb +9 -0
  48. data/lib/aoc_cli/models/location.rb +24 -0
  49. data/lib/aoc_cli/models/puzzle.rb +28 -0
  50. data/lib/aoc_cli/models/puzzle_dir_sync_log.rb +14 -0
  51. data/lib/aoc_cli/models/stats.rb +43 -0
  52. data/lib/aoc_cli/presenters/attempt_presenter.rb +29 -0
  53. data/lib/aoc_cli/presenters/puzzle_presenter.rb +29 -0
  54. data/lib/aoc_cli/presenters/stats_presenter.rb +32 -0
  55. data/lib/aoc_cli/processors/event_initialiser.rb +64 -0
  56. data/lib/aoc_cli/processors/puzzle_dir_synchroniser.rb +80 -0
  57. data/lib/aoc_cli/processors/puzzle_initialiser.rb +91 -0
  58. data/lib/aoc_cli/processors/puzzle_refresher.rb +27 -0
  59. data/lib/aoc_cli/processors/resource_attacher.rb +22 -0
  60. data/lib/aoc_cli/processors/solution_poster.rb +72 -0
  61. data/lib/aoc_cli/processors/stats_initialiser.rb +36 -0
  62. data/lib/aoc_cli/processors/stats_refresher.rb +23 -0
  63. data/lib/aoc_cli/validators/collection_type_validator.rb +57 -0
  64. data/lib/aoc_cli/validators/event_year_validator.rb +42 -0
  65. data/lib/aoc_cli/validators/included_validator.rb +21 -0
  66. data/lib/aoc_cli/validators/integer_validator.rb +32 -0
  67. data/lib/aoc_cli/validators/path_validator.rb +39 -0
  68. data/lib/aoc_cli/validators/type_validator.rb +54 -0
  69. data/lib/aoc_cli/version.rb +1 -1
  70. data/lib/aoc_cli/views/event/attach.erb +3 -0
  71. data/lib/aoc_cli/views/event/init.erb +3 -0
  72. data/lib/aoc_cli/views/help/event/attach.erb +32 -0
  73. data/lib/aoc_cli/views/help/event/init.erb +38 -0
  74. data/lib/aoc_cli/views/help/event/progress.erb +12 -0
  75. data/lib/aoc_cli/views/help/puzzle/attempts.erb +12 -0
  76. data/lib/aoc_cli/views/help/puzzle/init.erb +31 -0
  77. data/lib/aoc_cli/views/help/puzzle/solve.erb +33 -0
  78. data/lib/aoc_cli/views/help/puzzle/sync.erb +32 -0
  79. data/lib/aoc_cli/views/puzzle/init.erb +3 -0
  80. data/lib/aoc_cli/views/puzzle/solve.erb +10 -0
  81. data/lib/aoc_cli.rb +32 -16
  82. data/rbs_collection.lock.yaml +168 -0
  83. data/rbs_collection.yaml +28 -0
  84. data/sig/aoc_cli/components/attempts_table.rbs +29 -0
  85. data/sig/aoc_cli/components/docs_component.rbs +15 -0
  86. data/sig/aoc_cli/components/errors_component.rbs +19 -0
  87. data/sig/aoc_cli/components/progress_table.rbs +28 -0
  88. data/sig/aoc_cli/components/puzzle_sync_component.rbs +19 -0
  89. data/sig/aoc_cli/configurators/session_configurator.rbs +7 -0
  90. data/sig/aoc_cli/controllers/application_controller.rbs +12 -0
  91. data/sig/aoc_cli/controllers/concerns/error_concern.rbs +9 -0
  92. data/sig/aoc_cli/controllers/concerns/location_concern.rbs +35 -0
  93. data/sig/aoc_cli/controllers/default_controller.rbs +7 -0
  94. data/sig/aoc_cli/controllers/event_controller.rbs +18 -0
  95. data/sig/aoc_cli/controllers/help/event_controller.rbs +11 -0
  96. data/sig/aoc_cli/controllers/help/puzzle_controller.rbs +13 -0
  97. data/sig/aoc_cli/controllers/puzzle_controller.rbs +15 -0
  98. data/sig/aoc_cli/core/attempt_parser.rbs +41 -0
  99. data/sig/aoc_cli/core/processor.rbs +25 -0
  100. data/sig/aoc_cli/core/repository.rbs +25 -0
  101. data/sig/aoc_cli/core/request.rbs +29 -0
  102. data/sig/aoc_cli/core/resource.rbs +25 -0
  103. data/sig/aoc_cli/core/stats_parser.rbs +23 -0
  104. data/sig/aoc_cli/helpers/table_generator.rbs +36 -0
  105. data/sig/aoc_cli/helpers/view_helper.rbs +15 -0
  106. data/sig/aoc_cli/models/attempt.rbs +35 -0
  107. data/sig/aoc_cli/models/event.rbs +17 -0
  108. data/sig/aoc_cli/models/location.rbs +19 -0
  109. data/sig/aoc_cli/models/puzzle.rbs +28 -0
  110. data/sig/aoc_cli/models/puzzle_dir_sync_log.rbs +11 -0
  111. data/sig/aoc_cli/models/stats.rbs +53 -0
  112. data/sig/aoc_cli/presenters/attempt_presenter.rbs +13 -0
  113. data/sig/aoc_cli/presenters/puzzle_presenter.rbs +19 -0
  114. data/sig/aoc_cli/presenters/stats_presenter.rbs +19 -0
  115. data/sig/aoc_cli/processors/event_initialiser.rbs +26 -0
  116. data/sig/aoc_cli/processors/puzzle_dir_synchroniser.rbs +40 -0
  117. data/sig/aoc_cli/processors/puzzle_initialiser.rbs +37 -0
  118. data/sig/aoc_cli/processors/puzzle_refresher.rbs +21 -0
  119. data/sig/aoc_cli/processors/resource_attacher.rbs +16 -0
  120. data/sig/aoc_cli/processors/solution_poster.rbs +34 -0
  121. data/sig/aoc_cli/processors/stats_initialiser.rbs +15 -0
  122. data/sig/aoc_cli/processors/stats_refresher.rbs +19 -0
  123. data/sig/aoc_cli/validators/collection_type_validator.rbs +24 -0
  124. data/sig/aoc_cli/validators/event_year_validator.rbs +19 -0
  125. data/sig/aoc_cli/validators/included_validator.rbs +11 -0
  126. data/sig/aoc_cli/validators/integer_validator.rbs +15 -0
  127. data/sig/aoc_cli/validators/path_validator.rbs +17 -0
  128. data/sig/aoc_cli/validators/type_validator.rbs +22 -0
  129. data/sig/aoc_cli.rbs +6 -0
  130. data/sig/http.rbs +3 -0
  131. data/sig/kangaru.rbs +5 -0
  132. data/sig/nokogiri.rbs +3 -0
  133. data/sig/reverse_markdown.rbs +3 -0
  134. metadata +142 -34
  135. data/.gitignore +0 -5
  136. data/bin/aoc +0 -4
  137. data/bin/console +0 -15
  138. data/bin/setup +0 -7
  139. data/lib/aoc_cli/commands.rb +0 -232
  140. data/lib/aoc_cli/database.rb +0 -224
  141. data/lib/aoc_cli/day.rb +0 -124
  142. data/lib/aoc_cli/db/reddit.db +0 -0
  143. data/lib/aoc_cli/errors.rb +0 -275
  144. data/lib/aoc_cli/files.rb +0 -163
  145. data/lib/aoc_cli/help.rb +0 -77
  146. data/lib/aoc_cli/interface.rb +0 -81
  147. data/lib/aoc_cli/paths.rb +0 -101
  148. data/lib/aoc_cli/solve.rb +0 -104
  149. data/lib/aoc_cli/tables.rb +0 -138
  150. data/lib/aoc_cli/tools.rb +0 -120
  151. data/lib/aoc_cli/year.rb +0 -116
  152. data/sample/aoc.rc +0 -21
@@ -1,224 +0,0 @@
1
- module AocCli
2
- module Database
3
- def self.correct(attempt:)
4
- attempt = Attempt.new(attempt:attempt).correct
5
- Stats::Complete.new(n:attempt.count_attempts).update
6
- Calendar::Part.new.increment
7
- end
8
- class Query
9
- require 'sqlite3'
10
- attr_reader :db
11
- def initialize(path:)
12
- @db = SQLite3::Database.open(path)
13
- end
14
- def select(t:, cols:"*", where:)
15
- db.execute(
16
- "SELECT #{cols} FROM #{t} "\
17
- "WHERE #{where.map{|k, v| "#{k} = #{v}"}.join(" AND ")}")
18
- end
19
- def table(t:, cols:)
20
- db.execute(
21
- "CREATE TABLE IF NOT EXISTS "\
22
- "#{t}(#{cols.map{|c, t| "#{c} #{t}"}.join(", ")})")
23
- self
24
- end
25
- def insert(t:, val:)
26
- db.execute(
27
- "INSERT INTO #{t} "\
28
- "VALUES(#{val.join(", ")})")
29
- self
30
- end
31
- def update(t:, val:, where:)
32
- db.execute(
33
- "UPDATE #{t} "\
34
- "SET #{val.map{|c, v| "#{c} = #{v}"}.join(", ")} "\
35
- "WHERE #{where.map{|c, v| "#{c} = #{v}"}.join(" AND ")}")
36
- self
37
- end
38
- end
39
- class Attempt
40
- attr_reader :attempt, :db
41
- def initialize(attempt:)
42
- @attempt = attempt
43
- @db = Query.new(path:Paths::Database.cfg(attempt.user))
44
- .table(t:"attempts", cols:cols)
45
- end
46
- def correct
47
- db.insert(t:"attempts", val:data << 1 << 0 << 0)
48
- self
49
- end
50
- def incorrect(low:, high:)
51
- db.insert(t:"attempts",
52
- val:data << 0 << parse_hint(low:low, high:high))
53
- self
54
- end
55
- def duplicate?(ans:)
56
- db.select(t:"attempts",
57
- where:where.merge({answer:ans})).count > 0
58
- end
59
- def parse_hint(low:, high:)
60
- [ low ? 1 : 0, high ? 1 : 0 ]
61
- end
62
- def data
63
- [ "'#{Time.now}'",
64
- "'#{attempt.year}'",
65
- "'#{attempt.day}'",
66
- "'#{attempt.part}'",
67
- "'#{attempt.answer}'" ]
68
- end
69
- def cols
70
- { time: :TEXT,
71
- year: :INT,
72
- day: :INT,
73
- part: :INT,
74
- answer: :TEXT,
75
- correct: :INT,
76
- low: :INT,
77
- high: :INT }
78
- end
79
- def count_attempts
80
- db.select(t:"attempts", where:where).count
81
- end
82
- def where
83
- { year:attempt.year,
84
- day:attempt.day,
85
- part:attempt.part }
86
- end
87
- end
88
- module Stats
89
- class Init
90
- attr_reader :user, :year, :day, :part, :now, :db
91
- def initialize(u:Metafile.get(:user),
92
- y:Metafile.get(:year),
93
- d:Metafile.get(:day),
94
- p:Metafile.get(:part))
95
- @user = Validate.user(u)
96
- @year = Validate.year(y)
97
- @day = Validate.day(d)
98
- @part = p
99
- @now = Time.now
100
- @db = Query.new(path:Paths::Database.cfg(user))
101
- .table(t:"stats", cols:cols)
102
- end
103
- def cols
104
- { year: :INT,
105
- day: :INT,
106
- part: :INT,
107
- dl_time: :TEXT,
108
- end_time: :TEXT,
109
- elapsed: :TEXT,
110
- attempts: :INT,
111
- correct: :INT }
112
- end
113
- def init
114
- db.insert(t:"stats", val:data)
115
- end
116
- def data
117
- [ "'#{year}'",
118
- "'#{day}'",
119
- "'#{part}'",
120
- "'#{now}'",
121
- "NULL",
122
- "NULL",
123
- "'0'",
124
- "'0'" ]
125
- end
126
- end
127
- class Complete < Init
128
- attr_reader :n_attempts
129
- def initialize(u:Metafile.get(:user),
130
- y:Metafile.get(:year),
131
- d:Metafile.get(:day),
132
- p:Metafile.get(:part),
133
- n:)
134
- super(u:u, y:y, d:d, p:p)
135
- @n_attempts = n
136
- end
137
- def update
138
- db.update(t:"stats", val:val, where:where)
139
- end
140
- def val
141
- { elapsed: "'#{elapsed}'",
142
- end_time: "'#{now}'",
143
- attempts: "'#{n_attempts}'",
144
- correct: "'1'" }
145
- end
146
- def where
147
- { year: year,
148
- day: day,
149
- part: part }
150
- end
151
- def elapsed
152
- @elapsed ||= hms(now - dl_time)
153
- end
154
- def hms(seconds)
155
- [seconds/3600, seconds/60 % 60, seconds % 60]
156
- .map{|t| t.to_i.to_s.rjust(2, "0")}.join(":")
157
- end
158
- def dl_time
159
- @dl_time ||= Time.parse(db
160
- .select(t:"stats", cols:"dl_time", where:where)
161
- .flatten.first)
162
- end
163
- end
164
- end
165
- module Calendar
166
- class Init
167
- attr_reader :user, :year, :db, :stars
168
- def initialize(u:Metafile.get(:user),
169
- y:Metafile.get(:year),
170
- stars:)
171
- @user = Validate.user(u)
172
- @year = Validate.year(y)
173
- @stars = stars
174
- @db = Query
175
- .new(path:Paths::Database.cfg(user))
176
- .table(t:"calendar", cols:cols)
177
- end
178
- def cols
179
- { year: :INT,
180
- day: :INT,
181
- stars: :TEXT }
182
- end
183
- def n_stars(day)
184
- stars.keys.include?(day) ? stars[day] : 0
185
- end
186
- def day_data(day)
187
- ["'#{year}'", "'#{day}'", "'#{n_stars(day)}'"]
188
- end
189
- def table_exist?
190
- db.select(t:"calendar", where:{year:"'#{year}'"}).count > 0
191
- end
192
- def insert
193
- unless table_exist?
194
- 1.upto(25){|day|
195
- db.insert(t:"calendar",
196
- val:day_data(day))}
197
- end
198
- end
199
- end
200
- class Part
201
- attr_reader :user, :year, :day, :db
202
- def initialize(u:Metafile.get(:user),
203
- y:Metafile.get(:year),
204
- d:Metafile.get(:day))
205
- @user = Validate.user(u)
206
- @year = Validate.year(y)
207
- @day = Validate.day(d)
208
- @db = Query.new(path:Paths::Database.cfg(user))
209
- end
210
- def get
211
- db.select(t:"calendar", cols:"stars", where:where)
212
- .flatten.first.to_i + 1
213
- end
214
- def increment
215
- db.update(t:"calendar", val:{stars:get}, where:where)
216
- end
217
- def where
218
- { year:"'#{year}'",
219
- day:"'#{day}'" }
220
- end
221
- end
222
- end
223
- end
224
- end
data/lib/aoc_cli/day.rb DELETED
@@ -1,124 +0,0 @@
1
- module AocCli
2
- module Day
3
- class Init
4
- attr_reader :user, :year, :day, :paths
5
- def initialize(u:Metafile.get(:user),
6
- y:Metafile.get(:year),
7
- d:Metafile.get(:day))
8
- @user = Validate.user(u)
9
- @year = Validate.year(y)
10
- @day = Validate.day(d)
11
- @paths = Paths::Day.new(u:user, y:year, d:day)
12
- end
13
- def mkdir
14
- Dir.mkdir(Validate.day_dir(paths.day_dir))
15
- self
16
- end
17
- def meta
18
- File.write(paths.local(f:"meta"),
19
- Metafile.day(u:user, y:year, d:day))
20
- self
21
- end
22
- end
23
- class Pages < Init
24
- attr_reader :files, :use_cache
25
- def initialize(u:Metafile.get(:user),
26
- y:Metafile.get(:year),
27
- d:Metafile.get(:day),
28
- f:[:Input, :Puzzle],
29
- use_cache:true)
30
- super(u:u, y:y, d:d)
31
- @files = f
32
- @use_cache = use_cache
33
- end
34
- def load
35
- files.each do |file| use_cache && cache[file] ?
36
- copy(file:file) : download(page:file) end
37
- end
38
- def cache
39
- @cache ||= Cache.new(d:day, f:files).query
40
- end
41
- def copy(file:)
42
- File.write(paths.local(f:file), cache[file])
43
- end
44
- def download(page:)
45
- req = Requests.const_get(page)
46
- .new(u:user, y:year, d:day)
47
- .write(to:paths.cache_and_local(f:page))
48
- req.init_stats if page == :Puzzle
49
- end
50
- end
51
- class Cache < Pages
52
- def initialize(u:Metafile.get(:user),
53
- y:Metafile.get(:year),
54
- d:Metafile.get(:day),
55
- f:[:Input, :Puzzle])
56
- super(u:u, y:y, d:d, f:f)
57
- paths.create_cache
58
- end
59
- def query
60
- files.map{|file| [file, read(file:file)]}.to_h
61
- end
62
- private
63
- def read(file:)
64
- File.exist?(paths.cache_path(f:file)) ?
65
- File.read(paths.cache_path(f:file)) : nil
66
- end
67
- end
68
- module Requests
69
- class Request < Init
70
- attr_reader :data, :part
71
- def initialize(u:Metafile.get(:user),
72
- y:Metafile.get(:year),
73
- d:Metafile.get(:day))
74
- super(u:u, y:y, d:d)
75
- @data = parse(raw:fetch)
76
- @part = Metafile.part(d:day)
77
- end
78
- def write(to:)
79
- to.each{|path| File.write(path, data)}; self
80
- end
81
- private
82
- def fetch
83
- Tools::Get.new(u:user, y:year, d:day, p:page)
84
- end
85
- end
86
- class Puzzle < Request
87
- def page
88
- :Puzzle
89
- end
90
- def parse(raw:fetch)
91
- raw.chunk(f:"<article", t:"<\/article", f_off:2)
92
- .md
93
- .gsub(/(?<=\])\[\]/, "")
94
- .gsub(/\n.*<!--.*-->.*\n/, "")
95
- end
96
- def init_stats
97
- Database::Stats::Init
98
- .new(d:day, p:part)
99
- .init if part < 3 && !stats_exist?
100
- end
101
- def stats_exist?
102
- Database::Query
103
- .new(path:Paths::Database.cfg(user))
104
- .select(t:"stats",
105
- where:{year:year, day:day, part:part})
106
- .count > 0
107
- end
108
- end
109
- class Input < Request
110
- def page
111
- :Input
112
- end
113
- def parse(raw:fetch)
114
- raw.raw
115
- end
116
- end
117
- end
118
- def self.refresh(files:[:Input, :Puzzle])
119
- puts "- Updating puzzle...".blue
120
- Init.new.meta
121
- Pages.new(f:files, use_cache:false).load
122
- end
123
- end
124
- end
Binary file
@@ -1,275 +0,0 @@
1
- module AocCli
2
- module Errors
3
- ERROR = "Error".bold.red
4
- class UserNil < StandardError
5
- def message
6
- <<~error
7
- #{ERROR}: No user alias value.
8
- Specify an alias to use when passing the #{"-u".yellow} or #{"--user".yellow} flag
9
- error
10
- end
11
- end
12
- class UserInv < StandardError
13
- def initialize(user)
14
- @user = user
15
- end
16
- def message
17
- <<~error
18
- #{ERROR}: Invalid user: #{@user.to_s.red}
19
- No key was found under this alias
20
- error
21
- end
22
- end
23
- class UserDup < StandardError
24
- attr_reader :user
25
- def initialize(user)
26
- @user = user
27
- end
28
- def message
29
- <<~error
30
- #{ERROR}: There is already a key set for the user #{user.yellow}
31
- Either check your config file or set a new username for this key using the #{"-u".yellow} or #{"--user".yellow} flags
32
- error
33
- end
34
- end
35
- class YearNil < StandardError
36
- def message
37
- <<~error
38
- #{ERROR}: No year value.
39
- Set the year using the #{"-y".yellow} or #{"--year".yellow} flags.
40
- error
41
- end
42
- end
43
- class YearInv < StandardError
44
- attr_reader :year
45
- def initialize(year)
46
- @year = year
47
- end
48
- def message
49
- <<~error
50
- #{ERROR}: Invalid year: #{year.to_s.red}
51
- Advent of Code currently spans 2015 - 2020.
52
- error
53
- end
54
- end
55
- class DayNil < StandardError
56
- def message
57
- <<~error
58
- #{ERROR}: No day value.
59
- Specify the day using the #{"-d".yellow} or #{"--day".yellow} flags.
60
- error
61
- end
62
- end
63
- class DayInv < StandardError
64
- def initialize(day)
65
- @day = day
66
- end
67
- def message
68
- <<~error
69
- #{ERROR}: Invalid day: #{@day.to_s.red}
70
- Valid days are between 1 and 25
71
- error
72
- end
73
- end
74
- class DayExist < StandardError
75
- def initialize(day)
76
- @day = day.to_s
77
- end
78
- def message
79
- <<~error
80
- #{ERROR}: Day #{@day.red} is already initialised!
81
- error
82
- end
83
- end
84
- class PartNil < StandardError
85
- def message
86
- <<~error
87
- #{ERROR}: No part value.
88
- Check the .meta file or pass it manually with the #{"-p".yellow} or #{"--part".yellow} flags
89
- error
90
- end
91
- end
92
- class PartInv < StandardError
93
- attr_reader :part
94
- def initialize(part)
95
- @part = part
96
- end
97
- def message
98
- <<~error
99
- #{ERROR}: Invalid part: #{part.red}
100
- Part refers to the part of the puzzle and can either be 1 or 2.
101
- error
102
- end
103
- end
104
- class AnsNil < StandardError
105
- def message
106
- <<~error
107
- #{ERROR}: No answer value.
108
- error
109
- end
110
- end
111
- class KeyNil < StandardError
112
- def message
113
- <<~error
114
- #{ERROR}: No session key value.
115
- Use the #{"-k".yellow} or #{"--key".yellow} flags to store the key
116
- error
117
- end
118
- end
119
- class KeyDup < StandardError
120
- attr_reader :key
121
- def initialize(key)
122
- @key = key
123
- end
124
- def message
125
- <<~error
126
- #{ERROR}: The key #{key.yellow} already exists in your config file
127
- error
128
- end
129
- end
130
- class AlrInit < StandardError
131
- def message
132
- <<~error
133
- #{ERROR}: This directory is already initialised.
134
- error
135
- end
136
- end
137
- class NotInit < StandardError
138
- def message
139
- <<~error
140
- #{ERROR}: You must initialise the directory first
141
- error
142
- end
143
- end
144
- class PuzzComp < StandardError
145
- def message
146
- <<~error
147
- #{ERROR}: This puzzle is already complete!
148
- error
149
- end
150
- end
151
- class FlagInv < StandardError
152
- attr_reader :flag
153
- def initialize(flag)
154
- @flag = flag
155
- end
156
- def message
157
- <<~error
158
- #{ERROR}: Invalid flag: #{flag.red}
159
- Use the #{"-h".yellow} or #{"--help".yellow} flags for a list of commands
160
- error
161
- end
162
- end
163
- class CmdNil < StandardError
164
- def message
165
- <<~error
166
- #{ERROR}: Flags passed but no command specified
167
- error
168
- end
169
- end
170
- class KeyInv < StandardError
171
- def message
172
- <<~error
173
- #{ERROR}: Invalid key
174
- Double check your session key. It should start with "session="
175
- error
176
- end
177
- end
178
- class ConfigExist < StandardError
179
- def message
180
- <<~error
181
- #{ERROR}: A config file already exists in #{Paths::Config.path.blue}
182
- error
183
- end
184
- end
185
- class AtmptDup < StandardError
186
- attr_reader :answer
187
- def initialize(answer)
188
- @answer = answer
189
- end
190
- def message
191
- <<~error
192
- #{ERROR}: You have already tried #{answer.red}
193
- To see previous attempts run #{"aoc -a".yellow}
194
- error
195
- end
196
- end
197
- end
198
- class Validate
199
- E = Errors
200
- def self.cmd(cmd)
201
- raise E::CmdNil if cmd.nil?
202
- cmd
203
- end
204
- def self.user(user)
205
- raise E::UserNil if user.nil?
206
- raise E::UserInv.new(user) unless user_in_config?(user)
207
- user
208
- end
209
- def self.set_user(user)
210
- raise E::UserNil if user.nil?
211
- raise E::UserDup.new(user) if user_in_config?(user)
212
- user
213
- end
214
- def self.year(year)
215
- raise E::YearNil if year.nil?
216
- raise E::YearInv.new(year) if year.to_i < 2015 ||
217
- year.to_i > 2020
218
- year
219
- end
220
- def self.day(day)
221
- raise E::DayNil if day.nil? || day == 0
222
- raise E::DayInv.new(day) if day.to_i < 1 ||
223
- day.to_i > 25
224
- day
225
- end
226
- def self.part(part)
227
- raise E::PartNil if part.nil?
228
- raise E::PuzzComp if part.to_i == 3
229
- raise E::PartInv if part.to_i < 1 || part.to_i > 2
230
- part
231
- end
232
- def self.set_key(key)
233
- raise E::KeyNil if key.nil?
234
- raise E::KeyDup.new(key) if Files::Config::Tools
235
- .is_set?(val:"#{key}(\b|$)")
236
- raise E::KeyInv unless valid_key?(key)
237
- key
238
- end
239
- def self.key(key)
240
- raise E::KeyNil if key.nil?
241
- raise E::KeyInv unless valid_key?(key)
242
- key
243
- end
244
- def self.ans(attempt:, ans:)
245
- raise E::AnsNil if ans.nil?
246
- raise E::AtmptDup.new(ans) if Database::Attempt
247
- .new(attempt:attempt).duplicate?(ans:ans)
248
- ans
249
- end
250
- def self.day_dir(day)
251
- raise E::DayExist.new(day) if Dir.exist?(day)
252
- day
253
- end
254
- def self.init(dir)
255
- raise E::NotInit unless File.exist?("#{dir}/.meta")
256
- dir
257
- end
258
- def self.not_init(dir:, year:)
259
- raise E::AlrInit if File.exist?("#{dir}/.meta") &&
260
- Metafile.get(:year) != year.to_s
261
- dir
262
- end
263
- def self.no_config
264
- raise E::ConfigExist if File.exist?(Paths::Config.path)
265
- Paths::Config.path
266
- end
267
- private
268
- def self.valid_key?(key)
269
- /session=(?:[a-f0-9]){96}/.match?(key)
270
- end
271
- def self.user_in_config?(user)
272
- Files::Config::Tools.is_set?(key:"cookie=>#{user}")
273
- end
274
- end
275
- end