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
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")
@@ -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
data/lib/aoc_cli/solve.rb DELETED
@@ -1,104 +0,0 @@
1
- module AocCli
2
- module Solve
3
- CORRECT = "That's the right answer"
4
- INCORRECT = "That's not the right answer"
5
- WAIT = "You gave an answer too recently"
6
- class Attempt
7
- attr_reader :user, :year, :day, :part, :answer
8
- def initialize(u:Metafile.get(:user),
9
- y:Metafile.get(:year),
10
- d:Metafile.get(:day),
11
- p:Metafile.get(:part), a:)
12
- @user = Validate.user(u)
13
- @year = Validate.year(y)
14
- @day = Validate.day(d)
15
- @part = Validate.part(p)
16
- @answer = Validate.ans(attempt:self, ans:a)
17
- end
18
- def exists?
19
- Database::Attempt.new(attempt:self)
20
- end
21
- def raw
22
- @raw ||= Tools::Post.new(u:user, y:year, d:day,
23
- data:{level:part, answer:answer}).plain
24
- end
25
- def check
26
- case raw
27
- when /#{CORRECT}/ then :Correct
28
- when /#{INCORRECT}/ then :Incorrect
29
- when /#{WAIT}/ then :Wait
30
- end
31
- end
32
- def respond
33
- Respond.const_get(check)
34
- .new(attempt:self)
35
- .respond
36
- .react
37
- end
38
- end
39
- module Respond
40
- class Response
41
- attr_reader :attempt
42
- def initialize(attempt:)
43
- @attempt = attempt
44
- end
45
- end
46
- class Correct < Response
47
- def react
48
- Database.correct(attempt:attempt)
49
- Year.refresh
50
- Day.refresh(files:[:Puzzle])
51
- end
52
- def respond
53
- puts <<~response
54
- #{"Correct!".bold.green} #{
55
- case attempt.part
56
- when "1" then "Downloading part two..."
57
- when "2" then "This day is now complete!".green
58
- end }
59
- response
60
- self
61
- end
62
- end
63
- class Incorrect < Response
64
- def react
65
- Database::Attempt
66
- .new(attempt:attempt)
67
- .incorrect(high:high, low:low)
68
- end
69
- def respond
70
- puts <<~response
71
- #{"Incorrect".red.bold}: You guessed - #{attempt
72
- .answer.to_s.red} #{
73
- high ? "(too high)" :
74
- low ? "(too low)" : ""}
75
- #{"Please wait".yellow} #{wait_time} before answering again
76
- response
77
- self
78
- end
79
- def high
80
- /too high/.match?(attempt.raw)
81
- end
82
- def low
83
- /too low/.match?(attempt.raw)
84
- end
85
- def wait_time
86
- attempt.raw.scan(/(?:(one minute|\d+ minutes))/)
87
- .first.first.to_s
88
- end
89
- end
90
- class Wait < Response
91
- def respond
92
- puts <<~response
93
- #{"Please wait".yellow.bold}: #{time.to_s}
94
- response
95
- self
96
- end
97
- def time
98
- attempt.raw.scan(/(?:\d+m\s)?\d+s/).first.to_s
99
- end
100
- def react; end
101
- end
102
- end
103
- end
104
- end
@@ -1,138 +0,0 @@
1
- module AocCli
2
- module Tables
3
- class Table
4
- require 'terminal-table'
5
- attr_reader :user, :year, :table, :cols, :where
6
- def initialize(u:Metafile.get(:user), y:Metafile.get(:year))
7
- @user = Validate.user(u)
8
- @year = Validate.year(y)
9
- end
10
- def border
11
- Prefs.bool(key:"unicode_tables") ? :unicode : :ascii
12
- end
13
- def data
14
- Database::Query
15
- .new(path:Paths::Database.cfg(user))
16
- .select(t:table, cols:cols, where:where)
17
- end
18
- def print
19
- puts rows.count > 0 ? make : nil_message
20
- end
21
- def make
22
- tab = Terminal::Table.new(
23
- :headings => headings,
24
- :rows => rows,
25
- :title => title)
26
- tab.style = {
27
- :border => border,
28
- :alignment => :center}
29
- tab
30
- end
31
- end
32
- class Attempts < Table
33
- attr_reader :day, :part
34
- def initialize(u:Metafile.get(:user),
35
- y:Metafile.get(:year),
36
- d:Metafile.get(:day),
37
- p:Metafile.get(:part))
38
- super(u:u, y:y)
39
- @day = Validate.day(d)
40
- @part = Validate.part(p)
41
- @table = :attempts
42
- @cols = "time, answer, high, low, correct"
43
- @where = {year:year, day:day, part:part}
44
- end
45
- def title
46
- "#{year} - Day #{day}:#{part}".bold
47
- end
48
- def headings
49
- ["Answer", "Time", "Hint"]
50
- end
51
- def rows
52
- @rows ||= data.map do |d|
53
- [parse_ans(d), parse_time(d), parse_hint(d)]
54
- end
55
- end
56
- def parse_ans(row)
57
- row[4] == 1 ? row[1].to_s.green : row[1].to_s.red
58
- end
59
- def parse_time(row)
60
- DateTime.strptime(row[0], "%Y-%m-%d %H:%M:%S %Z")
61
- .strftime("%H:%M - %d/%m/%y")
62
- end
63
- def parse_hint(row)
64
- row[3] == 1 ? "low" :
65
- row[2] == 1 ? "high" : "-"
66
- end
67
- def nil_message
68
- "You have not attempted part #{part} yet!"
69
- end
70
- end
71
- module Stats
72
- class Year < Table
73
- def initialize(u:Metafile.get(:user),
74
- y:Metafile.get(:year))
75
- super(u:u, y:y)
76
- @table = :stats
77
- @cols = "day, part, attempts, elapsed"
78
- @where = {year:"'#{year}'", correct:"'1'"}
79
- end
80
- def title
81
- "Year #{year}"
82
- end
83
- def headings
84
- ["Day", "Part", "Attempts", "Time (h:m:s)"]
85
- end
86
- def rows
87
- @rows ||= data.map{|d| [d[0], d[1], d[2], d[3]]}
88
- end
89
- def nil_message
90
- "You have not completed any puzzles yet"
91
- end
92
- end
93
- class Day < Year
94
- attr_reader :day
95
- def initialize(u:Metafile.get(:user),
96
- y:Metafile.get(:year),
97
- d:Metafile.get(:day))
98
- super(u:u, y:y)
99
- @day = Validate.day(d)
100
- @cols = "part, attempts, elapsed"
101
- @where = { year:"'#{year}'",
102
- day:"'#{day}'",
103
- correct:"'1'" }
104
- end
105
- def title
106
- "Year #{year}: Day #{day}"
107
- end
108
- def headings
109
- ["Part", "Attempts", "Time (h:m:s)"]
110
- end
111
- def rows
112
- @rows ||= data.map{|d| [d[0], d[1], d[2]]}
113
- end
114
- end
115
- end
116
- class Calendar < Table
117
- def initialize(u:Metafile.get(:user),
118
- y:Metafile.get(:year))
119
- super(u:u, y:y)
120
- @table = :calendar
121
- @cols = "*"
122
- @where = {year:year}
123
- end
124
- def title
125
- "#{user}: #{year}"
126
- end
127
- def headings
128
- ["Day", "Stars"]
129
- end
130
- def rows
131
- @rows ||= data.map{|d| [d[1], parse_stars(d[2])]}
132
- end
133
- def parse_stars(day)
134
- day.to_i == 0 ? ".." : ("*" * day.to_i).ljust(2, ".")
135
- end
136
- end
137
- end
138
- end