aboutsummaryrefslogblamecommitdiffstats
path: root/toj/php/problem.inc.php
blob: d4c8e451940857993d71560f97998e5350a30ad7 (plain) (tree)




































































































































                                                                                                                                                                                                    
                                                                      
 












                                                             





                                 

                                                                                                                           
                                                                              









                                                       
                                              
                                                  



























                                                                                                                             































                                                                                          
                                              



















































                                                                                                              
 





























                                                                                   







                                                                                    





                                                                                                        


                                  
                                                         











                                                                   




                                                                                                        
                                            
     



  
<?php
require_once('common.inc.php');
require_once('user.inc.php');
require_once('square.inc.php');

const PRONAME_LEN_MAX = 100;

const CODE_LEN_MIN = 1;
const CODE_LEN_MAX = 102400;

const SUBMIT_MIN_INTERVAL = 10;

$LANGUAGE = array(0x1=>'C/C++', 0x2=>'JAVA', 0x4=>'Pascal');
$EXTENSION = array(0x1=>'cpp', 0x2=>'java', 0x4=>'pas');

class problem
{
    public $proid;
    public $modid;
    public $proname;
    public $hidden;

    public static function getmod($sqlc, $modid)
    {
        //return pmodname, smodname, jmodname for specified $modid.
        //False if not found.
        $result = pg_query_params($sqlc, 'SELECT * FROM "mod" WHERE "modid"=$1 LIMIT 1;', array($modid));
        $mret = pg_fetch_object($result);
        pg_free_result($result);
        if(!$mret)
            return false;
        return $mret;
    }
    public static function get($sqlc, $proid)
    {
        //return problem data: proid, modid, proname, pmodname, smodname, jmodname
        //False if not found.
        $result = pg_query_params($sqlc, 'SELECT * FROM "problem" WHERE "proid"=$1 LIMIT 1;', array(intval($proid))) or die ("Eerror_get_problem");
        $ret = pg_fetch_object($result, null, 'problem');
        pg_free_result($result);
        if(!$ret)
            return false;
        
        $ret->proid = intval($ret->proid);
        $ret->modid = intval($ret->modid);
        $ret->admin_uid = intval($ret->admin_uid);

        $mret = problem::getmod($sqlc, $ret->modid);
        if(!$mret)
            return false;

        $ret->pmodname = $mret->pmodname;
        $ret->smodname = $mret->smodname;
        $ret->jmodname = $mret->jmodname;
        
        return $ret;    
    }
    
    public static function is_available($sqlc, $proid, $uid = null)
    {
        //return whether the problem is available for user $_COOKIE['uid'] or not.
        //USER_PER_PROADMIN always OK
        //admin of problem always OK
        //if HIDDEN , then NOT OK except admins
        //in sqid=1 always OK , even if not login
        //otherwise must exist at least one common square with relationship >= SQUARE_USER_ACTIVE
        $uidnull = false;
        if($uid == null)
        {
            $uid = intval($_COOKIE['uid']);
            $uidnull = true;
        }
        $sqlr = pg_query_params('SELECT "hidden", "admin_uid" FROM "problem" WHERE "proid"=$1;', array($proid));
        $obj = pg_fetch_object($sqlr);
        $hdn = $obj->hidden;
        if($hdn == null)
            return false; // no such problem    

        if(sec_check_level($sqlc, USER_PER_PROADMIN, $uidnull?null:$uid))
            return true;

        if((!$uidnull || sec_is_login()) && $uid == intval($obj->admin_uid))
            return true;

        if($hdn == "t")
            return false;

        $sqlstr = 'SELECT COUNT(*) FROM "pro_sq" WHERE "proid"=$1 AND "sqid"=$2;';
        $sqlarr = array($proid, 1);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        $ret = intval(pg_fetch_result($sqlr, 0));
        if($ret > 0)
            return true;

        if($uidnull && !sec_is_login())
            return false;

        $sqlstr = 'SELECT COUNT("pro_sq"."sqid") FROM "pro_sq" INNER JOIN "us_sq" ON "pro_sq"."sqid"="us_sq"."sqid" WHERE "pro_sq"."proid"=$1 AND "us_sq"."uid"=$2 AND "us_sq"."relationship">=$3;';
        $sqlarr = array($proid, $uid, SQUARE_USER_ACTIVE);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        $ret = intval(pg_fetch_result($sqlr, 0));
        if($ret > 0)
            return true;

        return false;
    }

