advent 0.1.6 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a49571ac28572d7a91bcc6a26ecb7253b4f10690dfe2c529a86eca8d310b059b
4
- data.tar.gz: 470af342600d4fac184e63837dd0f0cdfbd27d34268d34d4a191ef65ce59b960
3
+ metadata.gz: ab18c0d8a6206b03d6b070b406f4e746d6a0e312fabfe5aaa799a53399036b41
4
+ data.tar.gz: 12ba2ad51722b2f67edfcc3025e595b094492afdded74b49e4e3487a3994a8ee
5
5
  SHA512:
6
- metadata.gz: e94342f2d83c40b0bd360478d7535583da1076517b218c045b44ead0d455e389c174e58c92321da978f63cecbd41abfff0904927552b1acaeb08853b74874a34
7
- data.tar.gz: 5d2af6a890fc835148f7e1bc054ef49a3e69e641d7a93528ae184b8b39d48a8c69ce4cdf166c29750525750167278c8c84350d8c2d766df77c8d2a2b30f4e502
6
+ metadata.gz: ded4631baad2a0f0d30897fd9ae8a58d88c1874c40cedbc9c8599f5e2d639cd650d78e88c4a0e204f4ef88ac4b41238b5357aa1234ec13952ed84125e0449e74
7
+ data.tar.gz: 05b6cb034169d7b1fa6e4b6a4f52fd6a09a4c3e7394882df99438a064b99251e698e4991361bede9d57a6ef83dafd8ba536e74a53d0229d918e8d88a558661d9
data/{exe → bin}/advent RENAMED
@@ -2,6 +2,6 @@
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
4
 
5
- require "advent/cli"
5
+ require "advent"
6
6
 
7
- Advent::CLI.start
7
+ Advent::Cli.start ARGV
data/lib/advent/cli.rb CHANGED
@@ -1,101 +1,62 @@
1
- # frozen_string_literal: true
2
-
3
- require "advent"
4
- require "date"
5
- require "pathname"
6
1
  require "thor"
7
2
 
8
- module Advent
9
- class CLI < Thor
10
- include Thor::Actions
11
- EXCLUDED_ROOT_COMMANDS = %w[help init version]
12
-
13
- class_option :http_module, default: Net::HTTP, check_default_type: false
14
-
15
- def initialize(*args)
16
- super
17
-
18
- source_paths << File.expand_path("templates", __dir__)
19
-
20
- # Don't try to load Advent.root if we're a command that doesn't need it
21
- unless EXCLUDED_ROOT_COMMANDS.include? args.last[:current_command]&.name
22
- self.destination_root = Advent.root
23
- end
24
- end
25
-
26
- # @return [Boolean] defines whether an exit status is set if a command fails
27
- def self.exit_on_failure?
28
- true
29
- end
3
+ class Advent::Cli < Thor
4
+ include Thor::Actions
30
5
 
31
- desc "download YEAR DAY", "Download the input for YEAR and DAY"
32
- def download(year, day)
33
- require "advent/cli/downloader"
6
+ def self.exit_on_failure?
7
+ true
8
+ end
34
9
 
35
- Dir.chdir Advent.root do
36
- Downloader.new(self, year, day).download
37
- end
38
- end
10
+ desc "auth", "remember your session for downloading inputs"
11
+ option :session, aliases: "-s", type: :string, default: nil, desc: "Provide the value directly without being prompted"
12
+ def auth
13
+ session = options[:session] || ask("What is your Advent of Code session value?", echo: false)
14
+ say ""
39
15
 
40
- desc "generate YEAR DAY", "Generate a new solution for YEAR and DAY"
41
- # Generates a new solution file. If within a year directory, only the day
42
- # is used, otherwise both the year and day will be required to generate the
43
- # output.
44
- def generate(year, day)
45
- year = parse_number year
46
- day = parse_number day
16
+ create_file ".advent_session", session
17
+ append_to_file ".gitignore", ".advent_session" if File.exist? ".git"
18
+ end
47
19
 
48
- if (message = validate(year, day))
49
- say_error message, :red
50
- return
51
- end
20
+ desc "download YEAR DAY", "download input"
21
+ def download(year, day)
22
+ get "https://adventofcode.com/#{year}/day/#{day}/input", "#{year}/.day#{day}_input.txt", http_headers: http_headers
23
+ end
52
24
 
53
- template "solution.rb.tt", "#{year}/day#{day}.rb", context: binding
54
- template "solution_test.rb.tt", "#{year}/test/day#{day}_test.rb", context: binding
25
+ desc "new YEAR DAY", "start a new solution"
26
+ def new(year, day)
27
+ self.class.source_root __dir__
55
28
 
