aoc_cli 0.2.3 → 1.0.1
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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +88 -0
- data/.ruby-version +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +187 -0
- data/README.md +88 -282
- data/Rakefile +9 -2
- data/Steepfile +13 -0
- data/aoc_cli.gemspec +36 -26
- data/db/migrate/1_create_events.rb +14 -0
- data/db/migrate/2_create_puzzles.rb +21 -0
- data/db/migrate/3_create_stats.rb +19 -0
- data/db/migrate/4_create_attempts.rb +19 -0
- data/db/migrate/5_create_locations.rb +17 -0
- data/db/migrate/6_create_puzzle_dir_sync_logs.rb +18 -0
- data/db/migrate/7_create_progresses.rb +17 -0
- data/db/migrate/8_remove_legacy_timestamps.rb +8 -0
- data/exe/aoc +5 -0
- data/lib/aoc_cli/components/attempts_table.erb +5 -0
- data/lib/aoc_cli/components/attempts_table.rb +58 -0
- data/lib/aoc_cli/components/docs_component.erb +19 -0
- data/lib/aoc_cli/components/docs_component.rb +41 -0
- data/lib/aoc_cli/components/errors_component.erb +8 -0
- data/lib/aoc_cli/components/errors_component.rb +36 -0
- data/lib/aoc_cli/components/progress_table.erb +1 -0
- data/lib/aoc_cli/components/progress_table.rb +43 -0
- data/lib/aoc_cli/components/puzzle_sync_component.erb +2 -0
- data/lib/aoc_cli/components/puzzle_sync_component.rb +26 -0
- data/lib/aoc_cli/configurators/session_configurator.rb +7 -0
- data/lib/aoc_cli/controllers/application_controller.rb +27 -0
- data/lib/aoc_cli/controllers/concerns/error_concern.rb +17 -0
- data/lib/aoc_cli/controllers/concerns/location_concern.rb +79 -0
- data/lib/aoc_cli/controllers/default_controller.rb +9 -0
- data/lib/aoc_cli/controllers/event_controller.rb +35 -0
- data/lib/aoc_cli/controllers/help/event_controller.rb +11 -0
- data/lib/aoc_cli/controllers/help/puzzle_controller.rb +13 -0
- data/lib/aoc_cli/controllers/puzzle_controller.rb +39 -0
- data/lib/aoc_cli/core/attempt_parser.rb +69 -0
- data/lib/aoc_cli/core/processor.rb +32 -0
- data/lib/aoc_cli/core/repository.rb +74 -0
- data/lib/aoc_cli/core/request.rb +37 -0
- data/lib/aoc_cli/core/resource.rb +39 -0
- data/lib/aoc_cli/core/stats_parser.rb +43 -0
- data/lib/aoc_cli/helpers/table_generator.rb +64 -0
- data/lib/aoc_cli/helpers/view_helper.rb +35 -0
- data/lib/aoc_cli/models/attempt.rb +67 -0
- data/lib/aoc_cli/models/event.rb +9 -0
- data/lib/aoc_cli/models/location.rb +24 -0
- data/lib/aoc_cli/models/progress.rb +33 -0
- data/lib/aoc_cli/models/puzzle.rb +28 -0
- data/lib/aoc_cli/models/puzzle_dir_sync_log.rb +14 -0
- data/lib/aoc_cli/models/stats.rb +43 -0
- data/lib/aoc_cli/presenters/attempt_presenter.rb +29 -0
- data/lib/aoc_cli/presenters/puzzle_presenter.rb +29 -0
- data/lib/aoc_cli/presenters/stats_presenter.rb +32 -0
- data/lib/aoc_cli/processors/event_initialiser.rb +64 -0
- data/lib/aoc_cli/processors/progress_syncer.rb +48 -0
- data/lib/aoc_cli/processors/puzzle_dir_synchroniser.rb +80 -0
- data/lib/aoc_cli/processors/puzzle_initialiser.rb +106 -0
- data/lib/aoc_cli/processors/puzzle_refresher.rb +27 -0
- data/lib/aoc_cli/processors/resource_attacher.rb +22 -0
- data/lib/aoc_cli/processors/solution_poster.rb +72 -0
- data/lib/aoc_cli/processors/stats_initialiser.rb +36 -0
- data/lib/aoc_cli/processors/stats_refresher.rb +23 -0
- data/lib/aoc_cli/validators/collection_type_validator.rb +57 -0
- data/lib/aoc_cli/validators/event_year_validator.rb +42 -0
- data/lib/aoc_cli/validators/included_validator.rb +21 -0
- data/lib/aoc_cli/validators/integer_validator.rb +32 -0
- data/lib/aoc_cli/validators/path_validator.rb +39 -0
- data/lib/aoc_cli/validators/type_validator.rb +54 -0
- data/lib/aoc_cli/version.rb +1 -1
- data/lib/aoc_cli/views/event/attach.erb +3 -0
- data/lib/aoc_cli/views/event/init.erb +3 -0
- data/lib/aoc_cli/views/help/event/attach.erb +32 -0
- data/lib/aoc_cli/views/help/event/init.erb +38 -0
- data/lib/aoc_cli/views/help/event/progress.erb +12 -0
- data/lib/aoc_cli/views/help/puzzle/attempts.erb +12 -0
- data/lib/aoc_cli/views/help/puzzle/init.erb +31 -0
- data/lib/aoc_cli/views/help/puzzle/solve.erb +33 -0
- data/lib/aoc_cli/views/help/puzzle/sync.erb +32 -0
- data/lib/aoc_cli/views/puzzle/init.erb +3 -0
- data/lib/aoc_cli/views/puzzle/solve.erb +10 -0
- data/lib/aoc_cli.rb +36 -16
- data/rbs_collection.lock.yaml +168 -0
- data/rbs_collection.yaml +28 -0
- data/sig/aoc_cli/components/attempts_table.rbs +29 -0
- data/sig/aoc_cli/components/docs_component.rbs +15 -0
- data/sig/aoc_cli/components/errors_component.rbs +19 -0
- data/sig/aoc_cli/components/progress_table.rbs +28 -0
- data/sig/aoc_cli/components/puzzle_sync_component.rbs +19 -0
- data/sig/aoc_cli/configurators/session_configurator.rbs +7 -0
- data/sig/aoc_cli/controllers/application_controller.rbs +12 -0
- data/sig/aoc_cli/controllers/concerns/error_concern.rbs +9 -0
- data/sig/aoc_cli/controllers/concerns/location_concern.rbs +35 -0
- data/sig/aoc_cli/controllers/default_controller.rbs +7 -0
- data/sig/aoc_cli/controllers/event_controller.rbs +18 -0
- data/sig/aoc_cli/controllers/help/event_controller.rbs +11 -0
- data/sig/aoc_cli/controllers/help/puzzle_controller.rbs +13 -0
- data/sig/aoc_cli/controllers/puzzle_controller.rbs +15 -0
- data/sig/aoc_cli/core/attempt_parser.rbs +41 -0
- data/sig/aoc_cli/core/processor.rbs +25 -0
- data/sig/aoc_cli/core/repository.rbs +25 -0
- data/sig/aoc_cli/core/request.rbs +29 -0
- data/sig/aoc_cli/core/resource.rbs +25 -0
- data/sig/aoc_cli/core/stats_parser.rbs +23 -0
- data/sig/aoc_cli/helpers/table_generator.rbs +36 -0
- data/sig/aoc_cli/helpers/view_helper.rbs +15 -0
- data/sig/aoc_cli/models/attempt.rbs +35 -0
- data/sig/aoc_cli/models/event.rbs +17 -0
- data/sig/aoc_cli/models/location.rbs +19 -0
- data/sig/aoc_cli/models/progress.rbs +21 -0
- data/sig/aoc_cli/models/puzzle.rbs +27 -0
- data/sig/aoc_cli/models/puzzle_dir_sync_log.rbs +11 -0
- data/sig/aoc_cli/models/stats.rbs +53 -0
- data/sig/aoc_cli/presenters/attempt_presenter.rbs +13 -0
- data/sig/aoc_cli/presenters/puzzle_presenter.rbs +19 -0
- data/sig/aoc_cli/presenters/stats_presenter.rbs +19 -0
- data/sig/aoc_cli/processors/event_initialiser.rbs +26 -0
- data/sig/aoc_cli/processors/progress_syncer.rbs +29 -0
- data/sig/aoc_cli/processors/puzzle_dir_synchroniser.rbs +40 -0
- data/sig/aoc_cli/processors/puzzle_initialiser.rbs +41 -0
- data/sig/aoc_cli/processors/puzzle_refresher.rbs +21 -0
- data/sig/aoc_cli/processors/resource_attacher.rbs +16 -0
- data/sig/aoc_cli/processors/solution_poster.rbs +34 -0
- data/sig/aoc_cli/processors/stats_initialiser.rbs +15 -0
- data/sig/aoc_cli/processors/stats_refresher.rbs +19 -0
- data/sig/aoc_cli/validators/collection_type_validator.rbs +24 -0
- data/sig/aoc_cli/validators/event_year_validator.rbs +19 -0
- data/sig/aoc_cli/validators/included_validator.rbs +11 -0
- data/sig/aoc_cli/validators/integer_validator.rbs +15 -0
- data/sig/aoc_cli/validators/path_validator.rbs +17 -0
- data/sig/aoc_cli/validators/type_validator.rbs +22 -0
- data/sig/aoc_cli.rbs +6 -0
- data/sig/http.rbs +3 -0
- data/sig/kangaru.rbs +5 -0
- data/sig/nokogiri.rbs +3 -0
- data/sig/reverse_markdown.rbs +3 -0
- metadata +149 -34
- data/.gitignore +0 -5
- data/bin/aoc +0 -4
- data/bin/console +0 -15
- data/bin/setup +0 -7
- data/lib/aoc_cli/commands.rb +0 -232
- data/lib/aoc_cli/database.rb +0 -224
- data/lib/aoc_cli/day.rb +0 -124
- data/lib/aoc_cli/db/reddit.db +0 -0
- data/lib/aoc_cli/errors.rb +0 -275
- data/lib/aoc_cli/files.rb +0 -163
- data/lib/aoc_cli/help.rb +0 -77
- data/lib/aoc_cli/interface.rb +0 -81
- data/lib/aoc_cli/paths.rb +0 -101
- data/lib/aoc_cli/solve.rb +0 -104
- data/lib/aoc_cli/tables.rb +0 -138
- data/lib/aoc_cli/tools.rb +0 -120
- data/lib/aoc_cli/year.rb +0 -116
- data/sample/aoc.rc +0 -21
data/lib/aoc_cli/errors.rb
DELETED
|
@@ -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
|
data/lib/aoc_cli/files.rb
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
module AocCli
|
|
2
|
-
module Files
|
|
3
|
-
module Config
|
|
4
|
-
class Tools
|
|
5
|
-
def self.is_set?(key:nil, val:nil)
|
|
6
|
-
read.split("\n").grep(/(?<!\/\/)#{key}=>#{val}/).any?
|
|
7
|
-
end
|
|
8
|
-
def self.get_all(key:)
|
|
9
|
-
read.scan(/(?:(?<=(?<!\/\/)#{key}=>)).*$/)
|
|
10
|
-
end
|
|
11
|
-
def self.get_line(key:)
|
|
12
|
-
get_all(key:key)&.first
|
|
13
|
-
#read.scan(/(?:(?<=(?<!\/\/)#{key}=>)).*$/)&.first
|
|
14
|
-
end
|
|
15
|
-
def self.get_bool(key:)
|
|
16
|
-
get_line(key:key) == "true" ? true : false
|
|
17
|
-
end
|
|
18
|
-
def self.mod_line(key:, val:)
|
|
19
|
-
is_set?(key:key) ?
|
|
20
|
-
write(f:read.gsub(/(?<=^#{key}=>).*$/, val.to_s)) :
|
|
21
|
-
write(f:"#{key}=>#{val}\n", m:"a")
|
|
22
|
-
end
|
|
23
|
-
def self.set_line(key:, val:)
|
|
24
|
-
write(f:"#{key}=>#{val}\n", m:"a")
|
|
25
|
-
end
|
|
26
|
-
private
|
|
27
|
-
def self.read
|
|
28
|
-
Paths::Config.create
|
|
29
|
-
File.read(Paths::Config.path)
|
|
30
|
-
end
|
|
31
|
-
def self.write(f:, m:"w")
|
|
32
|
-
Paths::Config.create
|
|
33
|
-
File.write(Paths::Config.path, f, mode:m)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
class Prefs < Tools
|
|
37
|
-
def self.default_alias
|
|
38
|
-
is_set?(key:"default") ? get_line(key:"default") :
|
|
39
|
-
is_set?(key:"cookie=>main") ? "main" :
|
|
40
|
-
list_aliases.first || "main"
|
|
41
|
-
end
|
|
42
|
-
def self.list_aliases
|
|
43
|
-
get_all(key:"cookie")&.map{|a| a.gsub(/=>.*/, "")}
|
|
44
|
-
end
|
|
45
|
-
def self.bool(key:)
|
|
46
|
-
is_set?(key:key) ?
|
|
47
|
-
get_bool(key:key) : defaults[key.to_sym]
|
|
48
|
-
end
|
|
49
|
-
def self.string(key:)
|
|
50
|
-
is_set?(key:key) ?
|
|
51
|
-
get_line(key:key) : defaults[key.to_sym]
|
|
52
|
-
end
|
|
53
|
-
private
|
|
54
|
-
def self.defaults
|
|
55
|
-
{ calendar_file:true,
|
|
56
|
-
day_dir_prefix:"",
|
|
57
|
-
ignore_md_files:true,
|
|
58
|
-
ignore_meta_files:true,
|
|
59
|
-
init_git:false,
|
|
60
|
-
lb_in_calendar:true,
|
|
61
|
-
reddit_in_browser:false,
|
|
62
|
-
unicode_tables:true
|
|
63
|
-
}
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
class Cookie < Tools
|
|
67
|
-
def self.store(user:, key:)
|
|
68
|
-
set_line(key:"cookie=>#{Validate.set_user(user)}",
|
|
69
|
-
val:Validate.set_key(key))
|
|
70
|
-
end
|
|
71
|
-
def self.key(user:)
|
|
72
|
-
Validate.key(get_line(key:"cookie=>#{Validate
|
|
73
|
-
.user(user)}"))
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
class Example
|
|
77
|
-
def self.write
|
|
78
|
-
File.write(Validate.no_config, file)
|
|
79
|
-
end
|
|
80
|
-
def self.file
|
|
81
|
-
<<~file
|
|
82
|
-
//aoc-cli example config
|
|
83
|
-
//See the github repo for more information on configuring aoc-cli
|
|
84
|
-
//https://github.com/apexatoll/aoc-cli
|
|
85
|
-
|
|
86
|
-
[General]
|
|
87
|
-
//Print table in unicode rather than ascii
|
|
88
|
-
unicode_tables=>true
|
|
89
|
-
//Open Reddit in browser rather than use a Reddit CLI
|
|
90
|
-
reddit_in_browser=>false
|
|
91
|
-
|
|
92
|
-
[Initialise Year]
|
|
93
|
-
//Create a calendar file
|
|
94
|
-
calendar_file=>true
|
|
95
|
-
//Initialise git repo on year initialisation
|
|
96
|
-
init_git=>false
|
|
97
|
-
//Add calendar and puzzle files to gitignore
|
|
98
|
-
ignore_md_files=>true
|
|
99
|
-
//Add .meta files to gitignore
|
|
100
|
-
ignore_meta_files=>true
|
|
101
|
-
//Include leaderboard stats in calendar file
|
|
102
|
-
lb_in_calendar=>true
|
|
103
|
-
file
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
class Metafile
|
|
108
|
-
def self.get(field)
|
|
109
|
-
read.scan(/(?<=#{field}=>).*$/)&.first&.chomp
|
|
110
|
-
end
|
|
111
|
-
def self.type
|
|
112
|
-
get("dir").to_sym
|
|
113
|
-
end
|
|
114
|
-
def self.part(d:)
|
|
115
|
-
Database::Calendar::Part.new(d:d).get
|
|
116
|
-
end
|
|
117
|
-
private
|
|
118
|
-
def self.read(dir:".")
|
|
119
|
-
File.read("#{Validate.init(dir)}/.meta")
|
|
120
|
-
end
|
|
121
|
-
def self.year(u:, y:)
|
|
122
|
-
<<~meta
|
|
123
|
-
dir=>ROOT
|
|
124
|
-
user=>#{u}
|
|
125
|
-
year=>#{y}
|
|
126
|
-
meta
|
|
127
|
-
end
|
|
128
|
-
def self.day(u:, y:, d:)
|
|
129
|
-
<<~meta
|
|
130
|
-
dir=>DAY
|
|
131
|
-
user=>#{u}
|
|
132
|
-
year=>#{y}
|
|
133
|
-
day=>#{d}
|
|
134
|
-
part=>#{part(d:d)}
|
|
135
|
-
meta
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
class Calendar
|
|
139
|
-
attr_reader :cal, :stats, :year
|
|
140
|
-
def initialize(y:Metafile.get(:year), cal:, stats:)
|
|
141
|
-
@year, @cal, @stats = Validate.year(y), cal, stats
|
|
142
|
-
end
|
|
143
|
-
def include_leaderboard?
|
|
144
|
-
Prefs.bool(key:"lb_in_calendar")
|
|
145
|
-
end
|
|
146
|
-
def title
|
|
147
|
-
"Year #{year}: #{stats.total_stars}/50 *"
|
|
148
|
-
end
|
|
149
|
-
def underline
|
|
150
|
-
"-" * (cal.data[0].to_s.length + 2)
|
|
151
|
-
end
|
|
152
|
-
def make
|
|
153
|
-
<<~file
|
|
154
|
-
#{title}
|
|
155
|
-
#{underline}
|
|
156
|
-
#{cal.data.join("\n")}\n
|
|
157
|
-
#{stats.data.join("\n") if stats.total_stars > 0 &&
|
|
158
|
-
include_leaderboard?}
|
|
159
|
-
file
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
end
|
data/lib/aoc_cli/help.rb
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
def title(title)
|
|
2
|
-
"#{title.bold}"
|
|
3
|
-
end
|
|
4
|
-
def flag(short, full)
|
|
5
|
-
str = " #{short.yellow.bold} [#{full.blue.italic}]"
|
|
6
|
-
full.length > 6 ?
|
|
7
|
-
str += "\t" :
|
|
8
|
-
str += "\t\t"
|
|
9
|
-
str
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
help = <<~help
|
|
13
|
-
Advent of Code - cli, version #{AocCli::VERSION}
|
|
14
|
-
#{"C. Welham Feb 2021".italic}
|
|
15
|
-
|
|
16
|
-
#{title("Usage")}
|
|
17
|
-
#{" aoc".bold + " -flag".italic.yellow + " value".bold.blue}
|
|
18
|
-
|
|
19
|
-
#{title("General")}
|
|
20
|
-
#{flag("-v","--version")}Print version
|
|
21
|
-
#{flag("-h","--help")}Print this screen
|
|
22
|
-
|
|
23
|
-
#{title("Setup")}
|
|
24
|
-
- Store session cookie keys to access AoC
|
|
25
|
-
|
|
26
|
-
#{flag("-k","--key")}Store a session cookie to use the cli.
|
|
27
|
-
#{flag("-u","--user")}Set alias for key (default: "main")
|
|
28
|
-
#{flag("-U","--default")}Get/set default alias
|
|
29
|
-
|
|
30
|
-
#{title("Year Directory")}
|
|
31
|
-
- Initialise a year directory to use aoc-cli.
|
|
32
|
-
- If no alias is passed, the default key is used
|
|
33
|
-
|
|
34
|
-
#{flag("-y","--init-year")}Initialise directory and fetch calendar
|
|
35
|
-
#{flag("-u","--user")}Specify alias for initialisation
|
|
36
|
-
#{flag("-d","--init-day")}Create day subdirectory, fetch puzzle and input
|
|
37
|
-
#{flag("-r", "--refresh")}Refresh calendar
|
|
38
|
-
|
|
39
|
-
#{title("Day Subdirectory")}
|
|
40
|
-
- These commands can be run from the day subdirectory
|
|
41
|
-
|
|
42
|
-
#{flag("-s","--solve")}Attempt puzzle
|
|
43
|
-
#{flag("-p","--part")}Specify part (attempts)
|
|
44
|
-
#{flag("-r","--refresh")}Refresh puzzle
|
|
45
|
-
|
|
46
|
-
#{title("Reddit")}
|
|
47
|
-
- Defaults to a Reddit CLI if one is installed
|
|
48
|
-
|
|
49
|
-
#{flag("-R","--reddit")}Open Reddit solution megathread
|
|
50
|
-
#{flag("-B","--browser")}Open Reddit thread in browser
|
|
51
|
-
|
|
52
|
-
#{title("Manual Usage")}
|
|
53
|
-
- AocCli uses metadata so that these flags do not need to be entered.
|
|
54
|
-
- Command flags can be entered manually, but this is not recommended
|
|
55
|
-
|
|
56
|
-
#{flag("-u","--user")}Specify user
|
|
57
|
-
#{flag("-Y","--year")}Specify year
|
|
58
|
-
#{flag("-D","--day")}Specify day
|
|
59
|
-
#{flag("-p","--part")}Specify part
|
|
60
|
-
|
|
61
|
-
#{title("Configuration")}
|
|
62
|
-
- Pass with a value to update setting
|
|
63
|
-
- Pass without an argument to display current setting.
|
|
64
|
-
|
|
65
|
-
#{flag("-U","--default")}Default key alias to use
|
|
66
|
-
#{flag("-G","--gen-config")}Creates an example config file
|
|
67
|
-
|
|
68
|
-
#{title("Tables")}
|
|
69
|
-
- Print stats in a terminal-friendly table
|
|
70
|
-
|
|
71
|
-
#{flag("-a","--attempts")}Prints previous attempts for puzzle (part needed)
|
|
72
|
-
#{flag("-c","--simple-cal")}Prints your progress
|
|
73
|
-
#{flag("-C","--fancy-cal")}Prints your calendar file
|
|
74
|
-
#{flag("-S","--stats")}Prints your stats (time taken, number of attempts)
|
|
75
|
-
|
|
76
|
-
help
|
|
77
|
-
system("echo '#{help}' | less -r")
|
data/lib/aoc_cli/interface.rb
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
module AocCli
|
|
2
|
-
module Interface
|
|
3
|
-
class Query
|
|
4
|
-
def initialize
|
|
5
|
-
ARGV.size > 0 ?
|
|
6
|
-
run(args:Args.new.parse) : Help.print
|
|
7
|
-
rescue StandardError => e
|
|
8
|
-
abort e.message
|
|
9
|
-
end
|
|
10
|
-
def run(args:)
|
|
11
|
-
cmd = Commands.const_get(Validate.cmd(args.cmd))
|
|
12
|
-
.new(args.args).exec
|
|
13
|
-
cmd.respond if cmd.class
|
|
14
|
-
.instance_methods.include?(:respond)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
class Help
|
|
18
|
-
def self.print
|
|
19
|
-
require_relative "help.rb"
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
class Args
|
|
23
|
-
attr_reader :cmd, :args
|
|
24
|
-
def initialize
|
|
25
|
-
@args = {}
|
|
26
|
-
end
|
|
27
|
-
def parse
|
|
28
|
-
while ARGV.size > 0
|
|
29
|
-
case ARGV.shift
|
|
30
|
-
when "-a", "--attempts"
|
|
31
|
-
@cmd = :AttemptsTable
|
|
32
|
-
when "-B", "--browser"
|
|
33
|
-
@cmd = :OpenReddit
|
|
34
|
-
args[:browser] = true
|
|
35
|
-
when "-c", "--simple-cal"
|
|
36
|
-
@cmd = :CalendarTable
|
|
37
|
-
when "-C", "--fancy-cal"
|
|
38
|
-
@cmd = :PrintCal
|
|
39
|
-
when "-d", "--init-day"
|
|
40
|
-
@cmd = :DayInit
|
|
41
|
-
args[:day] = Validate.day(ARGV.shift.to_i)
|
|
42
|
-
when "-D", "--day"
|
|
43
|
-
args[:day] = ARGV.shift.to_i
|
|
44
|
-
when "-G", "--gen-config"
|
|
45
|
-
@cmd = :GenerateConfig
|
|
46
|
-
when "-h", "--help"
|
|
47
|
-
exit Help.print
|
|
48
|
-
when "-k", "--key"
|
|
49
|
-
@cmd = :KeyStore
|
|
50
|
-
args[:key] = Validate.set_key(ARGV.shift)
|
|
51
|
-
when "-p", "--part"
|
|
52
|
-
args[:part] = ARGV.shift.to_i
|
|
53
|
-
when "-r", "--refresh"
|
|
54
|
-
@cmd = :Refresh
|
|
55
|
-
when "-R", "--reddit"
|
|
56
|
-
@cmd = :OpenReddit
|
|
57
|
-
when "-s", "--solve"
|
|
58
|
-
@cmd = :DaySolve
|
|
59
|
-
args[:ans] = ARGV.shift
|
|
60
|
-
when "-S", "--stats"
|
|
61
|
-
@cmd = :StatsTable
|
|
62
|
-
when "-u", "--user"
|
|
63
|
-
args[:user] = ARGV.shift
|
|
64
|
-
when "-U", "--default"
|
|
65
|
-
@cmd = :DefaultAlias
|
|
66
|
-
args[:user] = ARGV.shift
|
|
67
|
-
when "-v", "--version"
|
|
68
|
-
abort "aoc-cli(#{VERSION})"
|
|
69
|
-
when "-y", "--init-year"
|
|
70
|
-
@cmd = :YearInit
|
|
71
|
-
args[:year] = Validate.year(ARGV.shift.to_i)
|
|
72
|
-
when "-Y", "--year"
|
|
73
|
-
args[:year] = ARGV.shift.to_i
|
|
74
|
-
else raise Errors::FlagInv
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
self
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
data/lib/aoc_cli/paths.rb
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
module AocCli
|
|
2
|
-
module Paths
|
|
3
|
-
require 'fileutils'
|
|
4
|
-
class Year
|
|
5
|
-
attr_reader :user, :year
|
|
6
|
-
def initialize(u:Metafile.get(:user),
|
|
7
|
-
y:Metafile.get(:year))
|
|
8
|
-
@user = Validate.user(u)
|
|
9
|
-
@year = Validate.year(y)
|
|
10
|
-
end
|
|
11
|
-
def in_year?
|
|
12
|
-
File.exist?("./.meta") ?
|
|
13
|
-
Metafile.type == :ROOT : true
|
|
14
|
-
end
|
|
15
|
-
def year_dir
|
|
16
|
-
in_year? ? "." : ".."
|
|
17
|
-
end
|
|
18
|
-
def local(f:)
|
|
19
|
-
"#{Validate.not_init(dir:year_dir,
|
|
20
|
-
year:year)}/#{filename(f:f)}"
|
|
21
|
-
end
|
|
22
|
-
def filename(f:)
|
|
23
|
-
case f.to_sym
|
|
24
|
-
when :Stars then "#{year}.md"
|
|
25
|
-
when :meta then ".meta"
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
class Day
|
|
30
|
-
attr_reader :user, :year, :day
|
|
31
|
-
def initialize(u:Metafile.get(:user),
|
|
32
|
-
y:Metafile.get(:year), d:)
|
|
33
|
-
@user = Validate.user(u)
|
|
34
|
-
@year = Validate.year(y)
|
|
35
|
-
@day = Validate.day(d)
|
|
36
|
-
end
|
|
37
|
-
def create_cache
|
|
38
|
-
FileUtils.mkdir_p(cache_dir) unless Dir.exist?(cache_dir)
|
|
39
|
-
end
|
|
40
|
-
def prefix
|
|
41
|
-
Prefs.string(key:"day_dir_prefix")
|
|
42
|
-
end
|
|
43
|
-
def filename(f:)
|
|
44
|
-
case f.to_sym
|
|
45
|
-
when :Input then "input"
|
|
46
|
-
when :Puzzle then "#{day}.md"
|
|
47
|
-
when :meta then ".meta"
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
def in_day?
|
|
51
|
-
Metafile.type == :DAY
|
|
52
|
-
end
|
|
53
|
-
def day_dir
|
|
54
|
-
day.to_i < 10 ?
|
|
55
|
-
"#{prefix}0#{day}" :
|
|
56
|
-
"#{prefix}#{day}"
|
|
57
|
-
end
|
|
58
|
-
def local_dir
|
|
59
|
-
in_day? ? "." : "#{day_dir}"
|
|
60
|
-
end
|
|
61
|
-
def cache_dir
|
|
62
|
-
"#{Dir.home}/.cache/aoc-cli/"\
|
|
63
|
-
"#{user}/#{year}/#{day_dir}"
|
|
64
|
-
end
|
|
65
|
-
def local(f:)
|
|
66
|
-
"#{local_dir}/#{filename(f:f)}"
|
|
67
|
-
end
|
|
68
|
-
def cache_path(f:)
|
|
69
|
-
"#{cache_dir}/#{filename(f:f)}"
|
|
70
|
-
end
|
|
71
|
-
def cache_and_local(f:)
|
|
72
|
-
[cache_path(f:f), local(f:f)]
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
class Config
|
|
76
|
-
def self.create
|
|
77
|
-
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
|
78
|
-
File.write(path, "", mode:"a") unless File.exist?(path)
|
|
79
|
-
end
|
|
80
|
-
def self.dir
|
|
81
|
-
"#{Dir.home}/.config/aoc-cli"
|
|
82
|
-
end
|
|
83
|
-
def self.path
|
|
84
|
-
"#{dir}/aoc.rc"
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
class Database < Config
|
|
88
|
-
def self.dir
|
|
89
|
-
"#{super}/db"
|
|
90
|
-
end
|
|
91
|
-
def self.cfg(name)
|
|
92
|
-
FileUtils.mkdir_p(dir) unless Dir
|
|
93
|
-
.exist?(dir)
|
|
94
|
-
"#{dir}/#{name}.db"
|
|
95
|
-
end
|
|
96
|
-
def self.root(name)
|
|
97
|
-
"#{__dir__}/db/#{name}.db"
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|