at_coder_friends 0.6.3 → 0.6.8

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 (44) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +3 -2
  3. data/.travis.yml +1 -3
  4. data/CHANGELOG.md +37 -0
  5. data/Gemfile.lock +53 -48
  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 +222 -136
  10. data/lib/at_coder_friends.rb +1 -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 +3 -2
  16. data/lib/at_coder_friends/generator/main.rb +2 -1
  17. data/lib/at_coder_friends/parser/constraints.rb +1 -0
  18. data/lib/at_coder_friends/parser/input_format.rb +2 -0
  19. data/lib/at_coder_friends/parser/input_type.rb +3 -2
  20. data/lib/at_coder_friends/parser/modulo.rb +1 -1
  21. data/lib/at_coder_friends/parser/sections.rb +3 -3
  22. data/lib/at_coder_friends/path_info.rb +51 -0
  23. data/lib/at_coder_friends/path_util.rb +0 -31
  24. data/lib/at_coder_friends/scraping/agent.rb +11 -2
  25. data/lib/at_coder_friends/scraping/custom_test.rb +5 -6
  26. data/lib/at_coder_friends/scraping/submission.rb +6 -7
  27. data/lib/at_coder_friends/scraping/tasks.rb +8 -3
  28. data/lib/at_coder_friends/test_runner/base.rb +17 -4
  29. data/lib/at_coder_friends/test_runner/judge.rb +7 -9
  30. data/lib/at_coder_friends/test_runner/sample.rb +2 -4
  31. data/lib/at_coder_friends/verifier.rb +2 -3
  32. data/lib/at_coder_friends/version.rb +1 -1
  33. data/templates/cxx_builtin.cxx.erb +26 -35
  34. data/templates/ruby_builtin.rb.erb +17 -18
  35. metadata +7 -16
  36. data/tasks/regression/check_const.rake +0 -137
  37. data/tasks/regression/check_diff.rake +0 -30
  38. data/tasks/regression/check_fmt.rake +0 -45
  39. data/tasks/regression/check_parse.rake +0 -69
  40. data/tasks/regression/list_handler.rb +0 -46
  41. data/tasks/regression/regression.rb +0 -38
  42. data/tasks/regression/report_handler.rb +0 -20
  43. data/tasks/regression/section_list.rake +0 -53
  44. data/tasks/regression/setup.rake +0 -48
