atcoder_tools 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21578ce616e39fd778e17427eb0a1bee8a13fe4b2161331b83601b26b389cfdb
4
- data.tar.gz: 0cb19e3f8c40624a6215ebe903ed64579ee4446655a2ef3d2eb6be384c95ac6b
3
+ metadata.gz: e5d0c7a03c8491024c16d6ae87c288f04954180fe6bd3e189db5e3d8118faebf
4
+ data.tar.gz: 4967f7572872f9e90d1a30753a6c9c2c810392a5a78ee4936580de2b2016fe02
5
5
  SHA512:
6
- metadata.gz: b0c8ce53618f75d4eb7202d8439599fe1e0eaeb6b0d0fef6c9fe0c7a8824293bcc38a7954a4c139f15f3fa81cf590e3a45e32b369ab311843a190f1a0012e7f0
7
- data.tar.gz: 06cc6d61fd01079fbc5795ff0d7f4f1f4b352b178033eb39354f7ebd8e53825c36bbef892b5015b9c3b068f413aaea5e0a41311597b04ac3f12e2fc9c8440053
6
+ metadata.gz: b36e09e331d51158b46712cfa49e585b18e1be0e72385463b49fcc4bb0cc86060ffed4968469e9be0fd9dc48d8e1f4bae559ab98e526a0938e9b343c47510282
7
+ data.tar.gz: d758c5a868d0df29e73e9be659f6499eb383301dfca75835ccdcd210e34634d7307df61e7a5ac525a5f560a119dff2ebefa18858871aab27f5ca999c8ba8ccec
data/.envrc ADDED
@@ -0,0 +1 @@
1
+ ATCODER_TOOLS_ENV=development
@@ -0,0 +1,54 @@
1
+ name: Publish Gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - v*
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - uses: actions/setup-ruby@v1
14
+ with:
15
+ ruby-version: '2.7'
16
+
17
+ - name: Bundle install
18
+ run: bundle
19
+
20
+ - name: Build Gem
21
+ run: rake build
22
+
23
+ - name: Publish gem
24
+ uses: dawidd6/action-publish-gem@v1
25
+ with:
26
+ api_key: ${{secrets.RUBYGEMS_API_KEY}}
27
+
28
+ # - name: mkdir gem
29
+ # run: mkdir ~/.gem
30
+
31
+ # - name: Add api key
32
+ # run: "echo :rubygems_api_key: $RUBYGEMS_API_KEY > ~/.gem/credentials"
33
+ # env:
34
+ # RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
35
+
36
+ # - name: test
37
+ # run: cat ~/.gem/credentials
38
+
39
+ # - name: test2
40
+ # run: git status
41
+
42
+ # - name: test3
43
+ # run: "echo $RUBYGEMS_API_KEY"
44
+ # env:
45
+ # RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
46
+
47
+ # - name: set git username
48
+ # run: git config user.name "Aitaro Chaya"
49
+
50
+ # - name: set git email
51
+ # run: git config user.email "aitaro.chaya@gmail.com"
52
+
53
+ # - name: Release Gem
54
+ # run: rake release
data/.gitignore CHANGED
@@ -9,3 +9,6 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ test.rb
13
+
14
+ Gemfile.lock
data/README.md CHANGED
@@ -1,47 +1,51 @@
1
1
  # AtcoderTools
2
+ Atcoderの競技環境を簡単にsetupするためのツールです。
2
3
 
3
- TODOTODOTODO
4
-
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/atcoder_tools`. To experiment with that code, run `bin/console` for an interactive prompt.
6
-
7
- TODO: Delete this and the text above, and describe your gem
8
-
9
- ## Installation
10
-
11
- Add this line to your application's Gemfile:
12
-
13
- ```ruby
14
- gem 'atcoder_tools'
4
+ ## インストール
5
+ ```bash
6
+ $ gem install atcoder_tools
15
7
  ```
16
8
 
17
- And then execute:
18
-
19
- $ bundle install
9
+ ## 使い方
10
+ ### atcoderにログイン
11
+ ```
12
+ $ atcoder_tools login
13
+ ```
20
14
 
21
- Or install it yourself as:
15
+ ### コンテスト用ファイルの作成
16
+ ```
17
+ $ atcoder_tools create abc170
18
+ ```
22
19
 
