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.
Files changed (157) 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/db/migrate/7_create_progresses.rb +17 -0
  18. data/db/migrate/8_remove_legacy_timestamps.rb +8 -0
  19. data/exe/aoc +5 -0
  20. data/lib/aoc_cli/components/attempts_table.erb +5 -0
  21. data/lib/aoc_cli/components/attempts_table.rb +58 -0
  22. data/lib/aoc_cli/components/docs_component.erb +19 -0
  23. data/lib/aoc_cli/components/docs_component.rb +41 -0
  24. data/lib/aoc_cli/components/errors_component.erb +8 -0
  25. data/lib/aoc_cli/components/errors_component.rb +36 -0
  26. data/lib/aoc_cli/components/progress_table.erb +1 -0
  27. data/lib/aoc_cli/components/progress_table.rb +43 -0
  28. data/lib/aoc_cli/components/puzzle_sync_component.erb +2 -0
  29. data/lib/aoc_cli/components/puzzle_sync_component.rb +26 -0
  30. data/lib/aoc_cli/configurators/session_configurator.rb +7 -0
  31. data/lib/aoc_cli/controllers/application_controller.rb +27 -0
  32. data/lib/aoc_cli/controllers/concerns/error_concern.rb +17 -0
  33. data/lib/aoc_cli/controllers/concerns/location_concern.rb +79 -0
  34. data/lib/aoc_cli/controllers/default_controller.rb +9 -0
  35. data/lib/aoc_cli/controllers/event_controller.rb +35 -0
  36. data/lib/aoc_cli/controllers/help/event_controller.rb +11 -0
  37. data/lib/aoc_cli/controllers/help/puzzle_controller.rb +13 -0
  38. data/lib/aoc_cli/controllers/puzzle_controller.rb +39 -0
  39. data/lib/aoc_cli/core/attempt_parser.rb +69 -0
  40. data/lib/aoc_cli/core/processor.rb +32 -0
  41. data/lib/aoc_cli/core/repository.rb +74 -0
  42. data/lib/aoc_cli/core/request.rb +37 -0
  43. data/lib/aoc_cli/core/resource.rb +39 -0
  44. data/lib/aoc_cli/core/stats_parser.rb +43 -0
  45. data/lib/aoc_cli/helpers/table_generator.rb +64 -0
  46. data/lib/aoc_cli/helpers/view_helper.rb +35 -0
  47. data/lib/aoc_cli/models/attempt.rb +67 -0
  48. data/lib/aoc_cli/models/event.rb +9 -0
  49. data/lib/aoc_cli/models/location.rb +24 -0
  50. data/lib/aoc_cli/models/progress.rb +33 -0
  51. data/lib/aoc_cli/models/puzzle.rb +28 -0
  52. data/lib/aoc_cli/models/puzzle_dir_sync_log.rb +14 -0
  53. data/lib/aoc_cli/models/stats.rb +43 -0
  54. data/lib/aoc_cli/presenters/attempt_presenter.rb +29 -0
  55. data/lib/aoc_cli/presenters/puzzle_presenter.rb +29 -0
  56. data/lib/aoc_cli/presenters/stats_presenter.rb +32 -0
  57. data/lib/aoc_cli/processors/event_initialiser.rb +64 -0
  58. data/lib/aoc_cli/processors/progress_syncer.rb +48 -0
  59. data/lib/aoc_cli/processors/puzzle_dir_synchroniser.rb +80 -0
  60. data/lib/aoc_cli/processors/puzzle_initialiser.rb +106 -0
  61. data/lib/aoc_cli/processors/puzzle_refresher.rb +27 -0
  62. data/lib/aoc_cli/processors/resource_attacher.rb +22 -0
  63. data/lib/aoc_cli/processors/solution_poster.rb +72 -0
  64. data/lib/aoc_cli/processors/stats_initialiser.rb +36 -0
  65. data/lib/aoc_cli/processors/stats_refresher.rb +23 -0
  66. data/lib/aoc_cli/validators/collection_type_validator.rb +57 -0
  67. data/lib/aoc_cli/validators/event_year_validator.rb +42 -0
  68. data/lib/aoc_cli/validators/included_validator.rb +21 -0
  69. data/lib/aoc_cli/validators/integer_validator.rb +32 -0
  70. data/lib/aoc_cli/validators/path_validator.rb +39 -0
  71. data/lib/aoc_cli/validators/type_validator.rb +54 -0
  72. data/lib/aoc_cli/version.rb +1 -1
  73. data/lib/aoc_cli/views/event/attach.erb +3 -0
  74. data/lib/aoc_cli/views/event/init.erb +3 -0
  75. data/lib/aoc_cli/views/help/event/attach.erb +32 -0
  76. data/lib/aoc_cli/views/help/event/init.erb +38 -0
  77. data/lib/aoc_cli/views/help/event/progress.erb +12 -0
  78. data/lib/aoc_cli/views/help/puzzle/attempts.erb +12 -0
  79. data/lib/aoc_cli/views/help/puzzle/init.erb +31 -0
  80. data/lib/aoc_cli/views/help/puzzle/solve.erb +33 -0
  81. data/lib/aoc_cli/views/help/puzzle/sync.erb +32 -0
  82. data/lib/aoc_cli/views/puzzle/init.erb +3 -0
  83. data/lib/aoc_cli/views/puzzle/solve.erb +10 -0
  84. data/lib/aoc_cli.rb +36 -16
  85. data/rbs_collection.lock.yaml +168 -0
  86. data/rbs_collection.yaml +28 -0
  87. data/sig/aoc_cli/components/attempts_table.rbs +29 -0
  88. data/sig/aoc_cli/components/docs_component.rbs +15 -0
  89. data/sig/aoc_cli/components/errors_component.rbs +19 -0
  90. data/sig/aoc_cli/components/progress_table.rbs +28 -0
  91. data/sig/aoc_cli/components/puzzle_sync_component.rbs +19 -0
  92. data/sig/aoc_cli/configurators/session_configurator.rbs +7 -0
  93. data/sig/aoc_cli/controllers/application_controller.rbs +12 -0
  94. data/sig/aoc_cli/controllers/concerns/error_concern.rbs +9 -0
  95. data/sig/aoc_cli/controllers/concerns/location_concern.rbs +35 -0
  96. data/sig/aoc_cli/controllers/default_controller.rbs +7 -0
  97. data/sig/aoc_cli/controllers/event_controller.rbs +18 -0
  98. data/sig/aoc_cli/controllers/help/event_controller.rbs +11 -0
  99. data/sig/aoc_cli/controllers/help/puzzle_controller.rbs +13 -0
  100. data/sig/aoc_cli/controllers/puzzle_controller.rbs +15 -0
  101. data/sig/aoc_cli/core/attempt_parser.rbs +41 -0
  102. data/sig/aoc_cli/core/processor.rbs +25 -0
  103. data/sig/aoc_cli/core/repository.rbs +25 -0
  104. data/sig/aoc_cli/core/request.rbs +29 -0
  105. data/sig/aoc_cli/core/resource.rbs +25 -0
  106. data/sig/aoc_cli/core/stats_parser.rbs +23 -0
  107. data/sig/aoc_cli/helpers/table_generator.rbs +36 -0
  108. data/sig/aoc_cli/helpers/view_helper.rbs +15 -0
  109. data/sig/aoc_cli/models/attempt.rbs +35 -0
  110. data/sig/aoc_cli/models/event.rbs +17 -0
  111. data/sig/aoc_cli/models/location.rbs +19 -0
  112. data/sig/aoc_cli/models/progress.rbs +21 -0
  113. data/sig/aoc_cli/models/puzzle.rbs +27 -0
  114. data/sig/aoc_cli/models/puzzle_dir_sync_log.rbs +11 -0
  115. data/sig/aoc_cli/models/stats.rbs +53 -0
  116. data/sig/aoc_cli/presenters/attempt_presenter.rbs +13 -0
  117. data/sig/aoc_cli/presenters/puzzle_presenter.rbs +19 -0
  118. data/sig/aoc_cli/presenters/stats_presenter.rbs +19 -0
  119. data/sig/aoc_cli/processors/event_initialiser.rbs +26 -0
  120. data/sig/aoc_cli/processors/progress_syncer.rbs +29 -0
  121. data/sig/aoc_cli/processors/puzzle_dir_synchroniser.rbs +40 -0
  122. data/sig/aoc_cli/processors/puzzle_initialiser.rbs +41 -0
  123. data/sig/aoc_cli/processors/puzzle_refresher.rbs +21 -0
  124. data/sig/aoc_cli/processors/resource_attacher.rbs +16 -0
  125. data/sig/aoc_cli/processors/solution_poster.rbs +34 -0
  126. data/sig/aoc_cli/processors/stats_initialiser.rbs +15 -0
  127. data/sig/aoc_cli/processors/stats_refresher.rbs +19 -0
  128. data/sig/aoc_cli/validators/collection_type_validator.rbs +24 -0
  129. data/sig/aoc_cli/validators/event_year_validator.rbs +19 -0
  130. data/sig/aoc_cli/validators/included_validator.rbs +11 -0
  131. data/sig/aoc_cli/validators/integer_validator.rbs +15 -0
  132. data/sig/aoc_cli/validators/path_validator.rbs +17 -0
  133. data/sig/aoc_cli/validators/type_validator.rbs +22 -0
  134. data/sig/aoc_cli.rbs +6 -0
  135. data/sig/http.rbs +3 -0
  136. data/sig/kangaru.rbs +5 -0
  137. data/sig/nokogiri.rbs +3 -0
  138. data/sig/reverse_markdown.rbs +3 -0
  139. metadata +149 -34
  140. data/.gitignore +0 -5
  141. data/bin/aoc +0 -4
  142. data/bin/console +0 -15
  143. data/bin/setup +0 -7
  144. data/lib/aoc_cli/commands.rb +0 -232
  145. data/lib/aoc_cli/database.rb +0 -224
  146. data/lib/aoc_cli/day.rb +0 -124
  147. data/lib/aoc_cli/db/reddit.db +0 -0
  148. data/lib/aoc_cli/errors.rb +0 -275
  149. data/lib/aoc_cli/files.rb +0 -163
  150. data/lib/aoc_cli/help.rb +0 -77
  151. data/lib/aoc_cli/interface.rb +0 -81
  152. data/lib/aoc_cli/paths.rb +0 -101
  153. data/lib/aoc_cli/solve.rb +0 -104
  154. data/lib/aoc_cli/tables.rb +0 -138
  155. data/lib/aoc_cli/tools.rb +0 -120
  156. data/lib/aoc_cli/year.rb +0 -116
  157. data/sample/aoc.rc +0 -21