56
- download year, day if Advent.config.download_when_generating
57
- end
29
+ template "templates/solution.rb.tt", "#{year}/day#{day}.rb", context: binding
30
+ template "templates/solution_test.rb.tt", "test/#{year}/day#{day}_test.rb", context: binding
31
+ end
58
32
 
59
- desc "init DIR", "Initialise a new advent project in DIR"
60
- def init(dir = ".")
61
- create_file Pathname.getwd.join(dir).join(Advent::Configuration::FILE_NAME) do
62
- ""
63
- end
64
- end
33
+ desc "solve FILE", "solve your solution"
34
+ def solve(path)
35
+ load path
65
36
 
66
- desc "solve FILE", "Solve your solution"
67
- # Runs a solution file, outputting both :part1 and :part2 method return values.
68
- def solve(path)
69
- require "advent/cli/solver"
70
- file_path = Pathname.getwd.join(path)
37
+ require "active_support/core_ext/object/blank"
38
+ require "active_support/core_ext/string/inflections"
39
+ require "pathname"
40
+ klass = Pathname.new(path).basename(".rb").to_s.classify.constantize
71
41
 
72
- Dir.chdir Advent.root do
73
- Solver.new(self, file_path.relative_path_from(Advent.root)).solve
74
- end
75
- end
42
+ part_1 = klass.new.part_1
43
+ part_2 = klass.new.part_2
76
44
 
77
- desc "version", "Prints the current version of the gem"
78
- # Prints the current version of the gem
79
- def version
80
- say Advent::VERSION
81
- end
45
+ say_status "Part 1", part_1.presence || "No answer", part_1.present? ? :green : :red
46
+ say_status "Part 2", part_2.presence || "No answer", part_2.present? ? :green : :red
47
+ end
82
48
 
83
- private
49
+ desc "version", "current gem version"
50
+ def version
51
+ say Advent::VERSION
52
+ end
84
53
 
85
- def parse_number(str)
86
- if (m = str.match(/[0-9]+/))
87
- m[0]
88
- end
54
+ private
55
+ def http_headers
56
+ {"Cookie" => CGI::Cookie.new("session", session).to_s}
89
57
  end
90
58
 
91
- def validate(year, day)
92
- if year.to_i < 2014
93
- "Advent of Code only started in 2014!"
94
- elsif year.to_i > Date.today.year
95
- "Future years are not supported."
96
- elsif !(1..25).cover? day.to_i
97
- "Day must be between 1 and 25 (inclusive)."
98
- end
59
+ def session
60
+ File.read(".advent_session").chomp
99
61
  end
100
- end
101
62
  end
@@ -1,45 +1,10 @@
1
- # frozen_string_literal: true
1
+ class Advent::Solution
2
+ def input_text
3
+ require "pathname"
2
4
 
3
- require "pathname"
5
+ location, _ = Object.const_source_location(self.class.to_s)
6
+ path = Pathname.new(location)
4
7
 
5
- module Advent
6
- # Baes class for an Advent of Code solution attempt. If subclass is in a
7
- # directory matching a year (eg. 2015) and the filename is for a particular
8
- # day (eg. day1.rb) then the @year and @day instance variables are
9
- # automatically inferred.
10
- class Solution
11
- attr_reader :year # @return [Numeric] the year this solution is from
12
- attr_reader :day # @return [Numeric] the day this solution is for
13
-
14
- def initialize
15
- year, day = infer_year_and_day_from_file_system
16
-
17
- @year = year
18
- @day = day
19
-
20
- @input = Input.new(source_location.dirname, day: day)
21
- end
22
-
23
- def load_input
24
- File.read(@input.file_path)
25
- end
26
-
27
- private
28
-
29
- def infer_year_and_day_from_file_system
30
- path, day = source_location.split
31
-
32
- day = /day([0-9]+)/.match(day.to_s)[1]
33
- year = path.basename.to_s
34
-
35
- [year, day].map(&:to_i)
36
- rescue
37
- raise Error, "Failed to infer year/day of solution."
38
- end
39
-
40
- def source_location
41
- class_path, _ = Object.const_source_location(self.class.to_s)
42
- Pathname.new(class_path)
43
- end
8
+ path.dirname.join(".#{path.basename(".rb")}_input.txt").read
44
9
  end
45
10
  end
@@ -1,11 +1,9 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "advent"
4
2
 
5
3
  class Day<%= day %> < Advent::Solution
6
- def part1(input: load_input)
4
+ def part_1(input: input_text)
7
5
  end
8
6
 
9
- def part2(input: load_input)
7
+ def part_2(input: input_text)
10
8
  end
11
9
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "advent"
4
2
  require "minitest/autorun"
