AOJのコンテストをインポートできるようにしましょう
Description / 説明
- AOJの問題を本サービスで利用できるようにする
Motivation / 動機
- 教育的な良問が多いため、問題集の問題としてふさわしい
- AtCoderとは仕様がやや異なるため、個別の対応が必要
TODO
- [x] インポートの対象を確認
- [x] ざっと見た感じでは、Course・Challenge・Volに分かれている
- [x] Courseがメインと思えばいいのか?要確認
- [x] APIの有無を調べる
- [ ] 利用に関する制約や作者への許諾などの手続きが必要か確認
- [x] 必要であるなら、連絡先の調査・使用目的などの文面を用意
- [x] APIの利用申請
- [ ] 上記の許可が得られるまで待機
- [ ] APIの利用が難しい場合は自作
- [ ] DBのスキーマを改修
- [ ] 既存 or 自作のAPIをcall
- [ ] 問題のインポート部分をリファクタリング
- [ ] AOJ特有の処理が必要であれば追加
- [ ] 単体テストを追加
調査中
- サイトがv1, v2, v3で別々に稼働している。2024年9月ごろにv3が登場。
- 2024年10月現在は、v2がメインだと思われる。
- 理由: v3で新規アカウント作成しようとすると、v2にリダイレクトされるため。
- v2: https://onlinejudge.u-aizu.ac.jp/problems/NTL_1_A
- v3: https://onlinejudge.u-aizu.ac.jp/services/ice/?problemId=INFO1_14_G
- 2024年10月現在は、v2がメインだと思われる。
Other notes / その他
- Add any other context or screenshots about the feature request here.
- Will you try to create a pull request?
- yes / no
See
- ICPC Japan Problemsにおける実装例(新APIを利用している可能性が高い)
- https://github.com/ir5/icpc-japan-problems/blob/main/admin/crawl_aoj.py
- ojのAOJに関する実装(旧APIを利用していると思われる)
- https://github.com/online-judge-tools/api-client/blob/master/onlinejudge/service/aoj.py
問題集に追加予定
・https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP2_1_A&lang=ja (外部)(4Q) vector の末尾挿入、末尾削除、index アクセス ・https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_3_A&lang=ja (外部)(3Q) 逆ポラード記法 ・https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_3_D&lang=ja (外部)(1Q) 洪水の被害状況をシミュレーション ・https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_3_C&lang=ja (外部) (1D) ヒストグラムの中の最大長方形 ・https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DPL_3_B&lang=ja (外部) (1D) 最大長方形
テストにおけるAPIの操作の記録・再生
VitestでAPIのテストを行い、APIリクエスト内容の記録および再生を行うことは可能です。これを実現するためには、nockというライブラリを使用することが一般的です。nockはHTTPリクエストをモックし、リクエストとレスポンスを記録および再生する機能を提供します。
以下は、Vitestとnockを使用してAPIのテストを行う例です。
手順
- 必要なパッケージをインストールします。
- テストファイルを作成し、nockを使用してAPIリクエストをモックします。
- テストを実行します。
1. パッケージのインストール
npm install --save-dev vitest nock
2. テストファイルの作成
以下は、example.test.jsという名前のテストファイルの例です。
import { describe, it, expect } from 'vitest';
import nock from 'nock';
import axios from 'axios';
describe('API Test with Nock', () => {
it('should record and replay API request', async () => {
// nockを使用してAPIリクエストをモック
const scope = nock('https://api.example.com')
.get('/data')
.reply(200, { key: 'value' });
// 実際のAPIリクエスト
const response = await axios.get('https://api.example.com/data');
// レスポンスの検証
expect(response.status).toBe(200);
expect(response.data).toEqual({ key: 'value' });
// nockがすべてのリクエストを処理したかを確認
scope.done();
});
});
3. テストの実行
以下のコマンドを実行してテストを実行します。
npx vitest run
この手順に従うことで、Vitestとnockを使用してAPIのテストを行い、APIリクエスト内容の記録および再生を実現できます。
See
https://github.com/nock/nock?tab=readme-ov-file
HTTPリクエストの内容をファイルに保存して再生するためには、nockのrecorder機能を使用する必要があります。
以下は、HTTPリクエストの内容をファイルに保存し、再生する方法の例です。
手順
- 必要なパッケージをインストールします。
- リクエストを記録するスクリプトを作成します。
- 記録されたリクエストを再生するテストファイルを作成します。
- テストを実行します。
1. パッケージのインストール
npm install --save-dev vitest nock
2. リクエストを記録するスクリプトの作成
以下は、record.jsという名前のスクリプトの例です。
const nock = require('nock');
const axios = require('axios');
const fs = require('fs');
// nockのレコーダーを開始
nock.recorder.rec({
output_objects: true,
dont_print: true
});
(async () => {
// 実際のAPIリクエスト
await axios.get('https://api.example.com/data');
// レコーディングを停止して、リクエスト内容を取得
const nockCallObjects = nock.recorder.play();
// リクエスト内容をファイルに保存
fs.writeFileSync('nockRecordings.json', JSON.stringify(nockCallObjects, null, 2));
})();
このスクリプトを実行すると、nockRecordings.jsonというファイルにリクエスト内容が保存されます。
3. 記録されたリクエストを再生するテストファイルの作成
以下は、example.test.jsという名前のテストファイルの例です。
import { describe, it, expect } from 'vitest';
import nock from 'nock';
import fs from 'fs';
import axios from 'axios';
describe('API Test with Nock', () => {
beforeAll(() => {
// 記録されたリクエスト内容を読み込み
const nockCallObjects = JSON.parse(fs.readFileSync('nockRecordings.json', 'utf-8'));
// nockにリクエスト内容をロード
nock.define(nockCallObjects);
});
it('should replay recorded API request', async () => {
// 実際のAPIリクエスト
const response = await axios.get('https://api.example.com/data');
// レスポンスの検証
expect(response.status).toBe(200);
expect(response.data).toEqual({ key: 'value' });
});
});
4. テストの実行
以下のコマンドを実行してテストを実行します。
npx vitest run
この手順に従うことで、HTTPリクエストの内容をファイルに保存し、再生することができます。
上記のコードでは、const response = await axios.get('https://api.example.com/data'); の部分は実際のHTTP通信を行っていません。代わりに、nockが記録されたリクエスト内容を利用してレスポンスをモックしています。
具体的には、以下のように動作します:
-
記録フェーズ (
record.js):- 実際のHTTPリクエストが行われ、その内容が
nockRecordings.jsonに保存されます。
- 実際のHTTPリクエストが行われ、その内容が
-
再生フェーズ (
example.test.js):- テストの実行前に、
nockRecordings.jsonから記録されたリクエスト内容を読み込み、nockにロードします。 -
axios.get('https://api.example.com/data')が呼び出されると、nockがそのリクエストをインターセプトし、記録されたレスポンスを返します。
- テストの実行前に、
これにより、実際のHTTP通信を行わずに、記録されたレスポンスを利用してテストを行うことができます。
再生フェーズのコード再掲
import { describe, it, expect } from 'vitest';
import nock from 'nock';
import fs from 'fs';
import axios from 'axios';
describe('API Test with Nock', () => {
beforeAll(() => {
// 記録されたリクエスト内容を読み込み
const nockCallObjects = JSON.parse(fs.readFileSync('nockRecordings.json', 'utf-8'));
// nockにリクエスト内容をロード
nock.define(nockCallObjects);
});
it('should replay recorded API request', async () => {
// 実際のAPIリクエスト
const response = await axios.get('https://api.example.com/data');
// レスポンスの検証
expect(response.status).toBe(200);
expect(response.data).toEqual({ key: 'value' });
});
});
このコードでは、axios.getが呼び出されたときにnockがそのリクエストをキャッチし、記録されたレスポンスを返すため、実際のHTTP通信は行われません。