@@ -1,232 +0,0 @@
1
- module AocCli
2
- module Commands
3
- class KeyStore
4
- attr_reader :user, :key
5
- def initialize(args)
6
- args = defaults.merge(args).compact
7
- @user, @key = args[:user], args[:key]
8
- end
9
- def exec
10
- Files::Config::Cookie.store(user:user, key:key)
11
- self
12
- end
13
- def respond
14
- puts "Key added successfully"
15
- end
16
- def defaults
17
- { user:"main" }
18
- end
19
- end
20
- class YearInit
21
- attr_reader :user, :year, :git
22
- def initialize(args)
23
- args = defaults.merge(args).compact
24
- @user, @year, @git = args[:user], args[:year], args[:git]
25
- end
26
- def exec
27
- Year::Meta.new(u:user, y:year).write
28
- Year::Progress.new(u:user, y:year).write.init_calendar_db
29
- Year::GitWrap.new if git
30
- self
31
- end
32
- def respond
33
- puts "Year #{year} initialised"
34
- end
35
- def defaults
36
- { user:Prefs.default_alias,
37
- git:Prefs.bool(key:"init_git") }
38
- end
39
- end
40
- class DayInit
41
- attr_reader :user, :year, :day
42
- def initialize(args)
43
- args = defaults.merge(args).compact
44
- @user = args[:user]
45
- @year = args[:year]
46
- @day = args[:day]
47
- end
48
- def exec
49
- Day::Init.new(u:user, y:year, d:day).mkdir.meta
50
- Day::Pages.new(u:user, y:year, d:day).load
51
- self
52
- end
53
- def defaults
54
- { user:Metafile.get(:user),
55
- year:Metafile.get(:year) }
56
- end
57
- def respond
58
- puts "Day #{day} initialised"
59
- end
60
- end
61
- class DaySolve
62
- attr_reader :user, :year, :day, :part, :ans
63
- def initialize(args)
64
- args = defaults.merge(args).compact
65
- @user = args[:user]
66
- @year = args[:year]
67
- @day = args[:day]
68
- @part = args[:part]
69
- @ans = args[:ans]
70
- end
71
- def exec
72
- Solve::Attempt
73
- .new(u:user, y:year, d:day, p:part, a:ans)
74
- .respond
75
- self
76
- end
77
- def defaults
78
- {user:Metafile.get(:user),
79
- year:Metafile.get(:year),
80
- day:Metafile.get(:day),
81
- part:Metafile.get(:part)}
82
- end
83
- end
84
- class OpenReddit
85
- attr_reader :year, :day, :browser
86
- def initialize(args)
87
- args = defaults.merge(args).compact
88
- @year = Validate.year(args[:year])
89
- @day = Validate.day(args[:day])
90
- @browser = args[:browser]
91
- end
92
- def exec
93
- Tools::Reddit.new(y:year, d:day, b:browser).open
94
- self
95
- end
96
- def defaults
97
- { year:Metafile.get(:year),
98
- day:Metafile.get(:day),
99
- browser:Prefs.bool(key:"reddit_in_browser") }
100
- end
101
- end
102
- class DefaultAlias
103
- attr_reader :user, :mode
104
- def initialize(args)
105
- @user = args[:user]
106
- @mode = user.nil? ? :get : :set
107
- end
108
- def exec
109
- set if mode == :set && alias_valid
110
- self
111
- end
112
- def respond
113
- case mode
114
- when :get then current
115
- when :set then update end
116
- end
117
- private
118
- def set
119
- Files::Config::Tools
120
- .mod_line(key:"default", val:Validate.user(user))
121
- end
122
- def current
123
- puts <<~aliases
124
- Default alias: #{Prefs.default_alias.yellow}
125
- All aliases: #{Prefs.list_aliases.map{|a| a.blue}
126
- .join(", ")}
127
- aliases
128
- end
129
- def alias_valid
130
- Validate.key(Files::Config::Cookie.key(user:user))
131
- end
132
- def update
133
- puts "Default alias changed to: #{user.yellow}"
134
- end
135
- end
136
- class Refresh
137
- def initialize(args)
138
- end
139
- def exec
140
- case Metafile.type
141
- when :DAY then Day.refresh
142
- when :ROOT then Year.refresh end
143
- self
144
- end
145
- end
146
- class AttemptsTable
147
- attr_reader :user, :year, :day, :part
148
- def initialize(args)
149
- args = defaults.merge(args).compact
150
- @user = args[:user]
151
- @year = args[:year]
152
- @day = args[:day]
153
- @part = args[:part]
154
- end
155
- def exec
156
- Tables::Attempts.new(u:user, y:year, d:day, p:part).print
157
- self
158
- end
159
- def defaults
160
- {user:Metafile.get(:user),
161
- year:Metafile.get(:year),
162
- day:Metafile.get(:day),
163
- part:Metafile.get(:part)}
164
- end
165
- end
166
- class StatsTable
167
- attr_reader :user, :year, :day
168
- def initialize(args)
169
- args = defaults.merge(args).compact
170
- @user = args[:user]
171
- @year = args[:year]
172
- @day = args[:day]
173
- end
174
- def exec
175
- day.nil? ?
176
- Tables::Stats::Year.new(u:user, y:year).print :
177
- Tables::Stats::Day.new(u:user, y:year, d:day).print
178
- end
179
- def defaults
180
- { user:Metafile.get(:user),
181
- year:Metafile.get(:year),
182
- day:Metafile.get(:day) }
183
- end
184
- end
185
- class CalendarTable
186
- attr_reader :user, :year
187
- def initialize(args)
188
- args = defaults.merge(args).compact
189
- @user = Validate.user(args[:user])
190
- @year = Validate.year(args[:year])
191
- end
192
- def exec
193
- Tables::Calendar.new(u:user, y:year).print
194
- end
195
- def defaults
196
- { user:Metafile.get(:user),
197
- year:Metafile.get(:year) }
198
- end
199
- end
200
- class PrintCal
201
- attr_reader :path, :year
202
- def initialize(args)
203
- args = defaults.merge(args).compact
204
- @year = Validate.year(args[:year])
205
- end
206
- def path
207
- case Metafile.type
208
- when :DAY then "../#{year}.md"
209
- when :ROOT then "#{year}.md"
210
- end
211
- end
212
- def exec
213
- Prefs.bool(key:"calendar_file") ?
214
- system("cat #{path} | less") :
215
- puts("You have disabled calendar files")
216
- end
217
- def defaults
218
- {year:Metafile.get(:year)}
219
- end
220
- end
221
- class GenerateConfig
222
- def initialize(args) end
223
- def exec
224
- Files::Config::Example.write
225
- self
226
- end
227
- def respond
228
- puts "Default config written to #{Paths::Config.path.blue}"
229
- end
230
- end
231
- end
232
- end
@@ -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