23
- $ gem install atcoder_tools
20
+ ### コンテスト用自動デバッグ
21
+ ```
22
+ $ atcoder_tools start
23
+ ```
24
24
 
25
- ## Usage
25
+ ### コンテストの提出
26
26
  ```
27
- $ atcoder_tools abc170
27
+ $ atcoder_tools submit abc170
28
28
  ```
29
29
 
30
- ## Development
30
+ ### コンテストの削除
31
+ ```
32
+ $ atcoder_tools delete abc170
33
+ ```
31
34
 
32
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+ ### MODEについて
36
+ - NONE: なにもおこらない
37
+ - DEBUG: 標準入力で、testcaseが渡されたら状態で実行される。
38
+ - RUN: 単純にファイルを実行。標準入力は自分で渡す。
39
+ - TEST: rspecを用いたテスト自動実行。どれが通っていてどれが通っていないかわかる。
33
40
 
34
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
41
+ ## Development
42
+ 本リポジトリをクローンし、path指定して、gemをインストールするとデバッグできる。
35
43
 
36
44
  ## Contributing
37
-
38
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/atcoder_tools. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/atcoder_tools/blob/master/CODE_OF_CONDUCT.md).
39
-
45
+ issueやプルリク適当に投げてくれてかまいません。
40
46
 
41
47
  ## License
42
-
43
48
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
44
49
 
45
50
  ## Code of Conduct
46
-
47
51
  Everyone interacting in the AtcoderTools project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/atcoder_tools/blob/master/CODE_OF_CONDUCT.md).
@@ -31,4 +31,6 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency "listen"
32
32
  spec.add_dependency "rspec"
33
33
  spec.add_dependency 'nokogiri'
34
+ spec.add_dependency 'mechanize'
35
+ spec.add_dependency 'tty-prompt'
34
36
  end
@@ -0,0 +1,72 @@
1
+ require_relative 'settings'
2
+ require_relative 'log'
3
+
4
+ class Atcoder
5
+ include Log
6
+
7
+ def initialize
8
+ @settings = Settings.new
9
+ @agent = Mechanize.new
10
+ @agent.user_agent_alias = 'Mac Mozilla'
11
+ end
12
+
13
+ def self.test_login(username, password)
14
+ atcoder = Atcoder.new
15
+ return atcoder.login(username=username, password=password)
16
+ end
17
+
18
+ def self.submit(task)
19
+ atcoder = Atcoder.new
20
+ atcoder.login
21
+ atcoder.submit(task)
22
+ end
23
+
24
+ # 引数はtaskクラス
25
+ def task_url(task)
26
+ "https://atcoder.jp/contests/#{task.contest.name}/tasks/#{task.contest.name}_#{task.name}"
27
+ end
28
+
29
+ # 引数はcontest, taskクラス
30
+ def submit(task)
31
+ response = nil
32
+ @agent.get(task_url(task)) do |page|
33
+ # 1つ目のフォームはログアウト用なので2つ目を使用
34
+ form = page.forms.last
35
+ form.field_with(name: 'data.LanguageId').value = "4049"
36
+ form.field_with(name: 'sourceCode').value = task.code
37
+ response = @agent.submit(form)
38
+ end
39
+
40
+ if response.code.to_i == 200
41
+ return true
42
+ end
43
+ return false
44
+ end
45
+
46
+ def login(username=nil, password=nil)
47
+
48
+ username ||= @settings.credentials.username
49
+ password ||= @settings.credentials.password
50
+
51
+ response = nil
52
+ log_debug "try login to atcoder"
53
+ @agent.get("https://atcoder.jp/login") do |page|
54
+ # 1つ目のフォームはログアウト用なので2つ目を使用
55
+ form = page.forms.last
56
+ form.field_with(name: 'username').value = username
57
+ form.field_with(name: 'password').value = password
58
+ response = @agent.submit(form)
59
+ end
60
+
61
+ # print(response.response)
62
+ res = response.body.include?("Welcome, #{username}.")
63
+ if res
64
+ log_debug "login secceed!"
65
+ else
66
+ log_warn "login falied!"
67
+ end
68
+
69
+ return res
70
+ end
71
+
72
+ end
@@ -1,50 +1,156 @@
1
-
2
1
  require "thor"
3
2
  require 'fileutils'
4
3
  require "listen"
4
+ require 'mechanize'
5
5
  require_relative 'contest'