    public static function submit($sqlc, $proid, $uid, $lang, $code)
    {
        //Submit code(or data) : $proid, $uid, $lang, $code
        //Return subid. False if failed.

        ////$submit_time = date('Y-m-d H:i:s');
        ////$last_update = $submit_time;
        $sqlstr = 'INSERT INTO "submit" ("proid", "uid", "lang") VALUES ($1, $2, $3) RETURNING subid;';
        $sqlarr = array($proid, $uid, $lang);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        $subid = intval(pg_fetch_result($sqlr, 0));
        if(!$subid)
            return false;
        
        global $EXTENSION;
        $ext = $EXTENSION[intval($lang)];
        if($ext == null)
            die('Ewrong_extension');

        $parnum = $subid - ($subid%1000);
        $pardir = '../center/submit/'.$parnum.'/';
        if(!is_dir($pardir))
            mkdir($pardir, 0755) or die('Ecannot_mkdir');
        mkdir($pardir.$subid, 0755) or die('Ecannot_mkdir');    
        mkdir($pardir.$subid.'/data', 0755) or die('Ecannot_mkdir');
        mkdir($pardir.$subid.'/result', 0755) or die('Ecannot_mkdir');
        chmod($pardir.$subid.'/result', 0775) or die('Ecannot_chmod');

        $file = fopen($pardir.$subid.'/data/main.'.$ext,'w');
        if(!$file)
            die('Ewrite_file_failed');
        fwrite($file, $code);
        fclose($file);

        return $subid;
    }

    public static function add($sqlc, $pro)
    {
        //Add a new problem $pro into problem table.
        //Return the inserted object. False if failed.
        
        if($pro->hidden == true){
            $hidden = 't';
        }else{
            $hidden = 'f';
        }

        $sqlstr = 'INSERT INTO "problem" ("modid", "proname", "hidden", "admin_uid") VALUES ($1, $2, $3, $4) RETURNING *;';
        $sqlarr = array($pro->modid, $pro->proname, $hidden, $pro->admin_uid);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        if(!$sqlr)
            return false;
        $obj = pg_fetch_object($sqlr, null, 'problem');
        pg_free_result($sqlr);
        if(!$obj)
            return false;

        $obj->proid = intval($obj->proid);
        $obj->modid = intval($obj->modid);
        $obj->cacheid = intval($obj->cacheid);
        $obj->admin_uid = intval($obj->admin_uid);
        $obj->hidden = ($obj->hidden=='t');

        return $obj;
    }

    public static function edit($sqlc, $pro)
    {
        if($pro->hidden == true){
            $hidden = 't';
        }else{
            $hidden = 'f';
        }

        $sqlstr = 'UPDATE "problem" SET "modid"=$1, "proname"=$2, "hidden"=$3, "admin_uid"=$4 WHERE "proid"=$5 RETURNING *;';
        $sqlarr = array($pro->modid, $pro->proname, $hidden, $pro->admin_uid,$pro->proid);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        if(!$sqlr)
            return false;
        $obj = pg_fetch_object($sqlr, null, 'problem');
        pg_free_result($sqlr);
        if(!$obj)
            return false;

        $obj->proid = intval($obj->proid);
        $obj->modid = intval($obj->modid);
        $obj->cacheid = intval($obj->cacheid);
        $obj->admin_uid = intval($obj->admin_uid);
        $obj->hidden = ($obj->hidden=='t');

        return $obj;
    }
    
    public static function mod_get_lang($sqlc, $modid)
    {
        //get available language code (OR) format
        //return language code

        $sqlstr = 'SELECT "lang" FROM "mod" WHERE "modid"=$1;';
        $sqlarr = array($modid);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        $ret = pg_fetch_result($sqlr, 0);
        pg_free_result($sqlr);
        if(!$ret)
            return false;
        return intval($ret);
    }

    public static function recent_submit($sqlc, $uid, $time)
    {
        //return submission number in recent $time seconds.
        $lasttime = date('Y-m-d H:i:s', time()-$time);
        $sqlstr = 'SELECT COUNT(*) FROM "submit" WHERE "uid"=$1 AND "submit_time" >= $2;';
        $sqlarr = array($uid, $lasttime);
        $sqlr = pg_query_params($sqlstr, $sqlarr);
        $ret = pg_fetch_result($sqlr, 0);
        if(!$ret)
            return false;
        return intval($ret);
    }    

