aoc_generator 0.1.3 → 0.1.4
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/CHANGELOG.md +5 -1
- data/Gemfile.lock +1 -1
- data/lib/advent_of_code_generator/cli.rb +10 -2
- data/lib/advent_of_code_generator/generator.rb +17 -11
- data/lib/advent_of_code_generator/html_parser.rb +27 -6
- data/lib/advent_of_code_generator/scraper.rb +18 -12
- data/lib/advent_of_code_generator.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c2e50281fb4c3f191cbe11ca0417cb2ca969178f87a124572a5b34e07e01b17
|
4
|
+
data.tar.gz: b00f142cd08f4ca55e651974c7d923f2c62515a49a4f07c4d3443f5584f24e4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce6d572095bf2acc47c429e5ece1fee0c335ed0403c94c47f33063a996193d0848deacf49a981fa18546b418d05c2425a553317f1677c5fb714d3de9163caf18
|
7
|
+
data.tar.gz: 93ccfd82a61cb9ea1eb8b096cfa1c0a922a002abb923c93f06c25796a5af6d4356be28e06a88d9b62d4e489f04328e15d37569c24a7480cec366c57560bdd0ab
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -38,8 +38,7 @@ module AdventOfCodeGenerator
|
|
38
38
|
default: ENV.fetch("AOC_SESSION", nil)
|
39
39
|
|
40
40
|
def generate
|
41
|
-
|
42
|
-
generator = AdventOfCodeGenerator::Generator.new(options, scraper)
|
41
|
+
generator = AdventOfCodeGenerator::Generator.new(options, content)
|
43
42
|
|
44
43
|
generator.call
|
45
44
|
end
|
@@ -47,5 +46,14 @@ module AdventOfCodeGenerator
|
|
47
46
|
def self.exit_on_failure?
|
48
47
|
true
|
49
48
|
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def content
|
53
|
+
scraped_data = AdventOfCodeGenerator::Scraper.new(options).call
|
54
|
+
parsed_data = AdventOfCodeGenerator::HTMLParser.new(scraped_data[:puzzle_description]).call
|
55
|
+
|
56
|
+
scraped_data.merge(parsed_data)
|
57
|
+
end
|
50
58
|
end
|
51
59
|
end
|
@@ -20,11 +20,11 @@ module AdventOfCodeGenerator
|
|
20
20
|
class Generator
|
21
21
|
FileData = Struct.new(:path, :content)
|
22
22
|
|
23
|
-
def initialize(options,
|
23
|
+
def initialize(options, scraped_data)
|
24
24
|
@year = options[:year].to_s
|
25
25
|
@day = options[:day].to_s.rjust(2, "0") # Ensures day is two digits (e.g., "01" instead of "1")
|
26
26
|
@username = options[:username].gsub(/[_\-\.\s]/, "")
|
27
|
-
@
|
27
|
+
@scraped_data = scraped_data
|
28
28
|
end
|
29
29
|
|
30
30
|
def call
|
@@ -45,14 +45,14 @@ module AdventOfCodeGenerator
|
|
45
45
|
|
46
46
|
def readme
|
47
47
|
path = "#{daily_directory}/README.md"
|
48
|
-
content = @
|
48
|
+
content = @scraped_data[:puzzle_description]
|
49
49
|
|
50
50
|
FileData.new(path, content)
|
51
51
|
end
|
52
52
|
|
53
53
|
def data_file
|
54
54
|
path = "#{daily_directory}/data.txt"
|
55
|
-
content = @
|
55
|
+
content = @scraped_data[:input_data]
|
56
56
|
|
57
57
|
FileData.new(path, content)
|
58
58
|
end
|
@@ -86,22 +86,28 @@ module AdventOfCodeGenerator
|
|
86
86
|
|
87
87
|
def spec_file
|
88
88
|
path = "#{daily_directory}/day_#{@day}_spec.rb"
|
89
|
+
input, expectations = @scraped_data.values_at(:test_input, :test_expectations)
|
90
|
+
input ||= ["", ""]
|
89
91
|
content = <<~RUBY
|
90
92
|
# frozen_string_literal: true
|
91
93
|
|
92
94
|
require_relative "day_#{@day}"
|
93
95
|
|
94
96
|
RSpec.describe #{@username.capitalize}::Year#{@year}::Day#{@day} do
|
95
|
-
subject(:puzzle) { described_class.new(input) }
|
96
|
-
|
97
|
-
let(:input) { File.read("\#{__dir__}/data.txt") }
|
98
|
-
|
99
97
|
it "solves Part One" do
|
100
|
-
|
98
|
+
input = <<~INPUT
|
99
|
+
#{input[0]&.gsub("\n", "\n ")}
|
100
|
+
INPUT
|
101
|
+
|
102
|
+
expect(described_class.part_one(input)).to eq(#{expectations[0]})
|
101
103
|
end
|
102
104
|
|
103
|
-
|
104
|
-
|
105
|
+
it "solves Part Two", skip: "not implemented yet" do
|
106
|
+
input = <<~INPUT
|
107
|
+
#{input[1]&.gsub("\n", "\n ")}
|
108
|
+
INPUT
|
109
|
+
|
110
|
+
expect(described_class.part_two(input)).to eq(#{expectations[1]})
|
105
111
|
end
|
106
112
|
end
|
107
113
|
RUBY
|
@@ -5,20 +5,41 @@ require "nokogiri"
|
|
5
5
|
module AdventOfCodeGenerator
|
6
6
|
# Converts HTML puzzle descriptions from adventofcode.com into markdown format.
|
7
7
|
class HTMLParser
|
8
|
-
def initialize(
|
9
|
-
@
|
8
|
+
def initialize(html_content)
|
9
|
+
@html_content = html_content
|
10
10
|
end
|
11
11
|
|
12
12
|
def call
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
{
|
14
|
+
puzzle_description: part_descriptions.join("\n"),
|
15
|
+
test_input:,
|
16
|
+
test_expectations:
|
17
|
+
}
|
16
18
|
end
|
17
19
|
|
18
20
|
private
|
19
21
|
|
22
|
+
def part_descriptions
|
23
|
+
@part_descriptions ||= articles.map do |node|
|
24
|
+
process_article(node).join("\n")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_input
|
29
|
+
part_descriptions.map { |desc| desc.scan(/```sh\n(.*?)\n```/m) }.flatten
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_expectations
|
33
|
+
part_descriptions
|
34
|
+
.flat_map { |desc| desc.scan(/\*\*`(.*?)`\*\*/) }
|
35
|
+
.map do |matches|
|
36
|
+
match = matches.first
|
37
|
+
match&.match?(/\A\d+\z/) ? match.to_i : match
|
38
|
+
end.compact
|
39
|
+
end
|
40
|
+
|
20
41
|
def articles
|
21
|
-
doc = Nokogiri::HTML(@
|
42
|
+
doc = Nokogiri::HTML(@html_content)
|
22
43
|
doc.css("article")
|
23
44
|
end
|
24
45
|
|
@@ -6,11 +6,25 @@ require_relative "html_parser"
|
|
6
6
|
module AdventOfCodeGenerator
|
7
7
|
# Fetches puzzle descriptions and input data from adventofcode.com.
|
8
8
|
class Scraper
|
9
|
-
def initialize(options
|
9
|
+
def initialize(options)
|
10
10
|
@year = options[:year]
|
11
11
|
@day = options[:day]
|
12
12
|
@session_key = options[:session]
|
13
|
-
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
{
|
17
|
+
puzzle_description:,
|
18
|
+
input_data:
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def headers
|
25
|
+
return {} unless @session_key
|
26
|
+
|
27
|
+
@headers ||= { cookie: "session=#{@session_key}" }
|
14
28
|
end
|
15
29
|
|
16
30
|
def puzzle_description
|
@@ -19,24 +33,16 @@ module AdventOfCodeGenerator
|
|
19
33
|
uri = URI("https://adventofcode.com/#{@year}/day/#{@day}")
|
20
34
|
response = Net::HTTP.get_response(uri, headers)
|
21
35
|
|
22
|
-
|
36
|
+
response.body
|
23
37
|
end
|
24
38
|
|
25
39
|
def input_data
|
26
|
-
return @input_data if @input_data
|
27
40
|
return warn "No session key provided; unable to download data file." unless @session_key
|
28
41
|
|
29
42
|
uri = URI("https://adventofcode.com/#{@year}/day/#{@day}/input")
|
30
43
|
response = Net::HTTP.get_response(uri, headers)
|
31
|
-
@input_data ||= response.body
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
44
|
|
36
|
-
|
37
|
-
return {} unless @session_key
|
38
|
-
|
39
|
-
@headers ||= { cookie: "session=#{@session_key}" }
|
45
|
+
response.body
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|