优化 PHP client 代码 (#9)
* add a simple judge client for php * 把JudgeClient类单独抽出来 * Unify code style * Unify code style * 优化 PHP cliet 代码 * 添加 python3 支持 * 删除多余参数 * 下划线命名改为驼峰命名
This commit is contained in:
parent
384d31dc22
commit
7e3f394603
|
@ -1,84 +1,164 @@
|
|||
<?php
|
||||
|
||||
|
||||
class JudgeClient
|
||||
{
|
||||
|
||||
private $ch = null;
|
||||
private $serverBaseUrl = '';
|
||||
private $token;
|
||||
private static $languageConfigs = [];
|
||||
|
||||
public function __construct($token, $serverBaseUrl)
|
||||
{
|
||||
$this->serverBaseUrl = rtrim($serverBaseUrl, '/');
|
||||
$this->ch = curl_init();
|
||||
$defaults = [
|
||||
CURLOPT_RETURNTRANSFER => 1,
|
||||
CURLOPT_HEADER => 0,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-type: application/json',
|
||||
'X-Judge-Server-Token: ' . $token
|
||||
],
|
||||
//POST方式
|
||||
CURLOPT_POST => 1
|
||||
];
|
||||
curl_setopt_array($this->ch, $defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送http请求
|
||||
* @param $url string 请求的url
|
||||
* @param $data array 请求参数
|
||||
*/
|
||||
private function request($url, $data = [])
|
||||
{
|
||||
curl_setopt($this->ch, CURLOPT_URL, $url);
|
||||
curl_setopt($this->ch, CURLOPT_POSTFIELDS, empty($data) ? '{}' : json_encode($data));
|
||||
if (!$result = curl_exec($this->ch)) {
|
||||
trigger_error(curl_error($this->ch));
|
||||
}
|
||||
return json_decode($result);
|
||||
$this->token = hash('sha256', $token);
|
||||
}
|
||||
|
||||
public function ping()
|
||||
{
|
||||
return $this->request($this->serverBaseUrl . '/ping');
|
||||
return $this->post($this->serverBaseUrl . '/ping');
|
||||
}
|
||||
|
||||
public function judge($src, $language_config, $max_cpu_time, $max_memory, $test_case_id, $output = false, $spj_version = null,
|
||||
$spj_config = null, $spj_compile_config = null, $spj_src = null)
|
||||
/**
|
||||
* 调用判题 api
|
||||
* @param string $src 提交的源代码
|
||||
* @param string $language 使用的编程语言
|
||||
* @param string $testCaseId test_case_id
|
||||
* @param array $config 额外配置
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function judge($src, $language, $testCaseId, $config = [])
|
||||
{
|
||||
$data = [
|
||||
'language_config' => $language_config,
|
||||
'src' => $src,
|
||||
'max_cpu_time' => $max_cpu_time,
|
||||
'max_memory' => $max_memory,
|
||||
'test_case_id' => $test_case_id,
|
||||
'spj_version' => $spj_version,
|
||||
'spj_config' => $spj_config,
|
||||
'spj_compile_config' => $spj_compile_config,
|
||||
'spj_src' => $spj_src,
|
||||
'output' => $output
|
||||
];
|
||||
return $this->request($this->serverBaseUrl . '/judge', $data);
|
||||
$languageConfig = static::getLanguageConfigByLanguage($language);
|
||||
|
||||
if (is_null($languageConfig)) {
|
||||
throw new Exception("don't support \"$language\" language!");
|
||||
}
|
||||
|
||||
$default = [
|
||||
'language_config' => $languageConfig,
|
||||
'src' => $src,
|
||||
'test_case_id' => $testCaseId,
|
||||
'max_cpu_time' => $languageConfig['compile']['max_cpu_time'],
|
||||
'max_memory' => $languageConfig['compile']['max_memory'],
|
||||
'spj_version' => null,
|
||||
'spj_config' => null,
|
||||
'spj_compile_config' => null,
|
||||
'spj_src' => null,
|
||||
'output' => false
|
||||
];
|
||||
return $this->post($this->serverBaseUrl . '/judge', array_merge($default, $config));
|
||||
}
|
||||
|
||||
public function compileSpj($src, $spj_version, $spj_compile_config, $test_case_id)
|
||||
public function compileSpj($src, $spjVersion, $spjCompileConfig)
|
||||
{
|
||||
$data = [
|
||||
'src' => $src,
|
||||
'spj_version' => $spj_version,
|
||||
'spj_compile_config' => $spj_compile_config,
|
||||
'test_case_id' => $test_case_id
|
||||
'spj_version' => $spjVersion,
|
||||
'spj_compile_config' => $spjCompileConfig,
|
||||
];
|
||||
return $this->request($this->serverBaseUrl . '/compile_spj', $data);
|
||||
return $this->post($this->serverBaseUrl . '/compile_spj', $data);
|
||||
}
|
||||
|
||||
public static function loadLanguageConfigs()
|
||||
{
|
||||
if (empty(static::$languageConfigs))
|
||||
static::$languageConfigs = require('languages.php');
|
||||
}
|
||||
|
||||
public static function getLanguageConfigByLanguage($language)
|
||||
{
|
||||
return static::getLanguageConfigByKey($language . '_lang_config');
|
||||
}
|
||||
|
||||
public static function getLanguageConfigByKey($key)
|
||||
{
|
||||
return isset(static::$languageConfigs[$key]) ? static::$languageConfigs[$key] : null;
|
||||
}
|
||||
|
||||
private function needCreateCurl()
|
||||
{
|
||||
return is_null($this->ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 curl 资源
|
||||
* @return null|resource
|
||||
*/
|
||||
private function getCurl()
|
||||
{
|
||||
if ($this->needCreateCurl()) {
|
||||
$this->ch = curl_init();
|
||||
$defaults = [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HEADER => false,
|
||||
// set HTTP request header
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'Content-type: application/json',
|
||||
'X-Judge-Server-Token: ' . $this->token
|
||||
],
|
||||
];
|
||||
curl_setopt_array($this->ch, $defaults);
|
||||
}
|
||||
|
||||
return $this->ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 GET 请求
|
||||
* @param string $url 请求的url
|
||||
* @param array $data 请求参数
|
||||
* @return array
|
||||
*/
|
||||
private function get($url, $data = [])
|
||||
{
|
||||
return $this->request('GET', $url, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 POST 请求
|
||||
* @param string $url 请求的url
|
||||
* @param array $data 请求参数
|
||||
* @return array
|
||||
*/
|
||||
private function post($url, $data = [])
|
||||
{
|
||||
return $this->request('POST', $url, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 http 请求
|
||||
* @param string $method http method
|
||||
* @param string $url 请求的url
|
||||
* @param array $data 请求参数
|
||||
* @return array
|
||||
*/
|
||||
private function request($method, $url, $data = [])
|
||||
{
|
||||
$ch = $this->getCurl();
|
||||
$method = strtoupper($method);
|
||||
if (in_array($method, ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH']))
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, empty($data) ? '{}' : json_encode($data));
|
||||
if (!$result = curl_exec($this->ch)) {
|
||||
trigger_error(curl_error($this->ch));
|
||||
}
|
||||
return json_decode($result, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭 curl 资源
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
if (is_resource($this->ch)) {
|
||||
curl_close($this->ch);
|
||||
}
|
||||
$this->ch = null;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
|
@ -86,3 +166,5 @@ class JudgeClient
|
|||
$this->close();
|
||||
}
|
||||
}
|
||||
|
||||
JudgeClient::loadLanguageConfigs();
|
|
@ -2,24 +2,26 @@
|
|||
|
||||
require('JudgeClient.php');
|
||||
|
||||
$c_src = <<<EOD
|
||||
$token = 'YOUR_TOKEN_HERE';
|
||||
|
||||
$cSrc = <<<'CODE'
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
int a, b;
|
||||
scanf("%d%d", &a, &b);
|
||||
printf("%d", a+b);
|
||||
printf("%d\n", a+b);
|
||||
return 0;
|
||||
}
|
||||
EOD;
|
||||
CODE;
|
||||
|
||||
$c_spj_src = <<<EOD
|
||||
$cSpjSrc = <<<'CODE'
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
return 1;
|
||||
}
|
||||
EOD;
|
||||
CODE;
|
||||
|
||||
$cpp_src = <<<EOD
|
||||
$cppSrc = <<<'CODE'
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
@ -31,9 +33,9 @@ int main()
|
|||
cout << a+b << endl;
|
||||
return 0;
|
||||
}
|
||||
EOD;
|
||||
CODE;
|
||||
|
||||
$java_src = <<<EOD
|
||||
$javaSrc = <<<'CODE'
|
||||
import java.util.Scanner;
|
||||
public class Main{
|
||||
public static void main(String[] args){
|
||||
|
@ -43,32 +45,50 @@ public class Main{
|
|||
System.out.println(a + b);
|
||||
}
|
||||
}
|
||||
EOD;
|
||||
CODE;
|
||||
|
||||
$py2_src = <<<EOD
|
||||
$py2src = <<<'CODE'
|
||||
s = raw_input()
|
||||
s1 = s.split(" ")
|
||||
print int(s1[0]) + int(s1[1])
|
||||
EOD;
|
||||
CODE;
|
||||
|
||||
$py3src = <<<'CODE'
|
||||
s = input()
|
||||
s1 = s.split(" ")
|
||||
print(int(s1[0]) + int(s1[1]))
|
||||
CODE;
|
||||
|
||||
|
||||
$judgeClient = new JudgeClient(hash('sha256', 'token'), 'http://123.57.151.42:12358');
|
||||
$languages = require('languages.php');
|
||||
$judgeClient = new JudgeClient($token, 'http://127.0.0.1:12358');
|
||||
|
||||
echo "ping:\n";
|
||||
print_r($judgeClient->ping());
|
||||
|
||||
echo "\n\ncompile_spj:\n";
|
||||
print_r($judgeClient->compileSpj($c_spj_src, '2', $languages['c_lang_spj_compile'], 'spj'));
|
||||
print_r($judgeClient->compileSpj($cSpjSrc, '2', JudgeClient::getLanguageConfigByKey('c_lang_spj_compile')));
|
||||
|
||||
echo "\n\njudge c:\n";
|
||||
print_r($judgeClient->judge($c_src, $languages['c_lang_config'], 1000, 1024 * 1024 * 128, 'normal', true));
|
||||
echo "\n\nc_judge:\n";
|
||||
print_r($judgeClient->judge($cSrc, 'c', 'normal', [
|
||||
'output' => true
|
||||
]));
|
||||
|
||||
echo "\n\njudge cpp:\n";
|
||||
print_r($judgeClient->judge($cpp_src, $languages['cpp_lang_config'], 1000, 1024 * 1024 * 128, 'normal'));
|
||||
echo "\n\nc_spj_judge:\n";
|
||||
print_r($judgeClient->judge($cSrc, 'c', 'spj', [
|
||||
'spj_version' => '3',
|
||||
'spj_config' => JudgeClient::getLanguageConfigByKey('c_lang_spj_config'),
|
||||
'spj_compile_config' => JudgeClient::getLanguageConfigByKey('c_lang_spj_compile'),
|
||||
'spj_src' => $cSpjSrc,
|
||||
]));
|
||||
|
||||
echo "\n\njudge java:\n";
|
||||
print_r($judgeClient->judge($java_src, $languages['java_lang_config'], 1000, 1024 * 1024 * 128, 'normal'));
|
||||
echo "\n\ncpp_judge:\n";
|
||||
print_r($judgeClient->judge($cppSrc, 'cpp', 'normal'));
|
||||
|
||||
echo "\n\njudge python2:\n";
|
||||
print_r($judgeClient->judge($py2_src, $languages['py2_lang_config'], 1000, 1024 * 1024 * 128, 'normal'));
|
||||
echo "\n\njava_judge:\n";
|
||||
print_r($judgeClient->judge($javaSrc, 'java', 'normal'));
|
||||
|
||||
echo "\n\npy2_judge:\n";
|
||||
print_r($judgeClient->judge($py2src, 'py2', 'normal'));
|
||||
|
||||
echo "\n\npy3_judge:\n";
|
||||
print_r($judgeClient->judge($py3src, 'py3', 'normal'));
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
$default_env = ["LANG=en_US.UTF-8", "LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8"];
|
||||
|
||||
return [
|
||||
'c_lang_config' => [
|
||||
'compile' => [
|
||||
|
@ -13,6 +15,7 @@ return [
|
|||
'run' => [
|
||||
'command' => '{exe_path}',
|
||||
'seccomp_rule' => 'c_cpp',
|
||||
'env' => $default_env
|
||||
]
|
||||
],
|
||||
'c_lang_spj_compile' => [
|
||||
|
@ -26,7 +29,8 @@ return [
|
|||
'c_lang_spj_config' => [
|
||||
'exe_name' => 'spj-{spj_version}',
|
||||
'command' => '{exe_path} {in_file_path} {user_out_file_path}',
|
||||
'seccomp_rule' => 'c_cpp'
|
||||
'seccomp_rule' => 'c_cpp',
|
||||
'env' => $default_env
|
||||
],
|
||||
'cpp_lang_config' => [
|
||||
'name' => 'cpp',
|
||||
|
@ -55,8 +59,8 @@ return [
|
|||
],
|
||||
'run' => [
|
||||
'command' => '/usr/bin/java -cp {exe_dir} -Xss1M -XX:MaxPermSize=16M -XX:PermSize=8M -Xms16M -Xmx{max_memory}k -Djava.security.manager -Djava.security.policy==/etc/java_policy -Djava.awt.headless=true Main',
|
||||
'seccomp_rule' => null,
|
||||
'env' => ['MALLOC_ARENA_MAX=1']
|
||||
'seccomp_rule' => 'general',
|
||||
'env' => array_merge(['MALLOC_ARENA_MAX=1'], $default_env)
|
||||
]
|
||||
],
|
||||
'py2_lang_config' => [
|
||||
|
@ -71,6 +75,22 @@ return [
|
|||
'run' => [
|
||||
'command' => '/usr/bin/python {exe_path}',
|
||||
'seccomp_rule' => null,
|
||||
'env' => $default_env
|
||||
]
|
||||
],
|
||||
'py3_lang_config' => [
|
||||
'compile' => [
|
||||
'src_name' => 'solution.py',
|
||||
'exe_name' => '__pycache__/solution.cpython-35.pyc',
|
||||
'max_cpu_time' => 3000,
|
||||
'max_real_time' => 5000,
|
||||
'max_memory' => 128 * 1024 * 1024,
|
||||
'compile_command' => '/usr/bin/python3 -m py_compile {src_path}',
|
||||
],
|
||||
'run' => [
|
||||
'command' => '/usr/bin/python3 {exe_path}',
|
||||
'seccomp_rule' => 'general',
|
||||
'env' => array_merge(['MALLOC_ARENA_MAX=1'], $default_env)
|
||||
]
|
||||
]
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue