advent 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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