@@ -1,45 +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
- open_report('check_fmt.txt') do |f|
12
- local_pbm_list.each do |contest, q, url|
13
- next unless (res = process_fmt(contest, q, url))
14
-
15
- f.puts [
16
- contest, q, *res.map { |s| tsv_escape(s) }
17
- ].join("\t")
18
- end
19
- end
20
- end
21
-
22
- def process_fmt(contest, q, url)
23
- pbm = local_scraping_agent(nil, contest).fetch_problem(q, url)
24
- Parser::Sections.process(pbm)
25
- Parser::SampleData.process(pbm)
26
- fmt1 = Parser::InputFormat.find_fmt(pbm)
27
- return unless fmt1 && !fmt1.empty?
28
-
29
- fmt2 = Parser::InputFormat.normalize_fmt(fmt1).join("\n")
30
- Parser::InputFormat.process(pbm)
31
- Parser::InputType.process(pbm)
32
- inpdefs = pbm.formats_src
33
- fmt3 = inpdefs.map(&:to_s).join("\n")
34
- fmt4 = inpdefs.any? { |inpdef| inpdef.cols.empty? } ? '○' : ''
35
- [fmt1, fmt2, fmt3, fmt4]
36
- end
37
- end
38
- end
39
-
40
- namespace :regression do
41
- desc 'checks input format patterns'
42
- task :check_fmt do
43
- AtCoderFriends::Regression.check_fmt
44
- end
45
- end
@@ -1,69 +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 = local_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 = local_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
- open_report(file) do |f|
42
- list
43
- .select { |_, _, flags| flags.any? }
44
- .map { |c, q, flags| [c, q, flags.map { |flg| f_to_s(flg) }] }
45
- .each { |args| f.puts args.flatten.join("\t") }
46
- end
47
- end
48
-
49
- def f_to_s(f)
50
- if f.is_a?(Array)
51
- f
52
- else
53
- f ? '◯' : '-'
54
- end
55
- end
56
- end
57
- end
58
-
59
- namespace :regression do
60
- desc 'checks page parse result'
61
- task :check_parse do
62
- AtCoderFriends::Regression.check_parse
63
- end
64
-
65
- desc 'checks binary problem parse result'
66
- task :check_bin do
67
- AtCoderFriends::Regression.check_bin
68
- end
69
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'net/http'
4
- require 'uri'
5
- require 'json'
6
- require 'csv'
7
-
8
- module AtCoderFriends
9
- # tasks for regression
10
- module Regression
11
- module_function
12
-
13
- CONTEST_LIST_URL = 'https://kenkoooo.com/atcoder/resources/contests.json'
14
- ACF_HOME = File.expand_path(File.join(__dir__, '..', '..'))
15
- REGRESSION_HOME = File.join(ACF_HOME, 'regression')
16
- PAGES_DIR = File.join(REGRESSION_HOME, 'pages')
17
- EMIT_ORG_DIR = File.join(REGRESSION_HOME, 'emit_org')
18
- EMIT_DIR_FMT = File.join(REGRESSION_HOME, 'emit_%<now>s')
19
-
20
- def contest_id_list
21
- uri = URI.parse(CONTEST_LIST_URL)
22
- json = Net::HTTP.get(uri)
23
- contests = JSON.parse(json)
24
- puts "Total #{contests.size} contests"
25
- contests.map { |h| h['id'] }
26
- end
27
-
28
- def local_pbm_list
29
- Dir.glob(PAGES_DIR + '/**/*.html').map do |pbm_path|
30
- contest = File.basename(File.dirname(pbm_path))
31
- q = File.basename(pbm_path, '.html')
32
- url = "file://#{pbm_path}"
33
- [contest, q, url]
34
- end.sort # .take(10)
35
- end
36
-
37
- def pbm_list_from_file(file)
38
- dat = File.join(REGRESSION_HOME, file)
39
- CSV.read(dat, col_sep: "\t", headers: false).map do |contest, q|
40
- pbm_path = File.join(PAGES_DIR, contest, "#{q}.html")
41
- url = "file://#{pbm_path}"
42
- [contest, q, url]
43
- end
44
- end
45
- end
46
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'mechanize'
4
- require 'at_coder_friends'
5
- require_relative 'list_handler'
6
- require_relative 'report_handler'
7
-
8
- module AtCoderFriends
9
- # tasks for regression
10
- module Regression
11
- module_function
12
-
13
- def scraping_agent(root, contest)
14
- root ||= REGRESSION_HOME
15
- @ctx = Context.new({}, File.join(root, contest))
16
- @ctx.scraping_agent
17
- end
18
-
19
- def local_scraping_agent(root, contest)
20
- scraping_agent(root, contest)
21
- .tap { |sa| sa.agent.pre_connect_hooks.clear }
22
- end
23
-
24
- def agent
25
- @agent ||= Mechanize.new
26
- end
27
-
28
- def pipeline(pbm)
29
- Parser::Main.process(pbm)
30
- @ctx.generator.process(pbm)
31
- @ctx.emitter.emit(pbm)
32
- end
33
-
34
- def rmdir_force(dir)
35
- FileUtils.rm_r(dir) if Dir.exist?(dir)
36
- end
37
- end
38
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module AtCoderFriends
4
- # tasks for regression
5
- module Regression
6
- module_function
7
-
8
- def open_report(file)
9
- File.open(report_path(file), 'wb') { |f| yield f }
10
- end
11
-
12
- def report_path(file)
13
- File.join(REGRESSION_HOME, file)
14
- end
15
-
16
- def tsv_escape(str)
17
- '"' + str.gsub('"', '""').gsub("\t", ' ') + '"'
18
- end
19
- end
20
- 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
- open_report('section_list.txt') 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