5
3
 
@@ -1,6 +1,4 @@
1
1
  require "minitest"
2
2
 
3
- module Advent
4
- class TestCase < Minitest::Test
5
- end
3
+ class Advent::TestCase < Minitest::Test
6
4
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Advent
4
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
5
3
  end
data/lib/advent.rb CHANGED
@@ -1,39 +1,10 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "advent/configuration"
4
- require_relative "advent/input"
5
- require_relative "advent/session"
6
- require_relative "advent/solution"
7
- require_relative "advent/test_case"
8
- require_relative "advent/version"
1
+ require "active_support"
2
+ require "zeitwerk"
3
+ loader = Zeitwerk::Loader.for_gem
4
+ loader.setup
9
5
 
10
6
  module Advent
11
7
  class Error < StandardError; end
12
-
13
- class << self
14
- def config
15
- @_config ||= Configuration.from_file(root.join(Configuration::FILE_NAME))
16
- end
17
-
18
- def root
19
- if (location = find_config_location)
20
- location
21
- else
22
- raise Error, "Cannot find advent.yml config file in current or parent directories."
23
- end
24
- end
25
-
26
- def session
27
- @_session ||= Session.new
28
- end
29
-
30
- private
31
-
32
- def find_config_location
33
- Pathname.new(Dir.pwd).ascend do |path|
34
- return path if File.exist? path.join(Configuration::FILE_NAME)
35
- return nil if path.to_s == "/"
36
- end
37
- end
38
- end
39
8
  end
9
+
10
+ loader.eager_load
metadata CHANGED
@@ -1,29 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: advent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Grieve
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-02 00:00:00.000000000 Z
11
+ date: 2023-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: thor
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - "~>"
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
18
46
  - !ruby/object:Gem::Version
19
- version: '1.2'
47
+ version: '0'
20
48
  type: :runtime
21
49
  prerelease: false
22
50
  version_requirements: !ruby/object:Gem::Requirement
23
51
  requirements:
24
- - - "~>"
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: debug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
25
67
  - !ruby/object:Gem::Version
26
- version: '1.2'
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
27
111
  description:
28
112
  email:
29
113
  - dnlgrv@hey.com
@@ -34,14 +118,9 @@ extra_rdoc_files: []
34
118
  files:
35
119
  - LICENSE.txt
36
120
  - README.md
37
- - exe/advent
121
+ - bin/advent
38
122
  - lib/advent.rb
39
123
  - lib/advent/cli.rb
40
- - lib/advent/cli/downloader.rb
41
- - lib/advent/cli/solver.rb
42
- - lib/advent/configuration.rb
43
- - lib/advent/input.rb
44
- - lib/advent/session.rb
45
124
  - lib/advent/solution.rb
46
125
  - lib/advent/templates/solution.rb.tt
47
126
  - lib/advent/templates/solution_test.rb.tt
@@ -51,13 +130,7 @@ homepage: https://github.com/dnlgrv/advent-rb
51
130
  licenses:
52
131
  - MIT
53
132
  metadata: {}
54
- post_install_message: |2+
55
-
56
- advent v0.1.5 requires a config file in your working directory.
57
-
58
- See https://github.com/dnlgrv/advent-rb/blob/main/README.md#usage or if you're
59
- brave run `advent init` in your current directory.
60
-
133
+ post_install_message:
61
134
  rdoc_options: []
62
135
  require_paths:
63
136
  - lib
@@ -65,16 +138,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
138
  requirements:
66
139
  - - ">="
67
140
  - !ruby/object:Gem::Version
68
- version: 2.7.0
141
+ version: '0'
69
142
  required_rubygems_version: !ruby/object:Gem::Requirement
70
143
  requirements:
71
144
  - - ">="
72
145
  - !ruby/object:Gem::Version
73
146
  version: '0'
74
147
  requirements: []
75
- rubygems_version: 3.3.7
148
+ rubygems_version: 3.3.26
76
149
  signing_key:
77
150
  specification_version: 4
78
151
  summary: Have fun with the Advent of Code using Ruby.
79
152
  test_files: []
