katagen 1.0.1
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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +64 -0
- data/Rakefile +10 -0
- data/bin/console +15 -0
- data/bin/katagen +7 -0
- data/bin/setup +8 -0
- data/lib/katagen/cli.rb +13 -0
- data/lib/katagen/command.rb +19 -0
- data/lib/katagen/data/leetcode.json +10837 -0
- data/lib/katagen/generators/logging.rb +38 -0
- data/lib/katagen/generators/solution.rb +71 -0
- data/lib/katagen/generators/utils.rb +37 -0
- data/lib/katagen/question_info.rb +12 -0
- data/lib/katagen/strategy/base.rb +11 -0
- data/lib/katagen/strategy/leetcode.rb +49 -0
- data/lib/katagen/templates/solution.rb.erb +9 -0
- data/lib/katagen/templates/solution_spec.rb.erb +27 -0
- data/lib/katagen/version.rb +5 -0
- data/lib/katagen.rb +4 -0
- data/sig/katagen.rbs +4 -0
- metadata +172 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Katagen
|
2
|
+
module Generators
|
3
|
+
# Colorization for puts, no need for another gem
|
4
|
+
# TODO: should I move this into a small gem?
|
5
|
+
module Logging
|
6
|
+
COLOR_CODES = {
|
7
|
+
red: 31,
|
8
|
+
green: 32,
|
9
|
+
yellow: 33,
|
10
|
+
blue: 34,
|
11
|
+
pink: 35,
|
12
|
+
light_blue: 36
|
13
|
+
}
|
14
|
+
|
15
|
+
def info(message)
|
16
|
+
puts "#{colorize("info", :blue)} #{message}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def success(message)
|
20
|
+
puts "#{colorize("success", :green)} #{message}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def warning(message)
|
24
|
+
puts "#{colorize("warning", :yellow)} #{message}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# :reek:UtilityFunction
|
30
|
+
|
31
|
+
# Colorize string with provided code. Defaults to none(0)
|
32
|
+
# NOTE: reek should not complain about this in a module IMO
|
33
|
+
def colorize(message, color)
|
34
|
+
"\e[#{COLOR_CODES[color] || 0}m#{message}\e[0m"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "erb"
|
5
|
+
require "time"
|
6
|
+
require_relative "utils"
|
7
|
+
|
8
|
+
module Katagen
|
9
|
+
module Generators
|
10
|
+
# Generates a solution package
|
11
|
+
class Solution
|
12
|
+
include Utils
|
13
|
+
#
|
14
|
+
# Initialize generator with chosen method.
|
15
|
+
#
|
16
|
+
# @param [#build_question_info] strategy: instance of FromId or FromUrl
|
17
|
+
# @param [Hash] options: see cli.rb
|
18
|
+
# @option options [String] cwd current working directory, defaults is "./"
|
19
|
+
# @option options [String] lang_ext solution file extension, defaults to "rb" (ruby)
|
20
|
+
def initialize(strategy, options)
|
21
|
+
@strategy = strategy
|
22
|
+
@lang_ext = options[:lang] || "rb"
|
23
|
+
@cwd = options[:cwd] || "./"
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Create the folder containing: solution.rb, solution_spec.rb (defaults to rb)
|
28
|
+
#
|
29
|
+
# @param [String] cwd: default to ./
|
30
|
+
#
|
31
|
+
def create_package
|
32
|
+
question_info = @strategy.build_question_info
|
33
|
+
root = File.expand_path(File.join(@cwd, question_info.root))
|
34
|
+
generate_folder(root)
|
35
|
+
create_solution(root, question_info.url)
|
36
|
+
create_solution_spec(root)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def create_solution(root, url)
|
42
|
+
solution_path = File.join(root, "solution.#{@lang_ext}")
|
43
|
+
template_path = File.join(File.dirname(__FILE__), "../templates/solution.#{@lang_ext}.erb")
|
44
|
+
|
45
|
+
@timestamp = Time.now.iso8601
|
46
|
+
@url = url
|
47
|
+
|
48
|
+
generate_file(solution_path, dup_when_exists: true) do |file|
|
49
|
+
write_template(file, template_path) if File.exist?(template_path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_solution_spec(root)
|
54
|
+
solution_spec_path = File.join(root, "solution_spec.#{@lang_ext}")
|
55
|
+
template_path = File.join(File.dirname(__FILE__), "../templates/solution_spec.#{@lang_ext}.erb")
|
56
|
+
|
57
|
+
generate_file(solution_spec_path) do |file|
|
58
|
+
write_template(file, template_path) if File.exist?(template_path)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def write_template(file, template_path)
|
65
|
+
template = File.read(template_path)
|
66
|
+
result = ERB.new(template).result(binding)
|
67
|
+
file.write(result)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require_relative "logging"
|
3
|
+
|
4
|
+
module Katagen
|
5
|
+
module Generators
|
6
|
+
# Common path utilities :reek:UtilityFunction
|
7
|
+
module Utils
|
8
|
+
include Generators::Logging
|
9
|
+
# Generate a file ifne with custom body
|
10
|
+
def generate_file(path, options = {}, &block)
|
11
|
+
if !File.exist?(path)
|
12
|
+
elsif options[:dup_when_exists]
|
13
|
+
_, folder, target_file, ext = path.match(/(.+)\/(.+)\.(.+)\Z/).to_a
|
14
|
+
count = Dir["#{folder}/*"].count { |file| file.match(/#{target_file}\d*\.#{ext}/) }
|
15
|
+
path = "#{folder}/#{target_file}#{count + 1}.#{ext}"
|
16
|
+
else
|
17
|
+
warning "File already exists: #{path}, skipping..."
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
21
|
+
block ||= ->(file) {} unless block_given?
|
22
|
+
File.open(path, "w", &block)
|
23
|
+
success "Created file #{path}"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Mkdir ifne
|
27
|
+
def generate_folder(dir_path)
|
28
|
+
if File.directory?(dir_path)
|
29
|
+
warning "Dir already exists: #{dir_path}, skipping..."
|
30
|
+
else
|
31
|
+
FileUtils.mkdir_p(dir_path)
|
32
|
+
success "Created dir #{dir_path}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative "../question_info"
|
2
|
+
|
3
|
+
module Katagen
|
4
|
+
module Strategy
|
5
|
+
# :reek:U
|
6
|
+
class InvalidIndex < StandardError
|
7
|
+
def initialize(input) = super("#{input} is not a valid index")
|
8
|
+
end
|
9
|
+
|
10
|
+
# :reek:U
|
11
|
+
class QuestionNotExist < StandardError
|
12
|
+
def initialize(input) = super("question #{input} does not exist")
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Generator for leetcode questions
|
17
|
+
#
|
18
|
+
class LeetCode
|
19
|
+
def initialize(id)
|
20
|
+
@id = id.to_i
|
21
|
+
raise InvalidIndex.new(@id) unless @id.positive?
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_question_info
|
25
|
+
summary = questions_summary.find { |q| q["id"] == @id }
|
26
|
+
raise QuestionNotExist.new(@id) unless summary
|
27
|
+
topic, difficulty = summary.values_at("topic", "difficulty")
|
28
|
+
|
29
|
+
QuestionInfo.new(
|
30
|
+
"#{difficulty}/#{@id}.#{topic}",
|
31
|
+
"https:/leetcode.com/problems/#{topic}"
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
#
|
38
|
+
# @return [Array<Hash{String=>String}>] array of question summary
|
39
|
+
#
|
40
|
+
def questions_summary
|
41
|
+
@summary ||= begin
|
42
|
+
path = File.join(File.dirname(__FILE__), "../data/leetcode.json")
|
43
|
+
raw_summary_text = File.read(path)
|
44
|
+
JSON.parse(raw_summary_text)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
FILE_NAME = ENV["TESTEE"] || "solution.rb"
|
2
|
+
require_relative FILE_NAME
|
3
|
+
|
4
|
+
TEST_CASES = [
|
5
|
+
{
|
6
|
+
input: [],
|
7
|
+
output: 0
|
8
|
+
},
|
9
|
+
{
|
10
|
+
input: [],
|
11
|
+
output: 0
|
12
|
+
}
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
RSpec.describe FILE_NAME do
|
16
|
+
context TRAIN_OF_THOUGHT do
|
17
|
+
TEST_CASES.each do |tc|
|
18
|
+
case tc
|
19
|
+
in { input: input, output: output}
|
20
|
+
pending "TODO: assert solution output with expected"
|
21
|
+
# it "#{input} => #{output}" do
|
22
|
+
# expect(___).to eq(output)
|
23
|
+
# end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/katagen.rb
ADDED
data/sig/katagen.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: katagen
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- harryuan65
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-12-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: erb
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.2.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: reek
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '6.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '6.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: standard
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.29'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.29'
|
111
|
+
description: Generate a folder for a question to put all practice records for better
|
112
|
+
reviewing
|
113
|
+
email:
|
114
|
+
- harryuan.65@gmail.com
|
115
|
+
executables:
|
116
|
+
- katagen
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files: []
|
119
|
+
files:
|
120
|
+
- ".rspec"
|
121
|
+
- ".rubocop.yml"
|
122
|
+
- CHANGELOG.md
|
123
|
+
- CODE_OF_CONDUCT.md
|
124
|
+
- Gemfile
|
125
|
+
- LICENSE.txt
|
126
|
+
- README.md
|
127
|
+
- Rakefile
|
128
|
+
- bin/console
|
129
|
+
- bin/katagen
|
130
|
+
- bin/setup
|
131
|
+
- lib/katagen.rb
|
132
|
+
- lib/katagen/cli.rb
|
133
|
+
- lib/katagen/command.rb
|
134
|
+
- lib/katagen/data/leetcode.json
|
135
|
+
- lib/katagen/generators/logging.rb
|
136
|
+
- lib/katagen/generators/solution.rb
|
137
|
+
- lib/katagen/generators/utils.rb
|
138
|
+
- lib/katagen/question_info.rb
|
139
|
+
- lib/katagen/strategy/base.rb
|
140
|
+
- lib/katagen/strategy/leetcode.rb
|
141
|
+
- lib/katagen/templates/solution.rb.erb
|
142
|
+
- lib/katagen/templates/solution_spec.rb.erb
|
143
|
+
- lib/katagen/version.rb
|
144
|
+
- sig/katagen.rbs
|
145
|
+
homepage: https://github.com/harryuan65/Katagen
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata:
|
149
|
+
allowed_push_host: https://rubygems.org
|
150
|
+
homepage_uri: https://github.com/harryuan65/Katagen
|
151
|
+
source_code_uri: https://github.com/harryuan65/Katagen
|
152
|
+
changelog_uri: https://github.com/harryuan65/Katagen/blob/master/CHANGELOG.md
|
153
|
+
post_install_message:
|
154
|
+
rdoc_options: []
|
155
|
+
require_paths:
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 2.6.0
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubygems_version: 3.2.32
|
169
|
+
signing_key:
|
170
|
+
specification_version: 4
|
171
|
+
summary: Generates a folder for leet code practice
|
172
|
+
test_files: []
|