توضیحات کلی
در این پروژه ابتدا بکاند سیستم و سپس فرانتاند آن را ایجاد کردهایم. برای بکاند از شریف جاج، سلری و ربیتامکیو و برای فرانتاند از داکوویکی استفاده شده.
نصب سلری
با دستور زیر ابتدا پیاچپی را نصب میکنیم:
sudo apt-get install php5
برای نصب سلری ۲ متد وجود دارد. یکی از طریق pip پایتون یکی از روی سورس. برای نصب از روی سورس، اول آخرین نسخهٔ سلری را از اینجا دانلود میکنیم.
سپس فایل دانلود شده را از حالت فشرده خارج میکنیم:
tar xvfz celery-0.0.0.tar.gz
به داخل دایرکتوری رفته با اجرای دستور زیر فایل نصب را ایجاد میکنیم:
cd celery-x.x.x
python setup.py build
سپس با یوزر روت فایل ایجاد شده را نصب میکنیم:
python setup.py install
نصب ربیتامکیو
اگر میخواهید آخرین نسخه rabbitmq را نصب کنید خط زیر را به ریپازیتوریها در فایل source.list اضافه کنید درغیراینصورت این دستور و دستور بعد از آن را اسکیپ کنید و rabbitmq-server را نصب کنید:
deb http://www.rabbitmq.com/debian/ testing main
مخازن را آپدیت میکنیم:
apt-get update
با یوزر روت به نصب ربیتامکیو میپردازیم:
sudo apt-get install rabbitmq-server
برای شروع این سرویس از دستور زیر استفاده کنید:
sudo service rabbitmq-server start
با اجرای دستور زیر کمپوسر را دریافت و نصب میکنیم:
curl -sS https://getcomposer.org/installer | php
با اجرای دستور بالا کمپوسر در یک فایل به نام composer.phar در هوم کاربر نصب میشود. با اجرای دستور زیر در هر دایرکتوری که باشید وقتی دستور composer را وارد کنید فایل composer.phar اجرا میشود. دستور زیر را با یوزر روت اجرا کنید:
sudo mv ~/composer.phar /usr/local/bin/composer
ایجاد یک پروژه برای استفاده از ربیتامکیو و تنظیمات اولیه
برای پروژه، یک دایرکتوری ایجاد کنید و در این دایرکتوری فایلی با نام composer.json ایجاد کنید و سورس زیر را در آن وارد کنید تا با اجرای آن کتابخانههای مورد نیاز ربیتامکیو را دانلود و در محل پروژه قرار دهد:
{
"require":{
"videlalvaro/php-amqplib": "v2.1.0"
}
}
سپس در دایرکتوری پروژه، با یوزر روت کتابخانههای مورد نیاز را دریافت کنید:
sudo composer install
برای افزودن یک یوزر به ربیتامکیو:
sudo rabbitmqctl add_user username password
برای ایجاد یک هاست مجازی در ربیتامکیو میتوانید از دستور زیر استفاده کنید. منظور از هاست مجازی ایجاد یک کانال اختصاصی است که بتوان پیغامها را دستهبندی کرد و هر دسته را از طریق یک کانال ارسال کرد و بیشتر وقتی کاربرد دارد که چندین برنامه مختلف از ربیتامکیو استفاده میکنند.
sudo rabbitmqctl add_vhost vhostName
برای اینکه به یک یوزر دسترسی استفاده از یک هاست مجازی را بدهیم:
sudo rabbitmqctl set_permissions -p vhostName username ".*" ".*" ".*"
در دستورات بالا vhostName و username و password با مقادیر واقعی آنها جایگزین شوند.
ایجاد یک پروژه با ربیتامکیو و سلری
برای اینکار ابتدا فایلی با نام tasks.py ایجاد کنید و کد زیر را درون آن قرار دهید.
from celery import Celery
import time
app = Celery( 'tasks', backend='amqp', broker='amqp://' )
@app.task
def judge(x, y):
time.sleep(50)
return x+y
توضیحات کد بالا:
app = Celery( 'tasks', backend='amqp', broker='amqp://' )
ورودی اول: tasks اسم فایلی است که تسکهای سلری در آن نوشته شده است.
ورودی دوم: از امکانات خود ربیتامکیو به عنوان بکاند برای ذخیره کردن نتایج و وضعیت اجرای تسک در حال اجرا استفاده شده است.
ورودی سوم: در این خط از ربیتامکیو به عنوان مسیج بروکر استفاده شده است.
@app.task
def judge(x, y):
time.sleep(5)
return x+y
برای مشخص کردن عملی که سلری میخواهد انجام دهد تابع tasks را overwrite کردهایم و برای اینکه اجرای تابع را مشاهده کنیم گفتهایم فقط ۵ ثانیه sleep کند.
ورکر سلری را روی پورت 5672 گوش به فرمان قرار دهید (دستور زیر را با یوزر root یا sudo اجرا نکنید):
celery -A tasks worker --loglevel=info
برای صدا زدن تسک judge دستورات زیر را در کنسول پایتون وارد کنید:
from tasks import judge
result = judge.delay(12, 20)
در خط دوم تابع delay که بر روی آبجکت judge صدا زده شده است یک آبجکت از نوع آسنکرون بر میگرداند به این معنی که هر موقعی که بخواهیم میتوانیم خروجی آن را چک کنیم. به عنوان مثال با تابع زیر میتوانید چک کرد که آیا کار تابع تمام شده است یا خیر:
result.ready()
هم چنین به هر تسک یک آیدی یکتا اختصاص داده میشود که میتوانید با زدن نام متغیر result آن را مشاهده کنید:
result
چیزی شبیه این:
<AsyncResult: eccdb1cf-e16a-4461-9305-60d9ed4003ce>
اتصال به جاج
فرض شده است که کد برنامهٔ آپلود شده توسط کاربر جاج در آدرس زیر قرار دارد:
/path/to/assignment/p#/user_name/file_name-##.file_extension
تستکیسها در این آدرس:
/path/to/assignment/p#/in/ {input1.txt, input2.txt, ...}
و خروجی ها در این آدرس قرار خواهد گرفت:
/path/to/assignment/p#/out/ {output1.txt, output2.txt, ...}
فایل tester.sh را از گیتهاب شریفجاج دانلود میکنیم. این اسکریپت چندین آرگومان دارد که به تفصیل توضیح خواهم داد.
./tester.sh /path/to/assignment/p# user_name main_file_name file_name-## file_extension time_limit time_limit_int memory_limit output_size_limit Diff_Command Diff_Command_options bool_judge_log bool_easysandbox bool_c_c++_shield bool_python_shield bool_java_security_manager bool_java_exceptions
توضیح آرگومانهای ورودی فایل tester.sh
آرگومان main_file_name تنها برای فایل برنامههای جاوای ارسال شده توسط کاربر استفاده میشود. یعنی پیش از اجرای برنامه نام فایل file_name-## به main_file_name تغییر مییابد. در عمل چنین اتفاقی میافتد:
cp /path/to/assignment/p#/user_name/file_name-##.java main_file_name.java
آرگومان File_extension پسوند نام فایل است که این درواقع زبان برنامهٔ ارسال شده را مشخص میکند.
آرگومان time_limit محدودیت زمان اجرای برنامه را مشخص میکند. (با آرگومان time_limit_int چه فرقی دارد؟!)
آرگومان memory_limit محدودیت فضای حافظه قابل allocate کردن به برنامه را مشخص میکند.
آرگومان output_size_limit حجم فایل خروجی را مشخص میکند. (چه نیازی به اینکار هست؟!)
آرگومان Diff_Command نام دستوری است که از آن برای مقایسه نتیجه کد اجرا شده و خروجی صحیح استفاده میشود.
آرگومان Diff_Command_options آرگومانهای ورودی دستور مذکور میباشد.
آرگومان bool_judge_log از نوع بولین میباشد و تعیینکننده فعال بودن قابلیت لاگ جاج میباشد.
آرگومانهای بعدی نیز همگی مانند متغیر قبلی از نوع بولین بوده و تعیینکننده فعال بودن قابلیتهای نوشته شده میباشد.
آرگومان bool_java_exceptions نشاندهنده این است که آیا نوع exception رخ داده، به کاربر نشان داده شود یا خیر.
مثال نمونه صحیح:
./tester.sh /var/www/Sharif-Judge/assignments/assignment_1/p1 'wikiuser' 'sum' 'sum-4' cpp 0.5 1 50000
1048576 diff -bB 1 1 1 0 1 0
برای اتصال تسک judge به سیستم جاج کد بالا را درون تسک قرار میدهیم.
فرمت ورودی
به عنوان مثال برنامهای که قرار است در خط اول تعداد اعداد ورودی را بگیرد و در خط بعد اعداد را:
5
4 3 12 186 1
فرمت خروجی
در خروجی تنها یک عدد چاپ میشود که آن خروجی برنامه است. مثلا اگر برنامهای برای محاسبه ماکزیمم چند عدد نوشته شده باشد و تست کیس بالا را به آن بدهیم, در خروجی تنها عدد زیر چاپ میشود:
186
نتیجه اجرای کد
نتیجه نهایی اجرای کد و مقایسه با خروجی صحیح تستکیسها به ۳ صورت نشان داده میشود:
۱ - در دایرکتوری که کد کاربر قرار دارد فایلی به صورت result-##.html ایجاد میشود. یک نمونه خروجی آن به صورت زیر است:
<span class="shj_b">Test 1</span>
<span class="shj_b">ACCEPT</span>
<span class="shj_b">Test 2</span>
<span class="shj_b">WRONG</span>
<span class="shj_b">Test 3</span>
<span class="shj_b">Runtime Error</span>
<span class="shj_b">Test 4</span>
<span class="shj_b">Runtime Error</span>
۲- اگر قابلیت لاگ جاج فعال باشد در فولدری که کد کاربر قرار دارد فایلی به صورت ##-log ایجاد میشود. که در آن اطلاعات مربوط به اجرای هر تست کیس و زمان اجرای کلی نوشته شده است. نمونهای از محتوای این فایل:
cd /var/www/Sharif-Judge/tester;
./tester.sh /var/www/Sharif-Judge/assignments/assignment_1/p1 'mehran' 'sum' 'sum-4' cpp 0.5 1 50000
1048576 diff -bB 1 1 1 0 1 0
Starting tester...
Sat Feb 21 20:39:33 IRST 2015
Language: cpp
Time Limit: 0.5 s
Memory Limit: 50000 kB
Output size limit: 1048576 bytes
EasySandbox: true
C/C++ Shield: true
Compiling as cpp
Enabling EasySandbox
Enabling Shield For C/C++
Compiled. Exit Code=0 Execution Time: 229 ms
Testing...
4 test cases found
=== TEST 1 ===
Exit Code = 0
Time: 0.00 s
ACCEPTED
=== TEST 2 ===
Exit Code = 0
Time: 0.00 s
WRONG
=== TEST 3 ===
Exit Code = 1
Time: 0.00 s
Runtime Error
=== TEST 4 ===
Exit Code = 1
Time: 0.00 s
Runtime Error
Score from 10000: 2500
Total Execution Time: 397 ms
۳- خروجی فایل tester.sh یکی از حالات زیر خواهد بود:
الف ) یک عدد ( امتیاز از ۱۰۰۰۰ )
ب ) خطای کامپایل ( Compilation Error )
ج ) خطای نحوی ( Syntax Error )
د ) خطای در کد تست ( Invalid Tester Code )
ه ) عدم پشتیبانی فایل ( File Format Not Supported )
ی ) خطای جاج ( Judge Error )
روند کلی اجرا روی چند ماشین
در این متد سلری باید روی تمام ورکرها نصب باشد. همچنین روی یک سرور سایت جاج قرار دارد که اطلاعات ورودی کاربر اعم از تستکیسها و کد و … روی آن قرار دارد. روی سرور فرانتاند جاج یک فایل sender.php اجرا میشود که اطلاعات مورد نیاز را برای ورکرها ارسال میکند و روی تمام ورکرها یک فایل reciever.php وجود دارد که این اطلاعات را دریافت میکند. با اجرای فایل receiver.php روی سرور ورکر آن را در حالت انتظار قرار میدهیم:
php receiver.php
فایل reciever.php با اجرای یک کد روی ورکر، تسک جاج را استارت میزند و بدین ترتیب با شروع تسک جاج، کد ارسالشده به سیستم جاج فرستاده میشود. متن فایل reciever:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPConnection;
$connection = new AMQPConnection('ip', 5672, 'username', 'password', 'virtual_host_name');
$channel = $connection->channel();
$channel->queue_declare('email_queue', false, false, false, false);
echo ' * Waiting for messages. To exit press CTRL+C', "\n";
$callback = function($msg){
echo " * Message received", "\n";
$data = json_decode($msg->body, true);
// executing python code to start judge task from tasks.py
// runTask.py :
// from celery import Celery
// result = judge ( 5, 15)
$command = escapeshellcmd('/path/to/runTask.py');
shell_exec($command);
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_qos(null, 1, null);
$channel->basic_consume('email_queue', '', false, false, false, false, $callback);
while(count($channel->callbacks)) {
$channel->wait();
}
?>
قسمتی از این فایل که برای اتصال به جاج باید ویرایش شود کامنتگذاری شده. همچنین اطلاعات مربوط به کانکشن شامل username و password و virtualhost name هم باید اصلاح شود. فایل sender.php هم به این صورت است:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPConnection;
use PhpAmqpLib\Message\AMQPMessage;
$connection = new AMQPConnection('ip', 5672, 'username', 'password', 'virtual_host_name');
$channel = $connection->channel();
$channel->queue_declare('email_queue', false, false, false, false);
$data = json_encode($_POST);
$msg = new AMQPMessage($data, array('delivery_mode' => 2));
$channel->basic_publish($msg, '', 'email_queue');
?>
امکاناتی که باید اضافه شود و درست شوند
در اینجا دو کار باید انجام شود که نمیشود یکی اینکه سلری تسکها را نمیشکند و دو اینکه فایل خروجی جاج باید به سرور فرانتاند جاج به نوعی ارسال شود ولی الان ورکرها فقط نقش دریافتکننده دارند و خروجی جاج درون یک فایل روی worker ذخیره میشود.
فرمت پیشنهادی برای فرانتاند سایت
در روت داکوویکی دایرکتوری به نام data وجود دارد و در آن دایرکتوریهای pages و media هست. داکوویکی به ازای هر صفحه یک فایل با پسوند txt و با نام آدرس آن صفحه در /data/pages ایجاد میکند و متن صفحه به صورت plain text در این فایلها ذخیره میشود. همچنین فایلهایی که توسط کاربر آپلود میشوند در دایرکتوری /media قرار میگیرند.
در ویکی هر سوال یک صفحه مخصوص دارد که صورت سوال در آن نوشته شده و امکان ارسال کد و دیدن خروجی جاج وجود دارد. عنوان این صفحه با عنوان سوال با عنوان فایل txt صورت سوال در دایرکتوری pages با problem id سوال یکی خواهد بود. به ازای هر صفحه ویکی که برای نوشتن صورت سوال ایجاد میشود باید یک صفحه دیگر برای نوشتن تستکیسها و خروجی تستکیسها هم ایجاد شود. اما این صفحه نباید توسط کاربر نهایی از طریق وارد کردن آدرس آن در مرورگر قابل نمایش باشد. (چون قرار نیست کاربر تستکیس ها را ببیند) برای این منظور برای صفحات تستکیس از یک namespace مجزا به نام test: استفاده میکنیم و در بکاند ویکی میگوییم صفحات داخل این نیماسپیس فقط توسط گروه کاربری مجاز قابل مشاهده یا ویرایش باشد. پس به طور خلاصه محل ذخیره شدن صورت سوال به اینصورت است:
/data/pages/problem-id.txt
و محل ذخیره شدن تستکیسها:
/data/pages/tests/problem-id.txt
همچنین یوآرال صورت سوال به اینصورت:
http://example.com/doku.php/problem-id
و آدرس صفحه تستکیسها به اینصورت است:
http://example.com/doku.php/test:problem-id
ممکن است بعضی از تستکیسها سنگین باشند و نشود از قسمت ایجاد صفحه جدید داکوویکی برای نوشتن آن استفاده کرد. در این موارد تستکیس باید به صورت media روی سرور آپلود شود. پس سیستم باید هربار آدرس بالا را چک کند و اگر تستکیسی پیدا نکرد در دایرکتوری /media دنبال تستکیس بگردد.
سمت چپ صفحات dokuwiki یک سری لینک به تاریخچه یا ویرایش صفحه و …. هست. باید به این لینکها، لینک صفحه تستکیس آن سوال هم اضافه شود. یعنی کاربر با یک کلیک به صفحه ایجاد تستکیس برای سوالی که الان داخل صفحهاش هست برود. نکته بعد اینکه تمام اینکارها باید با مثلا اضافه کردن تگ <judge> به صفحات انجام شود. یعنی با اضافه کردن این کیورد به انتهای صفحهای که صورت سوال داخلش توضیح داده شده، ماژول مربوط به ارسال و دریافت کد به صفحه اضافه شود. کدهای ارسالی توسط کاربر باید در یک فایل با نام submissions.txt با این فرمت ذخیره شود:
problem-id, user, path-to-source-code-file
و نتیجه در یک فایل دیگر با نام results.txt و با یک ساختار جدولی به اینصورت:
user, prblem-id, status, ....
موقع سابمیت کردن کد در یک فایل txt ذخیره میشود و بعد کدهای ارسال شده به ترتیب وارد کیو میشوند و اجرا میشوند. هر تسک به صورت یک مسیج داخل این کیو قرار میگیرد و درون آن مشخصات مورد نیاز مانند تستکیسها، prblem-id و file-id قرار میگیرد. درضمن کاربران از سیستم ثبتنام خود سایت استفاده میکنند و موقع ارسال کد باید user id آنها هم همراه کدشان ارسال شود. شاید یک کاربر بخواهد کل کدهای ارسال شدهاش را ببیند برای همین باید یک لینک بالای داکوویکی (کنار لینکهای تغییرات اخیر و …) اضافه شود که با کلیک روی آن بتواند در یک جدول کدهای سابمیت شده و خروجی آنها را ببیند.
کدهای ارسالی توسط کاربر در یک سری فایل در یک دایرکتوری به خصوص که تحت وب در دسترس نیست ذخیره میشوند که مسیر آن فایلها در submissions.txt وجود دارد. دقت کنید این کدها باید درون یک sandbox اجرا شوند که اگر کد آلوده یا مخرب وجود داشت کاری نتواند انجام دهد. اینکار را قبلا sharif judge انجام داده. باید مستندات و سورس شلاسکریپت آن مطالعه شود و روی این سیستم نیز پیادهسازی شود.
توسعهٔ پلاگین
توسعه
به زودی یک نسخه لایو آن آپ میشود.
فهرست مندرجات
پارامترهای submission
موارد زیر در دیتابیس و جدول submissions ذخیره میشوند:
نام پارامتر | توضیحات | داده مربوطه از کجا به دست میآید | مقدار پیشفرض | اختیاری/اجباری |
---|---|---|---|---|
submit_id | شماره یونیک مربوط به هر ارسال کد که از طریقش میشود به اطلاعات آن سابمیشن دست یافت | توسط خود سیستم تولید میشود | auto increment | اجباری |
timestamp | زمان ارسال سابمیشن توسط کاربر | ذخیره کردن زمان حال هنگام ارسال کوئری insert | .now | اجباری |
problem_name | نام یونیک هر سوال که معادل آدرس صفحهای (page) که صورت سوال در آن قرار دارد هست | پارامتر اول syntax فرم جاج | اجباری | |
username | نام کاربری کسی که کد را ارسال کرده | داکو ویکی this user | اجباری | |
language | زبان برنامهنویسی مربوط به submission کاربر | پارامترهای صورت سوال یا انتخاب کاربر هنگام ارسال کد در فرم یا فرمت نام فایل | یکی از مقادیر java یا cpp | اجباری |
type | نوع جاج شدن سوال. اگر صفر بود یعنی تست کیسی است. اگر یک بود output only است | پارامتر مربوطه در syntax فرم جاج | اگر طراح سوال معلوم نکرده بود از نوع تست کیسی است | اجباری |
status_code | وضعیت اجرای کد. صفر به معنی running و یک به معنی done | ابتدا صفر است وقتی جواب حاضر شد یک میشود | صفر | اجباری |
valid_number | تعداد تستکیسهای درست. مثلا ۹ از ۱۰. برای حالت غیرمسابقهای که تعداد تستکیسهای درست سابمیشن مهم است به صورت عدد. در غیراینصورت یک استرینگ نشاندهندهٔ نوع ارور | وقتی جاج شد ست میشود | null | اختیاری |
runtime | مدت زمان اجرای کد سابمیشن برای مواقعی که مهم است | توسط برنامهای که جاج میکند ست میشود | null | اختیاری |
برای دیتابیس از sqlite استفاده کردیم چون همه چیز را درون یک فایل نگه میدارد. دستورات DDL استفاده شده به شرح زیرند:
CREATE TABLE submission
(
sumbit_id INTEGER PRIMARY KEY NOT NULL,
timestamp TEXT NOT NULL,
problem_name TEXT NOT NULL,
username TEXT NOT NULL,
language TEXT NOT NULL,
type INTEGER NOT NULL,
status_code INTEGER DEFAULT 0 NOT NULL,
valid_number INTEGER,
runtime INTEGER
);
سوال: runtime و category آیا لازمند؟ ران تایم لازمه چون شاید سابمیشن ها محدودیت زمانی از نظر الگوریتم داشته باشن. اما کتگوری فعلن نه چون جزو خصوصیات سابمیشن نیست بلکه جزو خصوصیات سواله.
سوال: برای حالتی که مشکل compile time error نداریم، آیا مهمه که هر تست کیس از چه نوعی بوده؟ مثلن یک تست کیس ران تایم ارور بوده یکی غلط بوده جوابش.
پترن
پترن به صورت زیر هست و تگ پایان هم ندارد:
{{judge|parameters}}
چون هم این فرمت با تگ های html و … اشتباه نمیشود و مشابه این فرمت در بقیه فریمورکها هم در بخش مربوط به template کاربرد دارد لذا از نظر معنایی ایده درستی است. هم اینکه با ساختار کلی تگهای بقیه پلاگینهای داکوویکی منطبق است.
خواص پلاگین
۱- از نوع syntax است.
۲- تایپ آن container تعریف شده. خصوصیت بارز container اینست که پلاگین میتواند درون تگهای listblock و table و quote و hr قرار بگیرد. یعنی پلاگین مثلن نمیتواند در تگهای فرمتر متن مثل bold و … یا بقیه حالات ممکن کار کند.
۳- نحوه ارتباط آن با پاراگراف block هست به این معنی که در خروجی html صفحه، قبل از شروع کد مربوط به پلاگین، تگ خاتمه پاراگراف قبل از آن و تگ شروع پارگراف بعد از آن قرار میگیرد. یعنی کد پلاگین بین پاراگراف یا در حالت دیگری نسبت به تگهای پاراگراف نیست.
۴- اولویت آن فعلا ۱۰ تعریف شده ولی این عدد زمانی مهم است که دو پلاگین مختلف برای یک pattern داشته باشیم و بخواهیم اولویت اجرای آنها را مشخص کنیم.
پارامترهای سوال
پارامترهای پترن سوال
پارامترها در پترنی مشابه مثال زیر مشخص میشوند. این موارد باید توسط طراح سوال تعیین شوند. ترتیب مشخص شدن موارد یا نوشتن key قبل از هر کدام از پارامترها الزامی نیست.
{{judge|problem:problem_name type:output-only time:10 lang:java}}
یک ایده اینست که problem_name را از روی url صفحهای که کد پلاگین درون آن قرار گرفته بگیریم. ولی این ایده خوب نیست چون انعطافپذیری سیستم را کم میکند و نمیشود در هر صفحهای خواستیم از پلاگین استفاده کنیم. پس بهترین ایده همینست که یک id برای این موضوع در نظر بگیریم و هر جا خواستیم پارامتر فوق را ست کنیم. اما این آیدی میتواند نام فایل txt صورت سوال و تستکیس آن باشد تا درصورت نیاز به آدرس صفحه سوال یا تستکیس، بشود از آن استفاده کرد. برای hint هم لازم نیست یک پترن جدا ایجاد کنیم. به صورت جاوا اسکریپت متن hint را میشود با کلیک روی یک کلید نشان داد. همچنین صورت سوال یا تستکیسها را هم نمیشود به صورت پارامتر از کاربر گرفت چون پلاگین فوق روی دیتابیس ادیت انجام نمیدهد و نباید عمل insert یا delete روی آن انجام دهد و این وظیفه صفحات است. چون این پلاگین ذاتن از نوع syntax است.
نحوه جداسازی پارامترها استفاده از کاراکتر فاصله بین آنها است. میشد از & هم استفاده کرد ولی باعث شلوغ شدن بصری سینتکس میشد.
تا اینجا پلاگین با پارامترهای مذکور عمل ایجاد فرم سابمیت کد را انجام میدهد. اما برای پراسس submissionها کار بیشتری لازم است. در این رابطه باید پارامترهای بیشتری را دریافت کرد ولی هیچ کدام از این پارامترها لازم نیست توسط طراح سوال وارد شوند. اینکه هر پارامتر هنگام اضافه شدن به دیتایبس از کجا میآید در جدول مربوطه آمده است.
نام key | توضیحات | مقادیر ممکن برای پارامتر | مقدار پیشفرض |
---|---|---|---|
problem | عنوان صفحه صورت سوال | همیشه اولین پارامتر باید باشد | ندارد و باید حتما توسط کاربر مشخص شود |
type | نوع سوال | test-case و output-only | اگر مشخص نشود یعنی سوال از نوع تست کیسی است |
time | محدودیت زمان اجرای سوال | یک عدد | اگر مشخص نشود یعنی پاسخ سوال محدودیت زمانی اجرا ندارد |
lang | محدودیت نداریم و بسته به فرمت فایل ارسالی کاربر زبان مشخص میشود | java و cpp و python | اگر مشخص نشود یعنی پاسخ سوال محدودیت زمانی اجرا ندارد |
راهنمای نصب
sudo apt-get install php5-sqlite
service apache2 restart