aoc_cli 0.2.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) 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/Gemfile +8 -0
  6. data/Gemfile.lock +187 -0
  7. data/README.md +88 -282
  8. data/Rakefile +9 -2
  9. data/Steepfile +13 -0
  10. data/aoc_cli.gemspec +36 -26
  11. data/db/migrate/1_create_events.rb +14 -0
  12. data/db/migrate/2_create_puzzles.rb +21 -0
  13. data/db/migrate/3_create_stats.rb +19 -0
  14. data/db/migrate/4_create_attempts.rb +19 -0
  15. data/db/migrate/5_create_locations.rb +17 -0
  16. data/db/migrate/6_create_puzzle_dir_sync_logs.rb +18 -0
  17. data/exe/aoc +5 -0
  18. data/lib/aoc_cli/components/attempts_table.erb +5 -0
  19. data/lib/aoc_cli/components/attempts_table.rb +58 -0
  20. data/lib/aoc_cli/components/docs_component.erb +19 -0
  21. data/lib/aoc_cli/components/docs_component.rb +41 -0
  22. data/lib/aoc_cli/components/errors_component.erb +8 -0
  23. data/lib/aoc_cli/components/errors_component.rb +36 -0
  24. data/lib/aoc_cli/components/progress_table.erb +1 -0
  25. data/lib/aoc_cli/components/progress_table.rb +43 -0
  26. data/lib/aoc_cli/components/puzzle_sync_component.erb +2 -0
  27. data/lib/aoc_cli/components/puzzle_sync_component.rb +26 -0
  28. data/lib/aoc_cli/configurators/session_configurator.rb +7 -0
  29. data/lib/aoc_cli/controllers/application_controller.rb +27 -0
  30. data/lib/aoc_cli/controllers/concerns/error_concern.rb +17 -0
  31. data/lib/aoc_cli/controllers/concerns/location_concern.rb +79 -0
  32. data/lib/aoc_cli/controllers/default_controller.rb +9 -0
  33. data/lib/aoc_cli/controllers/event_controller.rb +35 -0
  34. data/lib/aoc_cli/controllers/help/event_controller.rb +11 -0
  35. data/lib/aoc_cli/controllers/help/puzzle_controller.rb +13 -0
  36. data/lib/aoc_cli/controllers/puzzle_controller.rb +39 -0
  37. data/lib/aoc_cli/core/attempt_parser.rb +69 -0
  38. data/lib/aoc_cli/core/processor.rb +32 -0
  39. data/lib/aoc_cli/core/repository.rb +74 -0
  40. data/lib/aoc_cli/core/request.rb +37 -0
  41. data/lib/aoc_cli/core/resource.rb +39 -0
  42. data/lib/aoc_cli/core/stats_parser.rb +43 -0
  43. data/lib/aoc_cli/helpers/table_generator.rb +64 -0
  44. data/lib/aoc_cli/helpers/view_helper.rb +35 -0
  45. data/lib/aoc_cli/models/attempt.rb +67 -0
  46. data/lib/aoc_cli/models/event.rb +9 -0
  47. data/lib/aoc_cli/models/location.rb +24 -0
  48. data/lib/aoc_cli/models/puzzle.rb +28 -0
  49. data/lib/aoc_cli/models/puzzle_dir_sync_log.rb +14 -0
  50. data/lib/aoc_cli/models/stats.rb +43 -0
  51. data/lib/aoc_cli/presenters/attempt_presenter.rb +29 -0
  52. data/lib/aoc_cli/presenters/puzzle_presenter.rb +29 -0
  53. data/lib/aoc_cli/presenters/stats_presenter.rb +32 -0
  54. data/lib/aoc_cli/processors/event_initialiser.rb +64 -0
  55. data/lib/aoc_cli/processors/puzzle_dir_synchroniser.rb +80 -0
  56. data/lib/aoc_cli/processors/puzzle_initialiser.rb +91 -0
  57. data/lib/aoc_cli/processors/puzzle_refresher.rb +27 -0
  58. data/lib/aoc_cli/processors/resource_attacher.rb +22 -0
  59. data/lib/aoc_cli/processors/solution_poster.rb +72 -0
  60. data/lib/aoc_cli/processors/stats_initialiser.rb +36 -0
  61. data/lib/aoc_cli/processors/stats_refresher.rb +23 -0
  62. data/lib/aoc_cli/validators/collection_type_validator.rb +57 -0
  63. data/lib/aoc_cli/validators/event_year_validator.rb +42 -0
  64. data/lib/aoc_cli/validators/included_validator.rb +21 -0
  65. data/lib/aoc_cli/validators/integer_validator.rb +32 -0
  66. data/lib/aoc_cli/validators/path_validator.rb +39 -0
  67. data/lib/aoc_cli/validators/type_validator.rb +54 -0
  68. data/lib/aoc_cli/version.rb +1 -1
  69. data/lib/aoc_cli/views/event/attach.erb +3 -0
  70. data/lib/aoc_cli/views/event/init.erb +3 -0
  71. data/lib/aoc_cli/views/help/event/attach.erb +32 -0
  72. data/lib/aoc_cli/views/help/event/init.erb +38 -0
  73. data/lib/aoc_cli/views/help/event/progress.erb +12 -0
  74. data/lib/aoc_cli/views/help/puzzle/attempts.erb +12 -0
  75. data/lib/aoc_cli/views/help/puzzle/init.erb +31 -0
  76. data/lib/aoc_cli/views/help/puzzle/solve.erb +33 -0
  77. data/lib/aoc_cli/views/help/puzzle/sync.erb +32 -0
  78. data/lib/aoc_cli/views/puzzle/init.erb +3 -0
  79. data/lib/aoc_cli/views/puzzle/solve.erb +10 -0
  80. data/lib/aoc_cli.rb +32 -16
  81. data/rbs_collection.lock.yaml +168 -0
  82. data/rbs_collection.yaml +28 -0
  83. data/sig/aoc_cli/components/attempts_table.rbs +29 -0
  84. data/sig/aoc_cli/components/docs_component.rbs +15 -0
  85. data/sig/aoc_cli/components/errors_component.rbs +19 -0
  86. data/sig/aoc_cli/components/progress_table.rbs +28 -0
  87. data/sig/aoc_cli/components/puzzle_sync_component.rbs +19 -0
  88. data/sig/aoc_cli/configurators/session_configurator.rbs +7 -0
  89. data/sig/aoc_cli/controllers/application_controller.rbs +12 -0
  90. data/sig/aoc_cli/controllers/concerns/error_concern.rbs +9 -0
  91. data/sig/aoc_cli/controllers/concerns/location_concern.rbs +35 -0
  92. data/sig/aoc_cli/controllers/default_controller.rbs +7 -0
  93. data/sig/aoc_cli/controllers/event_controller.rbs +18 -0
  94. data/sig/aoc_cli/controllers/help/event_controller.rbs +11 -0
  95. data/sig/aoc_cli/controllers/help/puzzle_controller.rbs +13 -0
  96. data/sig/aoc_cli/controllers/puzzle_controller.rbs +15 -0
  97. data/sig/aoc_cli/core/attempt_parser.rbs +41 -0
  98. data/sig/aoc_cli/core/processor.rbs +25 -0
  99. data/sig/aoc_cli/core/repository.rbs +25 -0
  100. data/sig/aoc_cli/core/request.rbs +29 -0
  101. data/sig/aoc_cli/core/resource.rbs +25 -0
  102. data/sig/aoc_cli/core/stats_parser.rbs +23 -0
  103. data/sig/aoc_cli/helpers/table_generator.rbs +36 -0
  104. data/sig/aoc_cli/helpers/view_helper.rbs +15 -0
  105. data/sig/aoc_cli/models/attempt.rbs +35 -0
  106. data/sig/aoc_cli/models/event.rbs +17 -0
  107. data/sig/aoc_cli/models/location.rbs +19 -0
  108. data/sig/aoc_cli/models/puzzle.rbs +28 -0
  109. data/sig/aoc_cli/models/puzzle_dir_sync_log.rbs +11 -0
  110. data/sig/aoc_cli/models/stats.rbs +53 -0
  111. data/sig/aoc_cli/presenters/attempt_presenter.rbs +13 -0
  112. data/sig/aoc_cli/presenters/puzzle_presenter.rbs +19 -0
  113. data/sig/aoc_cli/presenters/stats_presenter.rbs +19 -0
  114. data/sig/aoc_cli/processors/event_initialiser.rbs +26 -0
  115. data/sig/aoc_cli/processors/puzzle_dir_synchroniser.rbs +40 -0
  116. data/sig/aoc_cli/processors/puzzle_initialiser.rbs +37 -0
  117. data/sig/aoc_cli/processors/puzzle_refresher.rbs +21 -0
  118. data/sig/aoc_cli/processors/resource_attacher.rbs +16 -0
  119. data/sig/aoc_cli/processors/solution_poster.rbs +34 -0
  120. data/sig/aoc_cli/processors/stats_initialiser.rbs +15 -0
  121. data/sig/aoc_cli/processors/stats_refresher.rbs +19 -0
  122. data/sig/aoc_cli/validators/collection_type_validator.rbs +24 -0
  123. data/sig/aoc_cli/validators/event_year_validator.rbs +19 -0
  124. data/sig/aoc_cli/validators/included_validator.rbs +11 -0
  125. data/sig/aoc_cli/validators/integer_validator.rbs +15 -0
  126. data/sig/aoc_cli/validators/path_validator.rbs +17 -0
  127. data/sig/aoc_cli/validators/type_validator.rbs +22 -0
  128. data/sig/aoc_cli.rbs +6 -0
  129. data/sig/http.rbs +3 -0
  130. data/sig/kangaru.rbs +5 -0
  131. data/sig/nokogiri.rbs +3 -0
  132. data/sig/reverse_markdown.rbs +3 -0
  133. metadata +142 -34
  134. data/.gitignore +0 -5
  135. data/bin/aoc +0 -4
  136. data/bin/console +0 -15
  137. data/bin/setup +0 -7
  138. data/lib/aoc_cli/commands.rb +0 -232
  139. data/lib/aoc_cli/database.rb +0 -224
  140. data/lib/aoc_cli/day.rb +0 -124
  141. data/lib/aoc_cli/db/reddit.db +0 -0
  142. data/lib/aoc_cli/errors.rb +0 -275
  143. data/lib/aoc_cli/files.rb +0 -163
  144. data/lib/aoc_cli/help.rb +0 -77
  145. data/lib/aoc_cli/interface.rb +0 -81
  146. data/lib/aoc_cli/paths.rb +0 -101
  147. data/lib/aoc_cli/solve.rb +0 -104
  148. data/lib/aoc_cli/tables.rb +0 -138
  149. data/lib/aoc_cli/tools.rb +0 -120
  150. data/lib/aoc_cli/year.rb +0 -116
  151. 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