Code Monkey home page Code Monkey logo

cargo-atcoder's Issues

Support workspaces

#18 で言った「多数のパッケージを一つのワークスペースで管理することでwarmupを不要にする」という話です。

Rustのワークスペースは同名のbinを含むことは非推奨でcargoコマンドの度にwarningが出ます。 無視するにしてもrust-analyzer等のツールが将来にわたって動いてくれるとは限りません。 ゆえにbinのリネームが必要だと考えます。

binをリネームするにあたってproblem-idbin名の対応をどうするかですが、ユーザーの既存の環境の互換性を考えると単純に<bin> = <contest-id>-<problem-id>等と仮定するよりはリネームするタイミング(new時)でしっかりとメモするのが良いと思います。 Cargo.tomlにはpackage.metadataといううってつけのフィールドがあります。

この考えの下で以下の方法を提案したいと思います。 どうでしょうか?

  1. cargo atcoder new時にbinの名前は<contest-id>-<problem-id>と、ファイル名は従来のまま<problem-id>.rsとする。その際package.metadataproblem-idbinの対応をメモする。

  2. cargo atcoder new時に既存のworkspace下に追加されるなら、(cargo newする前に)そのworkspaceのmembersに追加する。 そうでないなら、従来通り1パッケージからなるworkspaceを新たに作り、そこにprofile.releaseを書く

  3. cargo atcoder new以外のコマンドでは、1.でメモした表があるならそれでproblem-idbinを得る。 そうでないなら、従来通りproblem_id = binとする

# <workspace-root>/Cargo.toml

[workspace]
members = ["./abc126"]

# packageの方ではなくこちらに書く
[profile.release]
lto = true
panic = 'abort'
# <workspace-root>/abc126/Cargo.toml

[package]
name = "abc126"
version = "0.1.0"
authors = ["Ryo Yamashita <[email protected]>"]
edition = "2018"

[package.metadata.cargo-atcoder.problems]
a = { bin = "abc126-a" }
b = { bin = "abc126-b" }
c = { bin = "abc126-c" }
d = { bin = "abc126-d" }
e = { bin = "abc126-e" }
f = { bin = "abc126-f" }

[[bin]]
name = "abc126-a"
path = "./src/bin/a.rs"

[[bin]]
name = "abc126-b"
path = "./src/bin/b.rs"

[[bin]]
name = "abc126-c"
path = "./src/bin/c.rs"

[[bin]]
name = "abc126-d"
path = "./src/bin/d.rs"

[[bin]]
name = "abc126-e"
path = "./src/bin/e.rs"

[[bin]]
name = "abc126-f"
path = "./src/bin/f.rs"

# こっちではなくroot manifestに書く
#[profile.release]
#lto = true
#panic = 'abort'

[dependencies]
proconio = { version = "0.4.1", features = ["derive"] }

(edit) 互換性を保とうとする理由ですが、Codeforces等にも参加している人なんかはstdしか使わないのでこの機能による恩恵がほぼゼロに等しく、そういう人にとっては煩わしさの方が勝ると思われるからです。 実際Rustの提出をスクレイピングしてみると、2020年環境であってもproconioを含めクレートを使用している人はあまり多くはありません。

submissions

Config path is not ~/Library/Preferences/cargo-atcoder.toml but ~/Library/Application Support/cargo-atcoder.toml in macOS

macOS 環境における設定ファイルのパスが
~/Library/Preferences/cargo-atcoder.toml
から
~/Library/Application Support/cargo-atcoder.toml
に変更されたようです

macOS 環境でsubmitしてもソースコードで提出されたり、crossが使われなくなったりして不思議に思ったのですが上記が原因でした。
dirsのバージョンが2.0.2から3.0.1に更新されるに伴いconfig_dir()が返す値が変更された事が原因のようです。
https://docs.rs/dirs/2.0.2/dirs/fn.config_dir.html
https://docs.rs/dirs/3.0.1/dirs/fn.config_dir.html

`~/Library/Caches/cargo-atcoder` is not created in macOS

macOS Catalina ver 10.15.4, fish 環境にて、インストール直後にログインしようとしたところ、下記エラーが出ます。

> cargo atcoder login
Username: ***
Password: [hidden]
Login succeeded.
An error occurred while saving the session: failed to open `/Users/***/Library/Caches/cargo-atcoder/session.json`: No such file or directory (os error 2)