6
6
  require_relative 'task'
7
+ require_relative 'settings'
8
+ require_relative 'atcoder'
9
+ require "tty-prompt"
10
+ require_relative 'log'
11
+
7
12
 
8
13
  module AtcoderTools
9
14
  class CLI < Thor
10
- desc 'create [contest name]', 'create contest workspace'
15
+ include Log
16
+ Prompt = TTY::Prompt.new
17
+ desc 'login', 'login to atcoder'
18
+ def login
19
+ # 認証情報を書き込むので、gitignoreを設定する
20
+ unless Dir.exist?('.atcoder')
21
+ Dir.mkdir('.atcoder')
22
+ end
23
+ File.open(".atcoder/.gitignore", mode = "w"){|f|
24
+ f.write("*") # ファイルに書き込む
25
+ }
26
+ loop do
27
+ prompt = TTY::Prompt.new
28
+ username = prompt.ask("What is your atcoder username?", required: true)
29
+ password = prompt.mask("What is your atcoder password?", required: true)
30
+ puts ""
31
+ log_info 'starting test login.'
32
+
33
+ if Atcoder.test_login(username, password)
34
+ settings = Settings.new
35
+ settings.username = username
36
+ settings.password = password
37
+ settings.save!
38
+ log_info 'OK!'
39
+ break
40
+ else
41
+ log_error "Your username or password is invalid! try again!"
42
+ end
43
+ end
44
+ end
45
+
46
+ desc 'logout', 'logout from atcoder.'
47
+ def logout
48
+ settings = Settings.new
49
+ settings.destroy_credentials!
50
+ settings.save!
51
+ end
52
+
53
+ desc 'language [lang?]', '言語を選択できます。現在対応している言語は ruby, c++(gcc) です。'
54
+ def language(lang='')
55
+ unless ['ruby', 'c++(gcc)'].include?(lang)
56
+ lang = Prompt.select("choose your default language.", ['ruby', 'c++(gcc)'])
57
+ end
58
+
59
+ # コマンドが通っているかテスト
60
+ log_info "Checking path ..."
61
+ res = case lang
62
+ when 'ruby'
63
+ !!system('ruby -v')
64
+ when 'c++(gcc)'
65
+ !!system('c++ -v')
66
+ end
67
+
68
+ unless res
69
+ raise "Cannot find path of #{lang}. Is `$ #{lang} -v` working?"
70
+ end
71
+
72
+ settings = Settings.new
73
+ settings.language = lang
74
+ settings.save!
75
+ puts
76
+ log_info 'Default language successfully changed!'
77
+ end
78
+
79
+ desc 'create [contest name]', 'create contest workspace. contest name は actoderのurlより取得できます。(ex. abc173)'
11
80
  def create(contest_name)
12
81
  contest = Contest.new(contest_name)
82
+ contest.check_validity!
13
83
  contest.create!
14
84
 
15
- puts 'successfully created'
85
+ log_info 'successfully created'
16
86
  end
17
87
 
18
88
  desc 'start', 'start run'
19
89
  def start
20
- # system('bundle exec guard -d --guardfile .atcoder/Guardfile')
21
90
  listener = Listen.to('.', ignore: /.atcoder\/.*/) do |modified, added, removed|
22
- # puts "modified absolute path: #{modified}"
23
- # puts "added absolute path: #{added}"
24
- # puts "removed absolute path: #{removed}"
25
91
  if modified[0]
26
92
  contest_name ,task_name = modified[0].split('/')[-2..-1]
27
- task_name = task_name[..-4] # .rb抜き出し
28
-
29
- puts("#{contest_name}/#{task_name}.rb was changed")
93
+ task_name = task_name.scan(/(.*)\..*/)[0][0]
30
94
 
31
95
  contest = Contest.new(contest_name)
32
96
  # thor と名前空間がかぶっているため
33
97
  task = ::Task.new(contest, task_name)
98
+ # 最後に動かしたcontest, taskを記憶
99
+ settings = Settings.new
100
+ settings.current_contest = contest
101
+ settings.current_task = task
102
+ settings.save!
103
+
34
104
  task.run
35
105
  end
36
106
  end
37
- listener.start # not blocking
107
+ log_info 'started actoder_tools session.'
108
+ listener.start
38
109
  sleep
39
110
  end
