aoc_generator 0.1.2 → 0.1.4

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: 938e976e4342e3115907290c0c0c90385ca25c67f80bde2befc904baeb510a56
4
- data.tar.gz: 2900af440cc153869f1f5575c8a162a53b60ff36b702b8628dcc22e8cdb3c814
3
+ metadata.gz: 4c2e50281fb4c3f191cbe11ca0417cb2ca969178f87a124572a5b34e07e01b17
4
+ data.tar.gz: b00f142cd08f4ca55e651974c7d923f2c62515a49a4f07c4d3443f5584f24e4d
5
5
  SHA512:
6
- metadata.gz: 11471565e51be4d99ad7e11cd4e1aa2bb43546301aa485c1fbd64d4b5ce9fc78c02b85128e0f6c608caddae2dbeb63ca59d676b5712e1c91d3de72b933d52360
7
- data.tar.gz: 66b8d3dc1df84f44f5600aa3ec497f75b4245c955e54f287431e200d1e34eec3cf2efe3a7ec16f7363be522ae140f18b2060b276882b043d39f9f7dd3e44f6e2
6
+ metadata.gz: ce6d572095bf2acc47c429e5ece1fee0c335ed0403c94c47f33063a996193d0848deacf49a981fa18546b418d05c2425a553317f1677c5fb714d3de9163caf18
7
+ data.tar.gz: 93ccfd82a61cb9ea1eb8b096cfa1c0a922a002abb923c93f06c25796a5af6d4356be28e06a88d9b62d4e489f04328e15d37569c24a7480cec366c57560bdd0ab
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Changelog
2
2
 
3
- ## [0.1.2] - 2024-11-28
3
+ ## [0.1.4] - 2024-11-28
4
+
5
+ - Add test data to spec file
6
+
7
+ ## [0.1.3]
8
+
9
+ - Allow to read a AOC_SESSION environment variable
10
+ - Change file names
11
+ - Convert HTML to Markdown
12
+
13
+ ## [0.1.2]
4
14
 
5
15
  - [Fix] Add the correct FileUtils gem
6
16
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- aoc_generator (0.1.2)
4
+ aoc_generator (0.1.4)
5
5
  fileutils (~> 1.7)
6
6
  nokogiri (~> 1.16)
7
7
  thor (~> 1.3)
data/README.md CHANGED
@@ -16,12 +16,11 @@ A Ruby gem that generates daily puzzle templates for Advent of Code.
16
16
 
17
17
  ```sh
18
18
  -y, [--year=N] # Defaults to the current year.
19
- # Default: 2024
20
19
  -d, [--day=N] # Defaults to the current day.
21
- # Default: 28
22
20
  -u, [--username=USERNAME] # Files will be generated in a directory with this name. Useful for multi-user repos.
23
21
  # Default: advent_of_code
24
22
  -s, [--session=SESSION] # Your adventofcode.com session key. Necessary for scraping data files and specs for part two.
23
+ # Default: reads AOC_SESSION environment variable if it exists.
25
24
  ```
26
25
 
27
26
  ## Generated file structure
@@ -32,8 +31,8 @@ adventofcode/
32
31
  └── year_2024/
33
32
  |
34
33
  └── day_01/
35
- ├── main.rb
36
- ├── spec.rb
34
+ ├── day_01.rb
35
+ ├── day_01_spec.rb
37
36
  ├── data.txt
38
37
  └── README.md