~/Library/Cachesを見るとcargo-atcoderが無かったので、作成してみたところログインできるようになりました。

~/Library/Caches 
❯ mkdir cargo-atcoder
~/Library/Caches 
❯ cargo atcoder login
Username: ***
Password: [hidden]
Login succeeded.

thread 'main' panicked at 'assertion failed: `(left == right)`

How to reproduce:

$ cargo atcoder new dwacon5th-prelims
$ cd dwacon5th-prelims
$ cargo atcoder submit c

Error:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `3`,
 right: `5`', /Users/xxx/.cargo/git/checkouts/cargo-atcoder-22f22504501ff75c/3c72a19/src/atcoder.rs:469:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

`cargo atcoder new` で edition が指定できない

私は rustup でデフォルトの toolchain を stable-x86_64-unknown-linux-gnu としているのですが、AtCoder の Rust は 1.42.0 であるため、~/.config/cargo-atcoder.toml 内で rust-toolchain を生成するように指定しています。

[project]
# to create `rust-toolchain` file, uncomment this line.
rustc_version = "1.42.0"

先日 Rust 1.56.0 が stable としてリリースされ、 2021 edition が始まりました。これを反映させるため rustup の update を行いましたが、その影響で cargo new によって生成されるクレートは edition="2021" の指定が入るようになりました。
以上の理由から、cargo atcoder new ... で生成されるプロジェクトを動かすためには Cargo.toml を手で書き換えなければなりません。

プロジェクト生成部

let stat = Command::new("cargo")

でオプションとして --edition 2018 を指定すればこれを解決できると思うのですが、

  • cargo-atcoder.toml で指定された rustc_version から指定するべき edition を自動で認識し、オプションとして付加する
  • rustc_version と同様に editioncargo-atcoder.toml で指定できるようにする
  • cargo atcoder new に対して cargo new で使用可能なコマンドを受け付けるようにして、実行時にそのまま渡すようにする

といった解決策が考えられると思います。

この点について PR を送りたいと思っているのですが、どのようにするべきかご意見いただけると幸いです。

submit出来ません(panic発生)

面白い感じでしたので、実験させていただきました。
が、残念なことに、submitがうまく出来ません。
環境:

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="19.10 (Eoan Ermine)"
ID=ubuntu
$ rustup show
Default host: x86_64-unknown-linux-gnu
rustup home:  /home/mito/.rustup

installed toolchains
--------------------

stable-x86_64-unknown-linux-gnu (default)
nightly-x86_64-unknown-linux-gnu

installed targets for active toolchain
--------------------------------------

thumbv7em-none-eabihf
x86_64-unknown-linux-gnu
x86_64-unknown-linux-musl

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)
rustc 1.43.0 (4fb7144ed 2020-04-20)

この環境で、試しに、
$cargo atcoder new abc164
を実行。
abc164/src/bin/a.rsに次のソースを入力

use proconio::{input, fastout};

#[fastout]
fn main() {
    input! {
        r: f64,
    }
    println!("{}", 2.0 * r * 3.14159265358979);
}   

続いてtest

atcoder/abc163$ cargo atcoder test a
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
running 2 tests
test sample 1 ... ok (abs error: 6.217e-15 , rel error: 9.895e-16 )
test sample 2 ... ok (abs error: 4.547e-13 , rel error: 9.914e-16 )

test_result: ok

これは、順調。
次に、submitすると・・・(参考データにRUST_BACKTRACEをつけておきます。つけなくても同じ結果です。)

atcoder/abc163$ RUST_BACKTRACE=1 cargo atcoder submit a
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
running 2 tests
test sample 1 ... ok (abs error: 6.217e-15 , rel error: 9.895e-16 )
test sample 2 ... ok (abs error: 4.547e-13 , rel error: 9.914e-16 )

test_result: ok

thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /home/****/.cargo/git/checkouts/cargo-atcoder-22f22504501ff75c/e51f21f/src/atcoder.rs:536:24
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:77
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:59
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1052
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1426
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:62
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:49
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:204
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:224
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:472
  11: rust_begin_unwind
             at src/libstd/panicking.rs:380
  12: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
  13: core::panicking::panic
             at src/libcore/panicking.rs:52
  14: std::future::poll_with_tls_context
  15: cargo_atcoder::main::{{closure}}
  16: <std::future::GenFuture<T> as core::future::future::Future>::poll
  17: std::thread::local::LocalKey<T>::with
  18: tokio::runtime::basic_scheduler::BasicScheduler<P>::block_on
  19: tokio::runtime::context::enter
  20: tokio::runtime::handle::Handle::enter
  21: cargo_atcoder::main
  22: std::rt::lang_start::{{closure}}
  23: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:52
  24: std::panicking::try::do_call
             at src/libstd/panicking.rs:305
  25: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:86
  26: std::panicking::try
             at src/libstd/panicking.rs:281
  27: std::panic::catch_unwind
             at src/libstd/panic.rs:394
  28: std::rt::lang_start_internal
             at src/libstd/rt.rs:51
  29: main
  30: __libc_start_main
  31: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

となります。
便利そうだったので、ちょっと残念。
治ると嬉しいのですが。

Some command require users to login for even finished contests

現在newtest等のコマンドは終了後のコンテストに対してもログインを要求します。

例えばtest時のこれは一旦見て404なら"Please login first"で良いはずです。