40
111
 
41
- desc 'submit [contest name]', 'submit'
42
- def submit(contest_name, task_name)
43
- puts("まだ実装してないよ!")
112
+ desc 'submit', 'ソースコードを提出します。提出する問題は対話形式で指定できます。'
113
+ def submit
114
+ prompt = TTY::Prompt.new
115
+ # contest_name = prompt.select("Choose your submit contest?", Contest.list.map(&:name))
116
+ contest_name = Prompt.select("Choose your submit contest?") do |submit|
117
+ Contest.list.each_with_index do |contest, i|
118
+ submit.choice contest.name
119
+ if Settings.new.current_contest&.name == contest.name
120
+ submit.default i + 1
121
+ end
122
+ end
123
+ end
124
+
125
+ # contestによっては6種類ない可能性がある。
126
+ task_list = ['a', 'b', 'c', 'd', 'e', 'f']
127
+ task_name = prompt.select("Choose your tesk?") do |submit|
128
+ task_list.each_with_index do |task, i|
129
+ submit.choice task
130
+ if Settings.new.current_task&.name == task
131
+ submit.default i + 1
132
+ end
133
+ end
134
+ end
135
+
136
+ contest = Contest.new(contest_name)
137
+ # thor と名前空間がかぶっているため
138
+ task = ::Task.new(contest, task_name)
139
+ Atcoder.submit(task)
44
140
  end
45
141
 
46
- desc 'delete [contest name]', 'delete'
47
- def delete(contest_name)
142
+ desc 'delete [contest_name?]', 'delete'
143
+ def delete(contest_name=nil)
144
+ unless contest_name
145
+ contest_name = Prompt.select("Choose your submit contest?") do |submit|
146
+ Contest.list.each_with_index do |contest, i|
147
+ submit.choice contest.name
148
+ if Settings.new.current_contest&.name == contest.name
149
+ submit.default i + 1
150
+ end
151
+ end
152
+ end
153
+ end
48
154
  FileUtils.rm_rf(contest_name)
49
155
  FileUtils.rm_rf(".atcoder/#{contest_name}")
50
156
  puts 'successfully deleted'
@@ -3,6 +3,7 @@ require 'fileutils'
3
3
  require 'nokogiri'
4
4
  require 'erb'
5
5
  require_relative 'task'
6
+ require_relative 'settings'
6
7
 
7
8
  class Contest
8
9
  attr_reader :name
@@ -11,14 +12,39 @@ class Contest
11
12
  @name = name
12
13
  end
13
14
 
14
- def url(task_name)
15
- "https://atcoder.jp/contests/#{@name}/tasks/#{@name}_#{task_name}"
15
+ def check_validity!
16
+ # 実在するかcheck
17
+ begin
18
+ URI.open(url)
19
+ rescue OpenURI::HTTPError
20
+ raise 'contest name が存在しません。'
21
+ end
22
+ end
23
+
24
+ def url
25
+ "https://atcoder.jp/contests/#{@name}"
26
+ end
27
+
28
+ def submission_url
29
+ "https://atcoder.jp/contests/#{@name}/submissions/me"
16
30
  end
17
31
 
18
32
  def create!
19
33
  FileUtils.mkdir_p @name
20
34
  tasks = ['a','b','c','d','e','f'].map{|task_name| Task.new(self, task_name)}
21
35
  tasks.map(&:create!)
36
+ settings = Settings.new
37
+ settings.current_contest = @name
38
+ settings.contest_language = self, settings.language
39
+ settings.save!
40
+ end
41
+
42
+ def language
43
+ Settings.new.contest_language(self)
44
+ end
45
+
46
+ def self.list
47
+ Dir.glob("./*").select{|dir| FileTest.directory?(dir)}.map{|dir| Contest.new dir[2..-1] }
22
48
  end
23
49
 
24
50
  end
