| Crates.io | cargo-compete |
| lib.rs | cargo-compete |
| version | 0.10.7 |
| created_at | 2020-08-02 09:01:48.389825+00 |
| updated_at | 2024-06-08 12:11:45.179187+00 |
| description | A Cargo subcommand for competitive programming. |
| homepage | |
| repository | https://github.com/qryxip/cargo-compete |
| max_upload_size | |
| id | 272168 |
| size | 487,323 |
A Cargo subcommand for competitive programming.
Supports AtCoder, Codeforces, and yukicoder. Other websites are available via online-judge-tools/api-client.
| Registeration | Sample Test Cases | System Test Cases | Submiting | Watching Submissions | Submission Details | |
|---|---|---|---|---|---|---|
| AtCoder | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :grey_question: | :x: |
| Codeforces | :x: | :heavy_check_mark: | N/A | :heavy_check_mark: | :x: | :x: |
| yukicoder | N/A | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x: | :x: |
| Other websites | :x: | Depends on online-judge-tools | Depends on online-judge-tools | Depends on online-judge-tools | :x: | :x: |
$ cargo install cargo-compete
If the build fails, adding --locked may help.
master branch$ cargo install --git https://github.com/qryxip/cargo-compete
We provide the binaries in GitHub Releases.
cargo compete initGenerates some files for other commands.
Run this command first. It generates the following files.
Required for other commands.
Sets build/target-dir to share the target directory.
template-cargo-lock.toml
A template of Cargo.lock for cargo compete new.
Generated only if you answer 2 Yes to Do you use crates on AtCoder? question.
If this file is generated, file path to it is added to new.template.lockfile in compete.toml.

cargo compete migrate cargo-atcoderSee the section in the Japanese readme.
cargo compete loginLogges in a website.
This is not a command for a package.
You don't have to run this command beforehand, because cargo-compete asks credentials if necessary.
cargo compete participateRegisteres in a contest.
This is not a command for a package.
You don't have to run this command beforehand, because cargo-compete registers in the contest if necessary.
cargo compete newRetrieves test cases and creates a package for the contest.
Requires compete.toml.
Generate it with cargo compete init first.
You can opens the pages in your browser with the --open option.
And you can also open the source files and the test cases in your browser by testing open in compete.toml.
If you forget to add --open, cd to the generated package and run cargo compete open.

cargo compete addGenerates bin targets and retrieves the test cases for them.
Requires compete.toml.
Generate it with cargo compete init first.
To use this function, configure add in the compete.toml like this.
# for yukicoder
[add]
url = '{% case args[0] %}{% when "contest" %}https://yukicoder.me/contests/{{ args[1] }}{% when "problem" %}https://yukicoder.me/problems/no/{{ args[1] }}{% endcase %}'
is-contest = ["bash", "-c", '[[ $(cut -d / -f 4) == "contests" ]]'] # optional
#target-kind = "bin" # ["bin", "example"]. default to "bin"
bin-name = '{% assign segments = url | split: "/" %}{{ segments[5] }}'
#bin-alias = '{% assign segments = url | split: "/" %}{{ segments[5] }}' # optional
#bin-src-path = './src/bin/{{ bin_alias }}.rs' # optional
❯ cargo compete a contest 296
Added `1358` (bin) for https://yukicoder.me/problems/no/1358
Added `1359` (bin) for https://yukicoder.me/problems/no/1359
Added `1360` (bin) for https://yukicoder.me/problems/no/1360
Added `1361` (bin) for https://yukicoder.me/problems/no/1361
Added `1362` (bin) for https://yukicoder.me/problems/no/1362
Added `1363` (bin) for https://yukicoder.me/problems/no/1363
Added `1364` (bin) for https://yukicoder.me/problems/no/1364
Added `1365` (bin) for https://yukicoder.me/problems/no/1365
Saved 1 test case to /home/ryo/src/competitive/yukicoder/testcases/1358.yml
Saved 3 test cases to /home/ryo/src/competitive/yukicoder/testcases/1359.yml
Saved 3 test cases to /home/ryo/src/competitive/yukicoder/testcases/1360.yml
Saved 3 test cases to /home/ryo/src/competitive/yukicoder/testcases/1361.yml
Saved 3 test cases to /home/ryo/src/competitive/yukicoder/testcases/1362.yml
Saved 1 test case to /home/ryo/src/competitive/yukicoder/testcases/1363.yml
Saved 3 test cases to /home/ryo/src/competitive/yukicoder/testcases/1364.yml
Saved 3 test cases to /home/ryo/src/competitive/yukicoder/testcases/1365.yml
❯ cargo compete a problem 9001
Added `9001` (bin) for https://yukicoder.me/problems/no/9001
Saved 1 test case to /home/ryo/src/competitive/yukicoder/testcases/9001.yml
cargo compete retrieve testcases / cargo compete downloadRetrieves test cases for an existing package.
This is a command for a package.
cd to the package generated with cargo compete new.