pub fn test_cases(&self, problem_url: &str) -> Result<Vec<TestCase>> {
self.check_login()?;
let doc = self.http_get(problem_url)?;

不要なログインを要求しないことで #30 のようなテストが追加できます。 repository owner(=tanakhさん)のクレデンシャルをこんな感じで使うという方法も無くはないですが。

`--quiet` is specified for the `gen-binary` command

Gitterにも書きましたが現在gen_binary_source内のcargo buildには--quietが指定されています。

cargo-atcoder/src/main.rs

Lines 669 to 683 in 1e66dee

let status = Command::new(program)
.arg("build")
.arg(format!("--target={}", target))
.arg("--release")
.arg("--bin")
.arg(&bin.name)
.arg("--quiet")
.current_dir({
// `cross` does not work with `--manifest-path <absolute path>`.
package
.manifest_path
.parent()
.expect("`manifest_path` should end with \"Cargo.toml\"")
})
.status()?;

しかしTODO.mdを見ると

- [ ] バイナリ生成中にコンパイルの進捗が見えない

とあります。 --quietの対象はBuilding ...等の進捗メッセージを含みます。 この--quietは誤って追加されたものではないでしょうか?

問題名の 20 バイト目が char boundary でないと submit 後に panic する

例えば A - 2 倍チェック / Is It a Number? でこの現象が起きます.
以下の行 で最初の 20 bytes を取ろうとしているのが原因のようです.

                    pb.set_prefix(&format!(
                        "{} | {:20} |",
                        DateTime::<Local>::from(result.date).format("%Y-%m-%d %H:%M:%S"),
                        &result.problem_name[0..min(20, result.problem_name.len())],
                    ));
Fetching submission result...
thread 'main' panicked at 'byte index 20 is not a char boundary; it is inside 'ク' (bytes 18..21) of `A - 2 倍チェック / Is It a Number?`', src/libcore/str/mod.rs:2068:5
stack backtrace:
   0: backtrace::backtrace::libunwind::trace
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
   1: backtrace::backtrace::trace_unsynchronized
             at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
   2: std::sys_common::backtrace::_print_fmt
             at src/libstd/sys_common/backtrace.rs:77
   3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
             at src/libstd/sys_common/backtrace.rs:61
   4: core::fmt::write
             at src/libcore/fmt/mod.rs:1028
   5: std::io::Write::write_fmt
             at src/libstd/io/mod.rs:1412
   6: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:65
   7: std::sys_common::backtrace::print
             at src/libstd/sys_common/backtrace.rs:50
   8: std::panicking::default_hook::{{closure}}
             at src/libstd/panicking.rs:188
   9: std::panicking::default_hook
             at src/libstd/panicking.rs:205
  10: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:464
  11: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:373
  12: rust_begin_unwind
             at src/libstd/panicking.rs:302
  13: core::panicking::panic_fmt
             at src/libcore/panicking.rs:139
  14: core::str::slice_error_fail
             at src/libcore/str/mod.rs:0
  15: core::str::traits::<impl core::slice::SliceIndex<str> for core::ops::range::Range<usize>>::index::{{closure}}
  16: alloc::collections::btree::map::Entry<K,V>::or_insert_with
  17: cargo_atcoder::watch_submission_status::{{closure}}::{{closure}}
  18: tokio::task::core::Core<T>::poll
  19: std::panicking::try::do_call
  20: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:78
  21: tokio::task::harness::Harness<T,S>::poll
  22: tokio::runtime::basic_scheduler::BasicScheduler<P>::block_on
  23: tokio::runtime::context::enter
  24: tokio::runtime::handle::Handle::enter
  25: cargo_atcoder::main
  26: std::rt::lang_start::{{closure}}
  27: std::rt::lang_start_internal::{{closure}}
             at src/libstd/rt.rs:48
  28: std::panicking::try::do_call
             at src/libstd/panicking.rs:287
  29: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:78
  30: std::panicking::try
             at src/libstd/panicking.rs:265
  31: std::panic::catch_unwind
             at src/libstd/panic.rs:396
  32: std::rt::lang_start_internal
             at src/libstd/rt.rs:47
  33: main
  34: __libc_start_main
  35: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
^C
[1]    29112 interrupt  cargo atcoder submit a

HTML character references are not converted in test cases

ABC078のA問題のようにテストケースにHTMLのCharacter Referenceが混ざっている場合に元の文字へ変換されていない不具合があるようです

running 3 tests
test sample 1 ... FAILED
test sample 2 ... FAILED
test sample 3 ... ok

---- sample 1 ----
input:
     1 | A B

expected output:
     1 | &lt;

your output:
     1 | <

---- sample 2 ----
input:
     1 | E C

expected output:
     1 | &gt;

your output:
     1 | >

test result: FAILED. 1 passed; 2 failed

Feature to open webpages and source files

私が作っているcargo-competeでは

  • cargo compete new --open
  • cargo compete open

  1. 問題のページをブラウザで
  2. 各ソースファイルの.rsとテストファイルの.ymlを任意のエディタで

開けるようにしています。思いの他体験が良いのでcargo-atcoderでもどうでしょうか。

GIF

ただ1.はCargoでも使われているopenerで良いとして、2.を任意のエディタに対して提供しようとすると設定がちょっと面倒ですね。

こういうのを思いついたのでcargo-competeはそうしたんですが

# Open files with the command (`jq` command)
#
# Emacs:
open = '["emacsclient", "-n"] + (.paths | map([.src, .test_suite]) | flatten)'

VSCodeがこうなってしまい後悔しています。(-aを一緒にまとめるとrust-analyzer拡張が変なエラーを出したりして体験が悪い。VSCodeを常用していないので気づきませんでした)

# VSCode:
open = '["bash", "-c"] + ["code -a " + .manifest_dir + " && code " + (.paths | map([.src, .test_suite]) | flatten | join(" "))]'

(edit) こうしたら普通に解決しました (qryxip/cargo-compete#71)

# Open files with the command (`jq` command that outputs `string[] | string[][]`)
open = '[["code", "-a", .manifest_dir], ["code"] + (.paths | map([.src, .test_suite]) | flatten)]'

Failed to parse result

素晴らしいツールをありがとうございます!いつも使わせていただいてます!

cargo atcoder submit aなどで回答を提出した際にfailed to parse resultとエラーが表示され、正常に動作しません

cargo atcoder submit b
    Finished dev [unoptimized + debuginfo] target(s) in 0.24s
running 3 tests
test sample 1 ... ok
test sample 2 ... ok
test sample 3 ... ok

test_result: ok

Submitted to problem `abc178_b`, using language `Rust (1.42.0)`

Fetching submission result...
thread 'main' panicked at 'failed to parse result:
<tr>

                                                <td class="no-break"><time class="fixtime fixtime-second">2020-09-19 16:49:53+0900</time></td>
                                                <td><a href="/contests/abc178/tasks/abc178_b">B - Product Max</a></td>
                                                <td><a href="/users/DuGlaser">DuGlaser</a> <a href="/contests/abc178/submissions?f.User=DuGlaser"><span title="view DuGlaser" submissions'="" data-toggle="tooltip" s="" class="glyphicon glyphicon-search black" aria-hidden="true"></span></a></td>
                                                <td><a href="/contests/abc178/submissions/me?f.Language=4050">Rust (1.42.0)</a></td>
                                                <td data-id="16840943" class="text-right submission-score">0</td>
                                                <td class="text-right">543 Byte</td>
                                                <td class="text-center waiting-judge" data-id="16840943" colspan="3"><span title="Waiting for Judging" aria-hidden="true" data-toggle="tooltip" class="label label-default" data-placement="top">WJ</span></td>
                                                <td class="text-center">
                                                        <a href="/contests/abc178/submissions/16840943">Detail</a>
                                                </td>
                                        </tr>', /Users/DuGlaser/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-atcoder-0.2.0/src/atcoder.rs:667:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
RUST_BACKTRACE=1 cargo atcoder submit b
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
running 3 tests
test sample 1 ... ok
test sample 2 ... ok
test sample 3 ... ok

test_result: ok

Submitted to problem `abc178_b`, using language `Rust (1.42.0)`

Fetching submission result...
thread 'main' panicked at 'failed to parse result:
<tr>

                                                <td class="no-break"><time class="fixtime fixtime-second">2020-09-19 17:00:45+0900</time></td>
                                                <td><a href="/contests/abc178/tasks/abc178_b">B - Product Max</a></td>
                                                <td><a href="/users/DuGlaser">DuGlaser</a> <a href="/contests/abc178/submissions?f.User=DuGlaser"><span data-toggle="tooltip" title="view DuGlaser" s="" submissions'="" aria-hidden="true" class="glyphicon glyphicon-search black"></span></a></td>
                                                <td><a href="/contests/abc178/submissions/me?f.Language=4050">Rust (1.42.0)</a></td>
                                                <td class="text-right submission-score" data-id="16841177">0</td>
                                                <td class="text-right">543 Byte</td>
                                                <td class="text-center waiting-judge" colspan="3" data-id="16841177"><span aria-hidden="true" title="Waiting for Judging" class="label label-default" data-toggle="tooltip" data-placement="top">WJ</span></td>
                                                <td class="text-center">
                                                        <a href="/contests/abc178/submissions/16841177">Detail</a>
                                                </td>
                                        </tr>', /Users/DuGlaser/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-atcoder-0.2.0/src/atcoder.rs:667:17
stack backtrace:
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::default_hook
   5: std::panicking::rust_panic_with_hook
   6: rust_begin_unwind
   7: std::panicking::begin_panic_fmt
   8: cargo_atcoder::atcoder::AtCoder::submission_status
   9: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
  10: tokio::runtime::task::core::Core<T,S>::poll
  11: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
  12: tokio::runtime::task::raw::poll
  13: std::thread::local::LocalKey<T>::with
  14: tokio::runtime::basic_scheduler::BasicScheduler<P>::block_on
  15: tokio::runtime::context::enter
  16: tokio::runtime::handle::Handle::enter
  17: cargo_atcoder::main
  18: std::rt::lang_start::{{closure}}
  19: std::rt::lang_start_internal
  20: main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Save test cases in files

ファイルに保存して閲覧、編集できたほうが便利だと思うので。 方針としては以下の2つがあります。

ディレクトリにテキストを入れる

tests/in/test1.txttests/out/test1.txt、あるいはtests/test1.intests/test2.inをペアにするような保存形式です。

oj(とそれに依存するatcoder-cli等のツール)をはじめとしたほぼすべての競プロツールがこれのはずです。

Pros

  • 我々の実装が非常に楽
  • その場のシェルスクリプトで簡単にテストケースを追加できる
  • 外部から読みやすい
  • MiB級のサイズのデータに追加の対応が要らない

Cons

  • 一覧するのが面倒
  • 直に書き込むのにファイルを2つ開く必要がある

JSONやYAMLで管理

competitive-companionとかがこれです。あと私が作ったのも。

一応、大きいデータに対応するため一部をテキストファイルに替えることができます。

私のツールだとこんなのです。

---
type: batch       # "batch", "interactive", or "unsubmittable"
timelimit: 2000ms # optional
match: exact      # "any", "exact", or "float"

cases:
  - name: Sample 1
    in: |
      1
      2 3
      test
    out: |
      6 test
  - name: Sample 2
    in: |
      72
      128 256
      myonmyon
    out: |
      456 myonmyon
  # "name" and "out" are optional
  - in: |
      1000
      1000 1000
      oooooooooooooo

Pros

  • 上記のConsの逆
  • コンテスト開始時にRustのソースファイルと共にエディタで開くといったことが可能

Cons

  • 上記のProsの逆

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.