@@ -0,0 +1,25 @@
1
+ require 'logger'
2
+ module Log
3
+ LoggerIns = Logger.new(STDOUT)
4
+ if ENV['ATCODER_TOOLS_ENV'] == 'development'
5
+ LoggerIns.level = Logger::DEBUG
6
+ else
7
+ LoggerIns.level = Logger::INFO
8
+ end
9
+
10
+ def log_debug(msg)
11
+ LoggerIns.debug(msg)
12
+ end
13
+
14
+ def log_info(msg)
15
+ LoggerIns.info(msg)
16
+ end
17
+
18
+ def log_warn(msg)
19
+ LoggerIns.warn(msg)
20
+ end
21
+
22
+ def log_error(msg)
23
+ LoggerIns.error(msg)
24
+ end
25
+ end
@@ -0,0 +1,100 @@
1
+ require 'yaml'
2
+ require 'base64'
3
+ require 'fileutils'
4
+
5
+ class Settings
6
+ Credentials = Struct.new(:username, :password)
7
+
8
+ def initialize
9
+ if File.exist?(".atcoder/settings.yml")
10
+ @settings = YAML.load_file(".atcoder/settings.yml")
11
+ else
12
+ @settings = {}
13
+ end
14
+ end
15
+
16
+ def current_contest
17
+ @settings['current_contest'] && Contest.new(@settings['current_contest'])
18
+ end
19
+
20
+ def ambiguous_contest(contest)
21
+ case contest
22
+ when String
23
+ Contest.new(contest)
24
+ when Contest
25
+ contest
26
+ else
27
+ raise ArgumentError, "引数は StringまたはContestです。"
28
+ end
29
+ end
30
+
31
+ def current_contest=(contest)
32
+ @settings['current_contest'] = ambiguous_contest(contest).name
33
+
34
+ end
35
+
36
+ def current_task
37
+ current_contest && @settings['current_task'] && Task.new(current_contest, @settings['current_task'])
38
+ end
39
+
40
+ def current_task=(task)
41
+ case task
42
+ when String
43
+ task_name = task
44
+ when Task
45
+ task_name = task.name
46
+ else
47
+ raise ArgumentError, "引数は StringまたはTaskです。"
48
+ end
49
+ @settings['current_task'] = task_name
50
+ end
51
+
52
+ def language
53
+ @settings['language'] || 'ruby'
54
+ end
55
+
56
+ def language=(lang)
57
+ @settings['language'] = lang
58
+ end
59
+
60
+ def contest_language(contest)
61
+ if @settings[ambiguous_contest(contest).name]
62
+ @settings[ambiguous_contest(contest).name]['language']
63
+ else
64
+ language
65
+ end
66
+ end
67
+
68
+ # contest, languageの順に代入
69
+ def contest_language=(data)
70
+ name = ambiguous_contest(data[0]).name
71
+ @settings[name] ||= {}
72
+ @settings[name]['language'] = data[1]
73
+ end
74
+
75
+ def password=(password)
76
+ @settings['password'] = Base64.strict_encode64(password)
77
+ end
78
+
79
+ def username=(username)
80
+ @settings['username'] = username
81
+ end
82
+
83
+ def destroy_credentials!
84
+ @settings.delete('username')
85
+ @settings.delete('password')
86
+ end
87
+
88
+ def credentials
89
+ unless @settings.key?('username') && @settings.key?('password')
90
+ raise "先にログインしてください!"
91
+ end
92
+ return Credentials.new(@settings['username'], Base64.decode64(@settings['password']))
93
+ end
94
+
95
+ def save!
96
+ @settings['updated_at'] = Time.now
97
+ FileUtils.mkdir_p '.atcoder'
98
+ open('.atcoder/settings.yml' , 'w') {|f| YAML.dump(@settings , f ) }
99
+ end
100
+ end
@@ -3,8 +3,10 @@ require 'rspec'
3
3
  RSpec.describe 'test' do
4
4
  <% @tests.each do |test| %>
5
5
  it "test-<%= test[:no] %>" do
6
- io = IO.popen("ruby <%= task_file_path %>", "w+")
7
- io.puts("<%= test[:input] %>")
6
+ io = IO.popen("<%= command %>", "w+")
7
+ <% test[:inputs].each do |input| %>
8
+ io.puts("<%= input %>")
9
+ <% end %>
8
10
  io.close_write
9
11
  expect(io.readlines.join).to eq("<%= test[:output] %>")
10
12
  end
