# [CMS Online Judge] 互動題、Checker
:::info
目錄:
* [[CMS Online Judge] Docker安裝教學](/WKsC33XYRme4sM-Kkst_XA)
* [[CMS Online Judge] 完整安裝教學](/qLOLKTjlQ6ivpN0vg4yb-g)
* [[CMS Online Judge] 使用教學](/vzeJxoVGQPipzqd3R0_s9w)
* [[CMS Online Judge] 互動題、Checker](/cA70QEPVRROxvTxYujMTcw)
* [[CMS Online Judge] 給系統管理者的一些建議](/EOf5VvLOSM6BTjbVfb7vRg)
[Github連結](https://github.com/erichung09060/cms)
:::
:::success
所有的範例題目都是a+b問題
```
Input :
3 4
Output :
7
```
:::
## Checker
計分方式:checker會輸出一個介於0到1之間的浮點數,0表示沒有拿到分數,1表示完全拿到此題子測資的分數,0.5表示拿到一半子測資的分數,以此類推。
設定步驟:
* 把`Output evalution`改成`Outputs are compared by a comparator`
* 上傳checker執行檔
:::spoiler checker
編譯指令:`g++ checker.cpp -o checker -static`
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char* argv[]) {
ifstream input(argv[1]);
ifstream correct_output(argv[2]);
ifstream user_output(argv[3]);
int userans, ans;
user_output >> userans;
correct_output >> ans;
if (userans == ans) cout << 1.0 << '\n';
else cout << 0.0 << '\n';
}
```
:::
:::spoiler solution
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
cout << a + b << '\n';
}
```
:::
:::spoiler 示意圖
![](https://i.imgur.com/UeWurYr.png)
:::
## Loader Code
管理員需要上傳一份Code(Loader Code),judge會把參賽者的Code和Loader Code合併,再去編譯及執行,因此參賽者只需要實作特定的function即可。
設定步驟:
* 把`Compilation`改成`Submissions are compiled with a grader`
* 上傳Loader code,每一種支持的語言都要上傳一份,否則該語言會無法編譯
* 請注意,Task type不同會需要叫不同的檔名:
1. `Batch Type`:`grader.cpp`
2. `Communication Type`:`stub.cpp`
:::spoiler grader.cpp/stub.cpp
```cpp=
#include <bits/stdc++.h>
using namespace std;
int add(int x, int y);
int main() {
int a,b;
cin >> a >> b;
cout << add(a, b) << '\n';
}
```
:::
:::spoiler Solution
```cpp=
#include <bits/stdc++.h>
using namespace std;
int add(int a, int b){
return a + b;
}
```
:::
:::spoiler 示意圖
Batch Type:
![](https://i.imgur.com/mx9jlOL.png)
Communication Type:
![](https://i.imgur.com/Wj8dMxn.png)
:::
## 互動題
讓用戶的程式碼跟judge互動,一來一往,可防止參賽者使用離線算法。
:::warning
要記得設定Time Limit否則會無法編譯。
:::
* 設定`Time Limit`為`1`
* 設定`Task Type`為`Communitation`
* 設定`Number of Processes`為`1`
* 設定`User I/O`為`
User processes read from stdin and write to stdout
`
* 上傳manager.cpp的執行檔,做為參賽者互動的對象
### 例題
一樣a+b問題,但參賽者不知道有幾次查詢,計算完並輸出結果後judge才會告訴你下一組查詢。
#### 測資
```
Input :
2
3 4
34587378934534 32452384572389
Output :
7
67039763506923
```
:::spoiler manager.cpp
編譯指令:`g++ manager.cpp -o manager -static`
manager最後會需要輸出一個0到1之間的數,用法跟checker一樣用來計算分數。
```cpp=
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main(int argc, char **argv) {
ofstream to_user(argv[2]);
ifstream from_user(argv[1]);
int n;
cin >> n;
double score = 0;
for (int i = 1; i <= n; i++) {
ll a, b, userans;
cin >> a >> b;
to_user << a << ' ' << b << endl;
from_user >> userans;
ll ans = a + b;
score += (userans == ans) * 1.0 / n;
}
cout << score << '\n';
to_user.close();
from_user.close();
}
```
:::
:::spoiler solution.cpp
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char **argv) {
long long a, b;
while(cin >> a >> b){
cout << a + b << endl;
}
}
```
:::
:::spoiler 示意圖
![image](https://hackmd.io/_uploads/rkd1ioig0.png)
:::
------------------------
## 注意事項
:::warning
1. 要上傳的checker及manager為編譯過後的執行檔,請勿直接上傳.cpp檔。
2. 如果編譯出來的執行檔在cms上無法執行,請換一台電腦編譯。
3. `Communication Type`一定要使用`endl`或`flush`來清空緩衝區。
:::