With --open option, you can download system test cases instead of sample ones.
For AtCoder, we have to use Dropbox API. Generate an access token with these two permissions in some way,
files.metadata.readsharing.readand save a JSON file in the following format to {local data directory}/cargo-compete/tokens/dropbox.json.
(I'm thinking of better way)
{
"access_token": "<access token>"
}
cargo compete retrieve submission-summariesRetrieves your submissions, and outputs as JSON.
This is a command for a package.
cd to the package generated with cargo compete new.
For example, you can get "the URL for the latest submission" by adding | jq -r '.summaries[0].detail.
$ # for Linux
$ xdg-open "$(cargo compete r ss | jq -r '.summaries[0].detail')"
cargo compete openOpens pages in your browser, and opens source and test cases in your editor.
This is a command for a package.
cd to the package generated with cargo compete new.
cargo compete testRuns tests.
This is a command for a package.
cd to the package generated with cargo compete new.
You don't have to run this command beforehand, because the tests are run in the submit command.
cargo compete submitSubmits your code.
This is a command for a package.
cd to the package generated with cargo compete new.
You can convert code with a tool such as cargo-equip and cargo-executable-payload by setting submit in the compete.toml.
[submit]
kind = "command"
args = ["cargo", "+1.70.0", "equip", "--exclude-atcoder-202301-crates", "--remove", "docs", "--minify", "libs", "--bin", "{{ bin_name }}"]
language_id = "5054"
[submit]
kind = "command"
args = ["cargo", "executable-payload", "--bin", "{{ bin_name }}"]
language_id = "5054"
Here is an example for compete.toml.
# Path to the test file (Liquid template)
#
# Variables:
#
# - `manifest_dir`: Package directory
# - `contest`: Contest ID (e.g. "abc100")
# - `bin_name`: Name of a `bin` target (e.g. "abc100-a")
# - `bin_alias`: "Alias" for a `bin` target defined in `pacakge.metadata.cargo-compete` (e.g. "a")
# - `problem`: Alias for `bin_alias` (deprecated)
#
# Additional filters:
#
# - `kebabcase`: Convert to kebab case (by using the `heck` crate)
test-suite = "{{ manifest_dir }}/testcases/{{ bin_alias }}.yml"
# Open files with the command (`jq` command that outputs `string[] | string[][]`)
#
# VSCode:
#open = '[["code", "-a", .manifest_dir], ["code"] + (.paths | map([.src, .test_suite]) | flatten)]'
# Emacs:
#open = '["emacsclient", "-n"] + (.paths | map([.src, .test_suite]) | flatten)'
[template]
src = '''
fn main() {
todo!();
}
'''
[template.new]
# `edition` for `Cargo.toml`.
edition = "2018"
# `profile` for `Cargo.toml`.
#
# By setting this, you can run tests with `opt-level=3` while enabling `debug-assertions` and `overflow-checks`.
#profile = '''
#[dev]
#opt-level = 3
#'''
dependencies = '''
num = "=0.2.1"
num-bigint = "=0.2.6"
num-complex = "=0.2.4"
num-integer = "=0.1.42"
num-iter = "=0.1.40"
num-rational = "=0.2.4"
num-traits = "=0.2.11"
num-derive = "=0.3.0"
ndarray = "=0.13.0"
nalgebra = "=0.20.0"
alga = "=0.9.3"
libm = "=0.2.1"
rand = { version = "=0.7.3", features = ["small_rng"] }
getrandom = "=0.1.14"
rand_chacha = "=0.2.2"
rand_core = "=0.5.1"
rand_hc = "=0.2.0"
rand_pcg = "=0.2.1"
rand_distr = "=0.2.2"
petgraph = "=0.5.0"
indexmap = "=1.3.2"
regex = "=1.3.6"
lazy_static = "=1.4.0"
ordered-float = "=1.0.2"
ascii = "=1.0.0"
permutohedron = "=0.2.4"
superslice = "=1.0.0"
itertools = "=0.9.0"
itertools-num = "=0.1.3"
maplit = "=1.0.2"
either = "=1.5.3"
im-rc = "=14.3.0"
fixedbitset = "=0.2.0"
bitset-fixed = "=0.1.0"
proconio = { version = "=0.3.6", features = ["derive"] }
text_io = "=0.1.8"
whiteread = "=0.5.0"
rustc-hash = "=1.1.0"
smallvec = "=1.2.0"
'''
dev-dependencies = '''
#atcoder-202004-lock = { git = "https://github.com/qryxip/atcoder-202004-lock" }
'''
[template.new.copy-files]
"./template-cargo-lock.toml" = "Cargo.lock"
[new]
kind = "cargo-compete"
# Platform
#
# - atcoder
# - codeforces
# - yukicoder
platform = "atcoder"
# Path (Liquid template)
#
# Variables:
#
# - `contest`: Contest ID. **May be nil**
# - `package_name`: Package name
path = "./{{ contest }}"
#[new]
#kind = "oj-api"
#url = "https://atcoder.jp/contests/{{ id }}"
#path = "./{{ contest }}"
# for Library-Checker
#[add]
#url = "https://judge.yosupo.jp/problem/{{ args[0] }}"
##is-contest = ["false"] # optional
##target-kind = "bin" # ["bin", "example"]. default to "bin"
#bin-name = '{{ args[0] }}'
##bin-alias = '{{ args[0] }}' # optional
##bin-src-path = './src/bin/{{ bin_alias }}.rs' # optional
# for yukicoder
#[add]
#url = '{% case args[0] %}{% when "contest" %}https://yukicoder.me/contests/{{ args[1] }}{% when "problem" %}https://yukicoder.me/problems/no/{{ args[1] }}{% endcase %}'
#is-contest = ["bash", "-c", '[[ $(cut -d / -f 4) == "contests" ]]'] # optional
##target-kind = "bin" # ["bin", "example"]. default to "bin"
#bin-name = '{% assign segments = url | split: "/" %}{{ segments[5] }}'
##bin-alias = '{% assign segments = url | split: "/" %}{{ segments[5] }}' # optional
##bin-src-path = './src/bin/{{ bin_alias }}.rs' # optional
[test]
# Toolchain for the test. (optional)
toolchain = "1.42.0"
# Profile for `cargo build`. ("dev" | "release")
#
# Defaults to `"dev"`.
#profile = "dev"
[submit]
kind = "file"
path = "{{ src_path }}"
language_id = "5054"
#[submit]
#kind = "command"
#args = ["cargo", "+1.70.0", "equip", "--exclude-atcoder-202301-crates", "--remove", "docs", "--minify", "libs", "--bin", "{{ bin_name }}"]
#language_id = "5054"
And here is an example for package.metadata in Cargo.toml.
[package]
name = "practice"
version = "0.1.0"
authors = ["Ryo Yamashita <qryxip@gmail.com>"]
edition = "2018"
[package.metadata.cargo-compete.bin]
practice-a = { alias = "a", problem = "https://atcoder.jp/contests/practice/tasks/practice_1" }
practice-b = { alias = "b", problem = "https://atcoder.jp/contests/practice/tasks/practice_2" }
#[package.metadata.cargo-compete.example]
[[bin]]
name = "practice-a"
path = "src/bin/a.rs"
[[bin]]
name = "practice-b"
path = "src/bin/b.rs"
[dependencies]
num = "=0.2.1"
num-bigint = "=0.2.6"
num-complex = "=0.2.4"
num-integer = "=0.1.42"
num-iter = "=0.1.40"
num-rational = "=0.2.4"
num-traits = "=0.2.11"
num-derive = "=0.3.0"
ndarray = "=0.13.0"
nalgebra = "=0.20.0"
alga = "=0.9.3"
libm = "=0.2.1"
rand = { version = "=0.7.3", features = ["small_rng"] }
getrandom = "=0.1.14"
rand_chacha = "=0.2.2"
rand_core = "=0.5.1"
rand_hc = "=0.2.0"
rand_pcg = "=0.2.1"
rand_distr = "=0.2.2"
petgraph = "=0.5.0"
indexmap = "=1.3.2"
regex = "=1.3.6"
lazy_static = "=1.4.0"
ordered-float = "=1.0.2"
ascii = "=1.0.0"
permutohedron = "=0.2.4"
superslice = "=1.0.0"
itertools = "=0.9.0"
itertools-num = "=0.1.3"
maplit = "=1.0.2"
either = "=1.5.3"
im-rc = "=14.3.0"
fixedbitset = "=0.2.0"
bitset-fixed = "=0.1.0"
proconio = { version = "=0.3.6", features = ["derive"] }
text_io = "=0.1.8"
whiteread = "=0.5.0"
rustc-hash = "=1.1.0"
smallvec = "=1.2.0"
[dev-dependencies]
Test cases are saved as YAML files.
# https://atcoder.jp/contests/practice/tasks/practice_1
---
type: Batch
timelimit: 2s
match: Lines
cases:
- name: sample1
in: |
1
2 3
test
out: |
6 test
- name: sample2
in: |
72
128 256
myonmyon
out: |
456 myonmyon
extend:
- type: Text
path: "./a"
in: /in/*.txt
out: /out/*.txt
# https://atcoder.jp/contests/ddcc2019-final/tasks/ddcc2019_final_a
---
type: Batch
timelimit: 2s
match:
Float:
relative_error: 1e-8
absolute_error: 1e-8
cases:
- name: sample1
in: |
5
-->--
out: |
3.83333333333333
- name: sample2
in: |
7
-------
out: |
6.5
- name: sample3
in: |
10
-->>>-->--
out: |
6.78333333333333
extend:
- type: Text
path: "./a"
in: /in/*.txt
out: /out/*.txt
# https://judge.yosupo.jp/problem/sqrt_mod
---
type: Batch
timelimit: 10s
match:
Checker:
cmd: ~/.cache/online-judge-tools/library-checker-problems/math/sqrt_mod/checker "$INPUT" "$ACTUAL_OUTPUT" "$EXPECTED_OUTPUT"
shell: Bash
cases: []
extend:
- type: SystemTestCases
The format is TestSuite in the following schemas.
TestSuiteTestSuite::BatchA test suite for a normal problem.
| Field | Type | Default | Description |
|---|---|---|---|
timelimit |
Duration | null |
~ |
Time limit |
match |
Match |
Judging method | |
cases |
Case[] |
[] |
Sets of input and output |
extend |
Extend[] |
[] |
Additional sets of input and output |
DurationA string that can parsed with humantime::format_duration.
MatchAn untagged ADT.
Match::Exact = "Exact"Compares whole strings.
Match::SplitWhiteSpace = "SplitWhitespace"Compares words splitted by whitespace.
Match::Lines = "Lines"Compares lines.
Match::FloatCompares words splitted by whitespace.
absolute_error and relative_error are applied for pairs of words that can parsed as floating point numbers.
| Field | Type | Default | Description |
|---|---|---|---|
relative_error |
PositiveFiniteFloat64 | null |
~ |
Relative error |
absolute_error |
PositiveFiniteFloat64 | null |
~ |
Absolute error |
PositiveFiniteFloat64A 64-bit floating point number that is positive and is not inf.
Match::CheckerChecks with a shell script.
The following environment variables are given for the script.
INPUTACTUAL_OUTPUTEXPECTED_OUTPUT (only if the Case.out is present)| Field | Type | Default | Description |
|---|---|---|---|
cmd |
str |
Command | |
shell |
Shell |
Shell |
ShellAn untagged ADT.
Shell::Bash = "Bash"Bash.
Case| Field | Type | Default | Description |
|---|---|---|---|
name |
str |
"" |
Name |
in |
str |
Input | |
out |
str | null |
~ |
Output |
timelimit |
Duration | null |
~ |
Overrides timelimit |
match |
Match | null |
~ |
Overrides match |
ExtendExtend::Text| Field | Type | Default | Description |
|---|---|---|---|
path |
str |
Directory | |
in |
Glob |
Text files for input | |
out |
Glob |
Text files for output | |
timelimit |
Duration | null |
~ |
Overrides timelimit |
match |
Match | null |
~ |
Overrides match |
GlobA glob.
Extend::SystemTestCasesSystem test cases.
System test cases are stored under { cache directory }/cargo-compete/system-test-cases.
They are automatically downloaded if missing when testing code.
| Field | Type | Default | Description |
|---|---|---|---|
problem |
Url | null |
~ | URL of the problem |
UrlA URL.
TestSuite::InteractiveA test suite for an interactive problem.
| Field | Type | Default | Description |
|---|---|---|---|
timelimit |
Duration | null |
~ |
Time limit |
TestSuite::UnsubmittableA dummy test suite for dummy problems such as ones in APG4b.
| Field | Type | Default | Description |
|---|
The cookies and tokens are saved under { local data directory }/cargo-compete.
.
├── cookies.jsonl
└── tokens
├── codeforces.json
├── dropbox.json
└── yukicoder.json
cargo-compete reads these environment variables if they exist, and use them.
$DROPBOX_ACCESS_TOKEN$YUKICODER_API_KEY$CODEFORCES_API_KEY$CODEFORCES_API_SECRETFor unsupported websites, oj-api(.exe) in the $PATH is used when downloading and submitting.
[package]
name = "library-checker"
version = "0.0.0"
edition = "2018"
publish = false
[package.metadata.cargo-compete.bin]
aplusb = { problem = "https://judge.yosupo.jp/problem/aplusb" }
See the section in the Japanese readme.
Dual-licensed under MIT or Apache-2.0.