@@ -0,0 +1,20 @@
1
+ // ------------------------------------------------------------
2
+ // THIS IS METADATA FOR ATCODER_TOOLS
3
+ // BE CAREFULL WHEN YOU CHANGE THE VALUE
4
+ //
5
+ // METADATA::START<% inputs.each_with_index do |input, i| %>
6
+ // test-<%=i+1%>
7
+ // input: "<%= input.gsub(/\R/, '\\n') %>"
8
+ // output: "<%= outputs[i].gsub(/\R/, '\\n') %>"<% end %>
9
+ // MODE: TEST
10
+ // METADATA::FINISH
11
+ //
12
+ // you can add your original test case
13
+ // you can select MODE from NONE, DEBUG, RUN, TEST
14
+ // problem_url: <%= url %>
15
+ // submission_url: <%= contest.submission_url %>
16
+ // -------------------------------------------------------------
17
+
18
+ // snippets
19
+ // n = gets.to_i
20
+ // arr = gets.split(' ').map(&:to_i)
@@ -11,7 +11,8 @@
11
11
  #
12
12
  # you can add your original test case
13
13
  # you can select MODE from NONE, DEBUG, RUN, TEST
14
- # problem_url: <%=url%>
14
+ # problem_url: <%= url %>
15
+ # submission_url: <%= contest.submission_url %>
15
16
  # -------------------------------------------------------------
16
17
 
17
18
  # snippets
@@ -3,102 +3,154 @@ require 'fileutils'
3
3
  require 'nokogiri'
4
4
  require 'erb'
5
5
 
6
- # module Atcoder
7
- class Task
8
- def initialize(contest, name)
9
- @contest = contest
10
- @name = name
11
- @tests = []
12
- @test_outputs = []
13
- end
6
+ class Task
7
+ attr_reader :contest, :name
8
+
9
+ # contest引数はcontestクラス
10
+ def initialize(contest, name)
11
+ @contest = contest
12
+ @name = name
13
+ @tests = []
14
+ @test_outputs = []
15
+ end
16
+
17
+ def url
18
+ "https://atcoder.jp/contests/#{@contest.name}/tasks/#{@contest.name}_#{@name}"
19
+ end
14
20
 
15
- def url
16
- "https://atcoder.jp/contests/#{@contest.name}/tasks/#{@contest.name}_#{@name}"
21
+ def task_file_path
22
+ extension = nil
23
+ case @contest.language
24
+ when 'ruby'
25
+ extension = 'rb'
26
+ when 'c++(gcc)'
27
+ extension = 'cpp'
17
28
  end
29
+ "#{@contest.name}/#{@name}.#{extension}"
30
+ end
31
+
32
+ def compile_file_path
33
+ "#{@contest.name}/#{@name}"
34
+ end
18
35
 
19
- def task_file_path
20
- "#{@contest.name}/#{@name}.rb"
36
+ def test_file_path
37
+ ".atcoder/#{@contest.name}/#{@name}/spec.rb"
38
+ end
39
+
40
+ def template_task_file_path
41
+ extension = nil
42
+ case @contest.language
43
+ when 'ruby'
44
+ extension = 'rb'
45
+ when 'c++(gcc)'
46
+ extension = 'cpp'
21
47
  end
48
+ File.dirname(__dir__)+"/atcoder_tools/sources/task.#{extension}.erb"
49
+ end
22
50
 
23
- def test_file_path
24
- ".atcoder/#{@contest.name}/#{@name}/spec.rb"
51
+ def create!
52
+ html = URI.open(url) do |f|
53
+ charset = f.charset
54
+ f.read
25
55
  end
26
56
 
27
- def create!
28
- html = URI.open(url) do |f|
29
- charset = f.charset
30
- f.read
57
+ doc = Nokogiri::HTML.parse(html, nil, 'utf8')
58
+ samples = doc.css('.lang-ja > .part > section > pre').map { |e| e.children.text }
59
+ inputs, outputs = samples.partition.with_index { |_sample, i| i.even? }
60
+
61
+ erb = ERB.new(File.read(template_task_file_path))
62
+ File.write(task_file_path, erb.result(binding))
63
+ end
64
+
65
+ def run
66
+ read_meta_data
67
+ puts("#{@contest.name}/#{@name} is running in #{@mode} MODE")
68
+ update_spec
69
+ if @mode == "DEBUG"
70
+ compile
71
+ io = IO.popen(command, "w+")
72
+ @tests[0][:inputs].each do |input|
73
+ io.puts(input)
31
74
  end