39
38
  ```
@@ -32,11 +32,13 @@ module AdventOfCodeGenerator
32
32
  method_option :session,
33
33
  required: false,
34
34
  aliases: "-s",
35
- desc: "Your adventofcode.com session key. Necessary for scraping data files and specs for part two."
35
+ desc: "Your adventofcode.com session key. " \
36
+ "Necessary for scraping data files and specs for part two. " \
37
+ "Defaults to a AOC_SESSION environment variable if it exists.",
38
+ default: ENV.fetch("AOC_SESSION", nil)
36
39
 
37
40
  def generate
38
- scraper = AdventOfCodeGenerator::Scraper.new(options)
39
- generator = AdventOfCodeGenerator::Generator.new(options, scraper)
41
+ generator = AdventOfCodeGenerator::Generator.new(options, content)
40
42
 
41
43
  generator.call
42
44
  end
@@ -44,5 +46,14 @@ module AdventOfCodeGenerator
44
46
  def self.exit_on_failure?
45
47
  true
46
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
47
58
  end
48
59
  end
@@ -12,19 +12,19 @@ module AdventOfCodeGenerator
12
12
  # └── year_2024/
13
13
  # |
14
14
  # └── day_01/
15
- # ├── main.rb
16
- # ├── spec.rb
15
+ # ├── day_01.rb
16
+ # ├── day_01_spec.rb
17
17
  # ├── data.txt
18
18
  # └── README.md
19
19
  #
20
20
  class Generator
21
21
  FileData = Struct.new(:path, :content)
22
22
 
23
- def initialize(options, scraper)
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
- @scraper = scraper
27
+ @scraped_data = scraped_data
28
28
  end
29
29
 
30
30
  def call
@@ -45,20 +45,20 @@ module AdventOfCodeGenerator
45
45
 
46
46
  def readme
47
47
  path = "#{daily_directory}/README.md"
48
- content = @scraper.puzzle_description
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 = @scraper.input_data
55
+ content = @scraped_data[:input_data]
56
56
 
57
57
  FileData.new(path, content)
58
58
  end
59
59
 
60
60
  def main_file
61
- path = "#{daily_directory}/main.rb"
61
+ path = "#{daily_directory}/day_#{@day}.rb"
62
62
  content = <<~RUBY
63
63
  # frozen_string_literal: true
64
64
 
@@ -85,23 +85,29 @@ module AdventOfCodeGenerator
85
85
  end
86
86
 
87
87
  def spec_file
88
- path = "#{daily_directory}/spec.rb"
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
- require_relative "main"
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
- expect(puzzle.part_one).to eq("")
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
- xit "solves Part Two" do
104
- expect(puzzle.part_two).to eq("some other value")
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
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+
5
+ module AdventOfCodeGenerator
6
+ # Converts HTML puzzle descriptions from adventofcode.com into markdown format.
7
+ class HTMLParser
8
+ def initialize(html_content)
9
+ @html_content = html_content
10
+ end
11
+
12
+ def call
13
+ {
14
+ puzzle_description: part_descriptions.join("\n"),
15
+ test_input:,
16
+ test_expectations:
17
+ }
18
+ end
19
+
20
+ private
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
+
41
+ def articles
42
+ doc = Nokogiri::HTML(@html_content)
43
+ doc.css("article")
44
+ end
45
+
46
+ def process_article(article)
47
+ article.children.map { |node| process_node(node) }.compact
48
+ end
49
+
50
+ def process_node(node)
51
+ case node.name
52
+ when "h2"
53
+ "## #{node.text}\n"
54
+ when "p"
55
+ "#{process_paragraph(node)}\n"
56
+ when "pre"
57
+ "```sh\n#{node.text.strip}\n```\n"
58
+ end
59
+ end
60
+
61
+ def process_paragraph(para)
62
+ para.inner_html
63
+ .gsub(%r{<a[^>]*href="([^"]*)"[^>]*>(.*?)</a>}, '[\2](\1)')
64
+ .gsub(%r{<code><em>(.*?)</em></code>}, '**`\1`**')
65
+ .gsub(%r{<em><code>(.*?)</code></em>}, '**`\1`**')
66
+ .gsub(%r{<em.*?>(.*?)</em>}, '**\1**')
67
+ .gsub(%r{<code>(.*?)</code>}, '`\1`')
68
+ .gsub(/<[^>]*>/, "")
69
+ end
70
+ end
71
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "net/http"
4
+ require_relative "html_parser"
4
5
 
5
6
  module AdventOfCodeGenerator
6
7
  # Fetches puzzle descriptions and input data from adventofcode.com.
@@ -11,6 +12,21 @@ module AdventOfCodeGenerator
11
12
  @session_key = options[:session]
12
13
  end
13
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}" }
28
+ end
29
+
14
30
  def puzzle_description
15
31
  warn "You'll need to provide a session key to scrape Part Two." unless @session_key
16
32
 
@@ -21,20 +37,12 @@ module AdventOfCodeGenerator
21
37
  end
22
38
 
23
39
  def input_data
24
- return @input_data if @input_data
25
40
  return warn "No session key provided; unable to download data file." unless @session_key
26
41
 
27
42
  uri = URI("https://adventofcode.com/#{@year}/day/#{@day}/input")
28
43
  response = Net::HTTP.get_response(uri, headers)
29
- @input_data ||= response.body
30
- end
31
44
 
32
- private
33
-
34
- def headers
35
- return {} unless @session_key
36
-
37
- @headers ||= { cookie: "session=#{@session_key}" }
45
+ response.body
38
46
  end
39
47
  end
40
48
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AdventOfCodeGenerator
4
- VERSION = "0.1.2"
4
+ VERSION = "0.1.4"
5
5
 
6
6
  class Error < StandardError; end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aoc_generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-27 00:00:00.000000000 Z
11
+ date: 2024-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fileutils
@@ -74,6 +74,7 @@ files:
74
74
  - lib/advent_of_code_generator.rb
75
75
  - lib/advent_of_code_generator/cli.rb
76
76
  - lib/advent_of_code_generator/generator.rb
77
+ - lib/advent_of_code_generator/html_parser.rb
77
78
  - lib/advent_of_code_generator/scraper.rb
78
79
  homepage: https://github.com/cheddachedda/advent_of_code_generator
79
80
  licenses: []