80
- ...
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Advent::CLI::Downloader
4
- def initialize(command, year, day)
5
- @command = command
6
- @year = year
7
- @day = day
8
- end
9
-
10
- def download
11
- ask_for_session_cookie_if_needed
12
- input = Advent::Input.new(Advent.root.join(@year), day: @day.to_i)
13
-
14
- if input.download(Advent.session.value, @command.options.http_module)
15
- @command.say "Input downloaded to #{input.file_path}.", :green
16
- @command.say "\nUsing #load_input in your daily solution will load the input file for you."
17
- else
18
- @command.say_error "Something went wrong, maybe an old session cookie?", :red
19
- end
20
- end
21
-
22
- private
23
-
24
- def ask_for_session_cookie_if_needed
25
- return if Advent.session.exist?
26
-
27
- session = @command.ask "What is your Advent of Code session cookie value?", echo: false
28
- Advent.session.value = session
29
-
30
- @command.say "\n\nThanks. Psst, we're going to save this for next time. It's in .advent_session if you need to update or delete it.\n\n"
31
- end
32
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Advent::CLI::Solver
4
- PARTS = [1, 2]
5
-
6
- if RUBY_VERSION >= "3.1"
7
- module Solutions
8
- end
9
- end
10
-
11
- def initialize(command, path)
12
- @command = command
13
- @path = path
14
- end
15
-
16
- def solve
17
- if RUBY_VERSION >= "3.1"
18
- load @path, Solutions
19
- solution = Solutions.const_get(solution_class_name).new
20
- else
21
- require @path.expand_path
22
- solution = Object.const_get(solution_class_name).new
23
- end
24
-
25
- PARTS.each do |n|
26
- method_name = "part#{n}".to_sym
27
-
28
- result, colour = if solution.respond_to?(method_name)
29
- [solution.public_send(method_name), :green]
30
- end
31
-
32
- result, colour = ["Missing", :red] if result.nil?
33
-
34
- @command.say "Part #{n}: #{result}", colour, true
35
- end
36
- end
37
-
38
- private
39
-
40
- def solution_class_name
41
- "Day#{day}"
42
- end
43
-
44
- def day
45
- @_day ||= @path.basename.to_s.match(/day([0-9]+)\.rb/)[1]
46
- end
47
- end
@@ -1,30 +0,0 @@
1
- require "psych"
2
-
3
- module Advent
4
- class Configuration
5
- DEFAULTS = {
6
- "download_when_generating" => true,
7
- "remember_session" => true
8
- }
9
- FILE_NAME = "advent.yml"
10
-
11
- attr_reader :download_when_generating, :remember_session
12
-
13
- class << self
14
- def from_file(file = FILE_NAME)
15
- if RUBY_VERSION >= "3.1"
16
- new Psych.safe_load_file(file)
17
- else
18
- new Psych.safe_load(File.read(file))
19
- end
20
- end
21
- end
22
-
23
- def initialize(conf)
24
- config = DEFAULTS.merge(conf || {})
25
-
26
- @download_when_generating = config.dig("download_when_generating")
27
- @remember_session = config.dig("remember_session")
28
- end
29
- end
30
- end
data/lib/advent/input.rb DELETED
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "cgi/cookie"
4
- require "fileutils"
5
- require "net/http"
6
- require "uri"
7
-
8
- module Advent
9
- class Input
10
- def initialize(dir, day:)
11
- @dir = dir
12
- @day = day
13
- end
14
-
15
- def file_path
16
- @dir.join(".day#{@day}.input.txt")
17
- end
18
-
19
- def exist?
20
- File.exist? file_path
21
- end
22
-
23
- def download(session, http = Net::HTTP)
24
- session_cookie = CGI::Cookie.new("session", session)
25
- response = http.get_response(input_url, {"Cookie" => session_cookie.to_s})
26
-
27
- if success?(response)
28
- FileUtils.mkdir_p file_path.dirname
29
- File.write file_path, response.body
30
- true
31
- else
32
- false
33
- end
34
- end
35
-
36
- private
37
-
38
- def input_url
39
- URI("https://adventofcode.com/#{year}/day/#{@day}/input")
40
- end
41
-
42
- def year
43
- @_year ||= @dir.basename
44
- end
45
-
46
- def success?(response)
47
- response.code >= "200" && response.code < "300"
48
- end
49
- end
50
- end
@@ -1,39 +0,0 @@
1
- module Advent
2
- # Simple class for handling the session cookie file
3
- class Session
4
- FILE_NAME = ".advent_session"
5
-
6
- attr_reader :file_name
7
-
8
- def initialize(file_name = FILE_NAME)
9
- @file_name = file_name
10
- end
11
-
12
- def clear
13
- File.delete file_name if exist?
14
- end
15
-
16
- def exist?
17
- File.exist? file_name
18
- end
19
-
20
- def value=(val)
21
- if save_to_disk?
22
- File.write file_name, val
23
- else
24
- @_value = val
25
- end
26
- end
27
-
28
- def value
29
- return @_value unless save_to_disk?
30
- return File.read(file_name) if exist?
31
- end
32
-
33
- private
34
-
35
- def save_to_disk?
36
- Advent.config.remember_session
37
- end
38
- end
39
- end