75
+ io.close_write
76
+ puts io.readlines
77
+ end
78
+ if @mode == "RUN"
79
+ compile
80
+ system("echo put your inputs")
81
+ system(command)
82
+ end
83
+ if @mode == "TEST"
84
+ compile
85
+ system("bundle exec rspec #{test_file_path}")
86
+ end
87
+ end
32
88
 
33
- doc = Nokogiri::HTML.parse(html, nil, 'utf8')
34
- samples = doc.css('.lang-ja > .part > section > pre').map { |e| e.children.text }
35
- inputs, outputs = samples.partition.with_index { |_sample, i| i.even? }
89
+ def compile
90
+ case contest.language
91
+ when 'c++(gcc)'
92
+ p 'hoge'
93
+ system("c++ #{task_file_path} -o #{@contest.name}/#{@name}")
94
+ end
95
+ end
36
96
 
37
- erb = ERB.new(File.read(File.dirname(__dir__)+"/atcoder_tools/sources/task.rb.erb"))
38
- File.write(task_file_path, erb.result(binding))
97
+ def command
98
+ case contest.language
99
+ when 'ruby'
100
+ "ruby #{task_file_path}"
101
+ when 'c++(gcc)'
102
+ "#{compile_file_path}"
39
103
  end
104
+ end
40
105
 
41
- def run
42
- read_meta_data
43
- update_spec
44
- if @mode == "DEBUG"
45
- io = IO.popen("ruby #{task_file_path}", "w+")
46
- io.puts(@tests[0][:input])
47
- io.close_write
48
- puts io.readlines
106
+ def read_meta_data
107
+ meta_flag = false
108
+ test_no = nil
109
+ tests = []
110
+ mode = nil
111
+ File.foreach(task_file_path) do |line|
112
+ line.chomp!
113
+ if line == "# METADATA::START" || line == "// METADATA::START"
114
+ meta_flag = true
115
+ next
49
116
  end
50
- if @mode == "RUN"
51
- system("echo put your inputs")
52
- system("ruby #{task_file_path}")
117
+ if line == "# METADATA::FINISH" || line == "// METADATA::FINISH"
118
+ meta_flag = false
119
+ next
53
120
  end
54
- if @mode == "TEST"
55
- system("bundle exec rspec #{test_file_path}")
121
+ unless meta_flag
122
+ next
56
123
  end
