at_coder_friends 0.6.2 → 0.6.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -2
  3. data/.travis.yml +2 -2
  4. data/CHANGELOG.md +53 -0
  5. data/Gemfile.lock +32 -36
  6. data/README.md +1 -1
  7. data/at_coder_friends.gemspec +5 -7
  8. data/config/default.yml +146 -72
  9. data/docs/CONFIGURATION.md +224 -140
  10. data/lib/at_coder_friends.rb +3 -0
  11. data/lib/at_coder_friends/cli.rb +8 -0
  12. data/lib/at_coder_friends/config_loader.rb +11 -3
  13. data/lib/at_coder_friends/context.rb +10 -6
  14. data/lib/at_coder_friends/emitter.rb +2 -2
  15. data/lib/at_coder_friends/generator/base.rb +42 -0
  16. data/lib/at_coder_friends/generator/cxx_builtin.rb +196 -143
  17. data/lib/at_coder_friends/generator/main.rb +8 -2
  18. data/lib/at_coder_friends/generator/ruby_builtin.rb +97 -51
  19. data/lib/at_coder_friends/parser/constraints.rb +1 -0
  20. data/lib/at_coder_friends/parser/input_format.rb +389 -188
  21. data/lib/at_coder_friends/parser/input_type.rb +92 -0
  22. data/lib/at_coder_friends/parser/main.rb +1 -0
  23. data/lib/at_coder_friends/parser/modulo.rb +1 -1
  24. data/lib/at_coder_friends/parser/sections.rb +3 -3
  25. data/lib/at_coder_friends/path_info.rb +51 -0
  26. data/lib/at_coder_friends/path_util.rb +0 -31
  27. data/lib/at_coder_friends/problem.rb +81 -6
  28. data/lib/at_coder_friends/scraping/agent.rb +11 -2
  29. data/lib/at_coder_friends/scraping/custom_test.rb +5 -6
  30. data/lib/at_coder_friends/scraping/submission.rb +6 -7
  31. data/lib/at_coder_friends/scraping/tasks.rb +8 -3
  32. data/lib/at_coder_friends/test_runner/base.rb +17 -4
  33. data/lib/at_coder_friends/test_runner/judge.rb +7 -9
  34. data/lib/at_coder_friends/test_runner/sample.rb +2 -4
  35. data/lib/at_coder_friends/verifier.rb +2 -3
  36. data/lib/at_coder_friends/version.rb +1 -1
  37. data/templates/{cxx_builtin_interactive.cxx → cxx_builtin.cxx.erb} +26 -4
  38. data/templates/{ruby_builtin_interactive.rb → ruby_builtin.rb.erb} +17 -3
  39. metadata +11 -17
  40. data/tasks/regression/check_const.rake +0 -136
  41. data/tasks/regression/check_diff.rake +0 -30
  42. data/tasks/regression/check_fmt.rake +0 -42
  43. data/tasks/regression/check_parse.rake +0 -70
  44. data/tasks/regression/regression.rb +0 -72
  45. data/tasks/regression/section_list.rake +0 -53
  46. data/tasks/regression/setup.rake +0 -48
  47. data/templates/cxx_builtin_default.cxx +0 -26
  48. data/templates/ruby_builtin_default.rb +0 -7
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'regression'
4
-
5
- module AtCoderFriends
6
- # tasks for regression
7
- module Regression
8
- module_function
9
-
10
- def check_diff
11
- emit_dir = format(EMIT_DIR_FMT, now: Time.now.strftime('%Y%m%d%H%M%S'))
12
- rmdir_force(emit_dir)
13
-
14
- local_pbm_list.each do |contest, q, url|
15
- pbm = scraping_agent(emit_dir, contest).fetch_problem(q, url)
16
- pipeline(pbm)
17
- end
18
-
19
- diff_log = log_path('check_diff.txt')
20
- system("diff -r --exclude=.git #{EMIT_ORG_DIR} #{emit_dir} > #{diff_log}")
21
- end
22
- end
23
- end
24
-
25
- namespace :regression do
26
- desc 'run regression check'
27
- task :check_diff do
28
- AtCoderFriends::Regression.check_diff
29
- end
30
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'regression'
4
-
5
- module AtCoderFriends
6
- # tasks for regression
7
- module Regression
8
- module_function
9
-
10
- def check_fmt
11
- File.open(log_path('check_fmt.txt'), 'w') do |f|
12
- local_pbm_list.sort.each do |contest, q, url|
13
- pbm = scraping_agent(nil, contest).fetch_problem(q, url)
14
- Parser::Sections.process(pbm)
15
- fmt = Parser::InputFormat.find_fmt(pbm)
16
- next unless fmt && !fmt.empty?
17
-
18
- n_fmt = Parser::InputFormat.normalize_fmt(fmt).join("\n")
19
- Parser::InputFormat.process(pbm)
20
- res = pbm.formats.map(&:to_s).join("\n")
21
- f.puts [
22
- contest, q,
23
- tsv_escape(fmt),
24
- tsv_escape(n_fmt),
25
- tsv_escape(res)
26
- ].join("\t")
27
- end
28
- end
29
- end
30
-
31
- def tsv_escape(str)
32
- '"' + str.gsub('"', '""').gsub("\t", ' ') + '"'
33
- end
34
- end
35
- end
36
-
37
- namespace :regression do
38
- desc 'checks input format patterns'
39
- task :check_fmt do
40
- AtCoderFriends::Regression.check_fmt
41
- end
42
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'regression'
4
- require 'at_coder_friends'
5
-
6
- module AtCoderFriends
7
- # tasks for regression
8
- module Regression
9
- module_function
10
-
11
- def check_parse
12
- list = local_pbm_list.map do |contest, q, url|
13
- pbm = scraping_agent(nil, contest).fetch_problem(q, url)
14
- Parser::Main.process(pbm)
15
- flags = [
16
- !fmt?(pbm),
17
- pbm.samples.all? { |smp| smp.txt.empty? },
18
- pbm.options.interactive
19
- ]
20
- [contest, q, flags]
21
- end
22
- report(list, 'check_parse.txt')
23
- end
24
-
25
- def check_bin
26
- list = local_pbm_list.map do |contest, q, url|
27
- pbm = scraping_agent(nil, contest).fetch_problem(q, url)
28
- Parser::Main.process(pbm)
29
- flags = [pbm.options.binary_values]
30
- [contest, q, flags]
31
- end
32
- report(list, 'check_bin.txt')
33
- end
34
-
35
- def fmt?(pbm)
36
- fmt = Parser::InputFormat.find_fmt(pbm)
37
- fmt && !fmt.empty?
38
- end
39
-
40
- def report(list, file)
41
- File.open(log_path(file), 'w') do |f|
42
- list
43
- .select { |_, _, flags| flags.any? }
44
- .map { |c, q, flags| [c, q, flags.map { |flg| f_to_s(flg) }] }
45
- .sort
46
- .each { |args| f.puts args.flatten.join("\t") }
47
- end
48
- end
49
-
50
- def f_to_s(f)
51
- if f.is_a?(Array)
52
- f
53
- else
54
- f ? '◯' : '-'
55
- end
56
- end
57
- end
58
- end
59
-
60
- namespace :regression do
61
- desc 'checks page parse result'
62
- task :check_parse do
63
- AtCoderFriends::Regression.check_parse
64
- end
65
-
66
- desc 'checks binary problem parse result'
67
- task :check_bin do
68
- AtCoderFriends::Regression.check_bin
69
- end
70
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'net/http'
4
- require 'uri'
5
- require 'json'
6
- require 'csv'
7
- require 'mechanize'
8
- require 'at_coder_friends'
9
-
10
- module AtCoderFriends
11
- # tasks for regression
12
- module Regression
13
- module_function
14
-
15
- CONTEST_LIST_URL = 'https://kenkoooo.com/atcoder/resources/contests.json'
16
- ACF_HOME = File.expand_path(File.join(__dir__, '..', '..'))
17
- REGRESSION_HOME = File.join(ACF_HOME, 'regression')
18
- PAGES_DIR = File.join(REGRESSION_HOME, 'pages')
19
- EMIT_ORG_DIR = File.join(REGRESSION_HOME, 'emit_org')
20
- EMIT_DIR_FMT = File.join(REGRESSION_HOME, 'emit_%<now>s')
21
-
22
- def contest_id_list
23
- uri = URI.parse(CONTEST_LIST_URL)
24
- json = Net::HTTP.get(uri)
25
- contests = JSON.parse(json)
26
- puts "Total #{contests.size} contests"
27
- contests.map { |h| h['id'] }
28
- end
29
-
30
- def local_pbm_list
31
- Dir.glob(PAGES_DIR + '/**/*.html').map do |pbm_path|
32
- contest = File.basename(File.dirname(pbm_path))
33
- q = File.basename(pbm_path, '.html')
34
- url = "file://#{pbm_path}"
35
- [contest, q, url]
36
- end
37
- end
38
-
39
- def pbm_list_from_file(file)
40
- dat = File.join(REGRESSION_HOME, file)
41
- CSV.read(dat, col_sep: "\t", headers: false).map do |contest, q|
42
- pbm_path = File.join(PAGES_DIR, contest, "#{q}.html")
43
- url = "file://#{pbm_path}"
44
- [contest, q, url]
45
- end
46
- end
47
-
48
- def scraping_agent(root, contest)
49
- root ||= REGRESSION_HOME
50
- @ctx = Context.new({}, File.join(root, contest))
51
- @ctx.scraping_agent
52
- end
53
-
54
- def agent
55
- @agent ||= Mechanize.new
56
- end
57
-
58
- def pipeline(pbm)
59
- Parser::Main.process(pbm)
60
- @ctx.generator.process(pbm)
61
- @ctx.emitter.emit(pbm)
62
- end
63
-
64
- def rmdir_force(dir)
65
- FileUtils.rm_r(dir) if Dir.exist?(dir)
66
- end
67
-
68
- def log_path(file)
69
- File.join(REGRESSION_HOME, file)
70
- end
71
- end
72
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'regression'
4
-
5
- module AtCoderFriends
6
- # tasks for regression
7
- module Regression
8
- module_function
9
-
10
- SectionInfo = Struct.new(:contest, :q, :title)
11
-
12
- def section_list
13
- list = load_section_list
14
- save_section_list(list)
15
- end
16
-
17
- def load_section_list
18
- local_pbm_list.flat_map do |contest, q, url|
19
- page = agent.get(url)
20
- %w[h2 h3].flat_map do |tag|
21
- page.search(tag).map do |h|
22
- SectionInfo.new(contest, q, normalize(h.content))
23
- end
24
- end
25
- end
26
- end
27
-
28
- def save_section_list(list)
29
- File.open(log_path('section_list.txt'), 'w') do |f|
30
- list.group_by(&:title).each do |k, vs|
31
- f.puts [k, vs.size, vs[0].contest, vs[0].q].join("\t")
32
- end
33
- end
34
- end
35
-
36
- def normalize(s)
37
- s
38
- .tr('0-9A-Za-z', '0-9A-Za-z')
39
- .gsub(/[[:space:]]/, '')
40
- .gsub(/[^一-龠_ぁ-ん_ァ-ヶーa-zA-Z0-9 ]/, '')
41
- .downcase
42
- .gsub(/\d+/, '{N}')
43
- .strip
44
- end
45
- end
46
- end
47
-
48
- namespace :regression do
49
- desc 'list all section titles'
50
- task :section_list do
51
- AtCoderFriends::Regression.section_list
52
- end
53
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'regression'
4
-
5
- module AtCoderFriends
6
- # tasks for regression
7
- module Regression
8
- module_function
9
-
10
- def setup
11
- rmdir_force(PAGES_DIR)
12
- rmdir_force(EMIT_ORG_DIR)
13
- contest_id_list.each do |contest|
14
- setup_by_contest(contest)
15
- sleep 3
16
- end
17
- end
18
-
19
- def setup_by_contest(contest)
20
- scraping_agent(EMIT_ORG_DIR, contest).fetch_all do |pbm|
21
- setup_by_pbm(contest, pbm)
22
- end
23
- rescue StandardError => e
24
- p e
25
- end
26
-
27
- def setup_by_pbm(contest, pbm)
28
- html_path = File.join(PAGES_DIR, contest, "#{pbm.q}.html")
29
- save_file(html_path, pbm.page.body)
30
- pipeline(pbm)
31
- rescue StandardError => e
32
- p e
33
- end
34
-
35
- def save_file(path, content)
36
- dir = File.dirname(path)
37
- FileUtils.makedirs(dir) unless Dir.exist?(dir)
38
- File.binwrite(path, content)
39
- end
40
- end
41
- end
42
-
43
- namespace :regression do
44
- desc 'setup regression environment'
45
- task :setup do
46
- AtCoderFriends::Regression.setup
47
- end
48
- end
@@ -1,26 +0,0 @@
1
- // /*** URL ***/
2
-
3
- #include <cstdio>
4
-
5
- using namespace std;
6
-
7
- #define REP(i,n) for(int i=0; i<(int)(n); i++)
8
- #define FOR(i,b,e) for(int i=(b); i<=(int)(e); i++)
9
-
10
- /*** CONSTS ***/
11
-
12
- /*** DCLS ***/
13
-
14
- void solve() {
15
- /*** OUTPUT ***/
16
- }
17
-
18
- void input() {
19
- /*** INPUTS ***/
20
- }
21
-
22
- int main() {
23
- input();
24
- solve();
25
- return 0;
26
- }
@@ -1,7 +0,0 @@
1
- # ### URL ###
2
-
3
- ### CONSTS ###
4
-
5
- ### DCLS ###
6
-
7
- ### OUTPUT ###