    public static function send_socket($subid)
    {
        ///send socket to center.
        //Return true if success, false if failed.

        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        $sconn = socket_connect($socket, '127.0.0.1', CENTER_SOCKET_PORT);

        if(!$sconn)
            return false;

        $wret = socket_write($socket, $subid.chr(0).'{}'.chr(0));
        if($wret === false)
            return false;


        $cret = socket_read($socket, 1024);
        if($cret === false)
            return false;
        if($cret[0] != 'S')
            return false;
        return true;
    }

    public static function get_pro_stat($sqlc, $proid, $uid)
    {
        //get $uid 's score and is_ac of problem $proid.
        
        $ret = new stdClass();

        $sqlstr = 'SELECT COUNT(*) FROM "submit" WHERE "proid"=$1 AND "uid"=$2 AND "result"=0;';
        $sqlarr = array($proid, $uid);
        $res = pg_query_params($sqlc, $sqlstr, $sqlarr);
        $acct = pg_fetch_result($res, 0);
        $ret->is_ac = ($acct > 0);

        $sqlstr = 'SELECT "score" FROM "submit" WHERE "proid"=$1 AND "uid"=$2 ORDER BY "score" DESC LIMIT 1;';
        $sqlarr = array($proid, $uid);
        $res = pg_query_params($sqlc, $sqlstr, $sqlarr);
        $score = pg_fetch_result($res, 0);
        if($score === false)
        {
            $ret->tried = false;
            $ret->score = 0;
        }
        else
        {
            $ret->tried = true;
            $ret->score = $score;
        }

        return $ret;
    }

    public static function get_pro_list($sqlc){
        $sqlstr = 'SELECT * FROM "problem" ORDER BY "proid" ASC;';
        $sqlr = pg_query($sqlc,$sqlstr);

        $ret = array();
        while($obj = pg_fetch_object($sqlr))
        {
            $obj->proid = intval($obj->proid);
            $obj->modid = intval($obj->modid);
            $obj->cacheid = intval($obj->cacheid);
            $obj->admin_uid = intval($obj->admin_uid);
            $obj->hidden = ($obj->hidden=='t');
            array_push($ret, $obj);
        }

        pg_free_result($sqlr);
        return $ret;
    }

    public static function update_pro_cache($sqlc,$proid){
        $sqlstr = 'UPDATE "problem" SET "cacheid"="cacheid" + 1 WHERE "proid"=$1;';
        $sqlarr = array($proid);
        $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr);
        if(!$sqlr)return false;
        pg_free_result($sqlr);

        if(!problem::send_socket(-1))return false;
        else return true;
    }

    public static function rejudge_pro($sqlc, $proid)
    {
        $sqlstr = 'SELECT "subid" FROM "submit" WHERE "proid"=$1 ORDER BY "subid";';
        $sqlarr = array($proid);
        $res = pg_query_params($sqlc, $sqlstr, $sqlarr);
        $ok = true;
        $sublist = pg_fetch_all_columns($res, 0);
        if(!$sublist)return false;

        $sqlstr = 'UPDATE "submit" SET "result"=100,"runtime"=0,"memory"=0,"score"=0 WHERE "proid"=$1;';
        $sqlarr = array($proid);
        $res = pg_query_params($sqlc, $sqlstr, $sqlarr);
        pg_free_result($res);

        foreach($sublist as $sub)
        {
            $subid = intval($sub);
            if(!problem::send_socket($subid))$ok = false;
        }
        return $ok;
    }

    public static function rejudge_sub($sqlc, $subid)
    {
        $sqlstr = 'SELECT "proid" FROM "submit" WHERE "subid"=$1;';
        $sqlarr = array($subid);
        $res = pg_query_params($sqlc, $sqlstr, $sqlarr);
        $proid = intval(pg_fetch_result($res, 0));
        if(!$proid)return false;

        $sqlstr = 'UPDATE "submit" SET "result"=100,"runtime"=0,"memory"=0,"score"=0 WHERE "subid"=$1;';
        $sqlarr = array($subid);
        $res = pg_query_params($sqlc, $sqlstr, $sqlarr);
        pg_free_result($res);

        return problem::send_socket($subid);
    }
}


?>