57
- end
58
-
59
- def read_meta_data
60
- meta_flag = false
61
- test_no = nil
62
- tests = []
63
- mode = nil
64
- File.foreach(task_file_path) do |line|
65
- line.chomp!
66
- if line == "# METADATA::START"
67
- meta_flag = true
68
- next
69
- end
70
- if line == "# METADATA::FINISH"
71
- meta_flag = false
72
- next
73
- end
74
- unless meta_flag
75
- next
76
- end
77
- if line =~ /\#\stest-/
78
- test_no = line.scan(/\#\stest-(\d+)/)[0][0].to_i
79
- tests.push({ no: test_no })
80
- end
81
- if line =~ /\#\sinput:/
82
- test = tests.find{|test| test[:no] == test_no}
83
- test.merge!({ input: line.scan(/\#\sinput\:\s\"(.*)\"/)[0][0] })
84
- end
85
- if line =~ /\#\soutput:/
86
- test = tests.find{|test| test[:no] == test_no}
87
- test.merge!({ output: line.scan(/\#\soutput\:\s\"(.*)\"/)[0][0] })
88
- end
89
- if line =~ /\#\sMODE:/
90
- mode = line.scan(/\#\sMODE:\s(.+)/)[0][0]
91
- end
124
+ if line =~ /(\#|\/\/)\stest-/
125
+ test_no = line.scan(/(\#|\/\/)\stest-(\d+)/)[0][1].to_i
126
+ tests.push({ no: test_no })
127
+ end
128
+ if line =~ /(\#|\/\/)\sinput:/
129
+ test = tests.find{|test| test[:no] == test_no}
130
+ input_str = line.scan(/(\#|\/\/)\sinput\:\s\"(.*)\"/)[0][1]
131
+ inputs = input_str.chomp.split('\\n')
132
+ test.merge!({ inputs: inputs })
133
+ end
134
+ if line =~ /(\#|\/\/)\soutput:/
135
+ test = tests.find{|test| test[:no] == test_no}
136
+ test.merge!({ output: line.scan(/(\#|\/\/)\soutput\:\s\"(.*)\"/)[0][1] })
137
+ end
138
+ if line =~ /(\#|\/\/)\sMODE:/
139
+ mode = line.scan(/(\#|\/\/)\sMODE:\s(.+)/)[0][1]
92
140
  end
93
- @tests = tests
94
- @mode = mode
95
141
  end
142
+ @tests = tests
143
+ @mode = mode
144
+ end
96
145
 
97
- def update_spec
98
- FileUtils.mkdir_p ".atcoder/#{@contest.name}/#{@name}"
99
- erb = ERB.new(File.read(File.dirname(__dir__)+"/atcoder_tools/sources/spec.rb.erb"))
100
- File.write(test_file_path, erb.result(binding))
101
- end
146
+ def code
147
+ File.read(task_file_path)
148
+ end
102
149
 
150
+ def update_spec
151
+ FileUtils.mkdir_p ".atcoder/#{@contest.name}/#{@name}"
152
+ erb = ERB.new(File.read(File.dirname(__dir__)+"/atcoder_tools/sources/spec.rb.erb"))
153
+ File.write(test_file_path, erb.result(binding))
103
154
  end
104
- # end
155
+
156
+ end
@@ -1,3 +1,3 @@
1
1
  module AtcoderTools
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atcoder_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aitaro Chaya
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-20 00:00:00.000000000 Z
11
+ date: 2020-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mechanize
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: tty-prompt
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  description: Write a longer description or delete this line.
70
98
  email:
71
99
  - aitaro.chaya@gmail.com
@@ -74,12 +102,12 @@ executables:
74
102
  extensions: []
75
103
  extra_rdoc_files: []
76
104
  files:
105
+ - ".envrc"
106
+ - ".github/workflows/deploy.yml"
77
107
  - ".gitignore"
78
108
  - ".rspec"
79
- - ".travis.yml"
80
109
  - CODE_OF_CONDUCT.md
81
110
  - Gemfile
82
- - Gemfile.lock
83
111
  - LICENSE.txt
84
112
  - README.md
85
113
  - Rakefile
@@ -88,9 +116,13 @@ files:
88
116
  - bin/setup
89
117
  - exe/atcoder_tools
90
118
  - lib/atcoder_tools.rb
119
+ - lib/atcoder_tools/atcoder.rb
91
120
  - lib/atcoder_tools/cli.rb
92
121
  - lib/atcoder_tools/contest.rb
122
+ - lib/atcoder_tools/log.rb
123
+ - lib/atcoder_tools/settings.rb
93
124
  - lib/atcoder_tools/sources/spec.rb.erb
125
+ - lib/atcoder_tools/sources/task.cpp.erb
94
126
  - lib/atcoder_tools/sources/task.rb.erb
95
127
  - lib/atcoder_tools/task.rb
96
128
  - lib/atcoder_tools/version.rb
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.1
6
- before_install: gem install bundler -v 2.1.4
@@ -1,50 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- atcoder_tools (0.1.0)
5
- listen
6
- nokogiri
7
- rspec
8
- thor
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- diff-lcs (1.3)
14
- ffi (1.13.1)
15
- listen (3.2.1)
16
- rb-fsevent (~> 0.10, >= 0.10.3)
17
- rb-inotify (~> 0.9, >= 0.9.10)
18
- mini_portile2 (2.4.0)
19
- nokogiri (1.10.9)
20
- mini_portile2 (~> 2.4.0)
21
- rake (12.3.3)
22
- rb-fsevent (0.10.4)
23
- rb-inotify (0.10.1)
24
- ffi (~> 1.0)
25
- rspec (3.9.0)
26
- rspec-core (~> 3.9.0)
27
- rspec-expectations (~> 3.9.0)
28
- rspec-mocks (~> 3.9.0)
29
- rspec-core (3.9.2)
30
- rspec-support (~> 3.9.3)
31
- rspec-expectations (3.9.2)
32
- diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.9.0)
34
- rspec-mocks (3.9.1)
35
- diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.9.0)
37
- rspec-support (3.9.3)
38
- thor (1.0.1)
39
-
40
- PLATFORMS
41
- ruby
42
-
43
- DEPENDENCIES
44
- atcoder_tools!
45
- listen (~> 3.2)
46
- rake (~> 12.0)
47
- rspec (~> 3.0)
48
-
49
- BUNDLED WITH
50
- 2.1.4